feat: add ssh-verify.ts

This commit is contained in:
2025-01-19 15:20:34 +08:00
parent eb6357f6bb
commit d3604ea8eb
3 changed files with 106 additions and 2 deletions

View File

@@ -28,7 +28,7 @@
"publickey.ts": {
"script_name": "publickey.ts",
"script_length": 1572,
"script_sha256": "7910b0d8c727a5d8cefa0174d19b0e6e7925dc3960dbe3625735f4a55f7180e2",
"script_sha256": "83947c19952ef8f69f50354b809bc584e4ff702a663364c9572db8a0bb32cc8e",
"script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/single-scripts/publickey.ts",
"single_script_file": true
},
@@ -38,6 +38,13 @@
"script_sha256": "0371be7620d5aa2607a5ed1a9b45e2664b5c27ee163966a681e630d568c4a445",
"script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/sigstore-verify-ts/main.ts"
},
"ssh-verify.ts": {
"script_name": "ssh-verify.ts",
"script_length": 2708,
"script_sha256": "c8ffa0e730db27046f4fdc2c7946e53eb3f4209f663374b60b64521957218a43",
"script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/single-scripts/ssh-verify.ts",
"single_script_file": true
},
"wget.ts": {
"script_name": "wget.ts",
"script_length": 3848,

View File

@@ -5,7 +5,7 @@
// - https://docs.deno.com/api/node/crypto/~/X509Certificate#property_issuercertificate
// - https://docs.deno.com/api/node/crypto/~/createPublicKey
const {X509Certificate, createPublicKey} = await import('node:crypto');
const {X509Certificate, createPublicKey} = await import("node:crypto");
if (Deno.args.length === 0) {
console.log("Usage: publickey.ts <certificate|publickey|jwk>");

97
single-scripts/ssh-verify.ts Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env -S deno run --allow-env --allow-import --allow-read --allow-net
import { parseArgs } from "jsr:@std/cli/parse-args";
import {
fetchKeys,
SshKey,
} from "https://hatter.ink/script/fetch/library/deno-github-mod.ts?202501191443";
import {
SshSignature,
} from "https://hatter.ink/script/fetch/library/deno-sshsig-mod.ts?202501191510";
const flags = parseArgs(Deno.args, {
boolean: ["help", "debug"],
string: ["username"],
});
if (Deno.args.length === 0) {
console.log("ssh-verify.ts --help for help");
Deno.exit(1);
}
if (flags.help) {
console.log(`ssh-verify.ts - SSH verify tool
ssh-verify.ts --help
ssh-verify.ts --username <github-username> <filename>
`);
Deno.exit(0);
}
if (flags._.length === 0) {
console.log("Requires filename.");
Deno.exit(1);
}
const filename = flags._[0] as string;
const sshSigFilename = `${filename}.sshsig`;
if (flags.debug) {
console.log(`SSH signature file: ${sshSigFilename}`);
}
const sshSignature = await SshSignature.parseFile(sshSigFilename);
const verifyResult = await sshSignature.verifyFile(filename);
if (!verifyResult) {
console.log(
`[ERROR] Verify ${filename}, signature: ${sshSigFilename} failed.`,
);
Deno.exit(1);
}
const sshPublicKey = sshSignature.publicKey;
const sshPublicKeyRawBase64 = sshSignature.publicKey.asRawBase64();
const sshPublicKeySshFormat = sshPublicKey.toSshKeyFormat();
console.log(`[SUCCESS] File ${filename} verify success.`);
console.log(`[SUCCESS] Signing SSH key: ${sshPublicKeySshFormat}`);
if (flags.username) {
let matches = false;
try {
console.log(`[INFO] Fetch SSH keys for user: ${flags.username}`);
const keys: Array<SshKey> = await fetchKeys(flags.username);
if (flags.debug) {
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
console.log(
`[DEBUG] Found SSH key: ${key.algorithm} ${key.material}`,
);
}
}
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key.material == sshPublicKeyRawBase64) {
matches = true;
break;
}
}
} catch (e) {
console.error(
`[ERROR] Fetch SSH keys for ${flags.username} failed: ${e}`,
);
}
if (matches) {
console.log(
`[SUCCESS] SSH key matches for GitHub user: ${flags.username} success.`,
);
} else {
console.log(
`[ERROR] SSH key NOT matched for GitHub user: ${flags.username}.`,
);
}
} else {
console.log("[WARN] GitHub user is not assigned.");
}