diff --git a/script-meta-v2.json b/script-meta-v2.json index cef6b5a..be00e41 100644 --- a/script-meta-v2.json +++ b/script-meta-v2.json @@ -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, diff --git a/single-scripts/publickey.ts b/single-scripts/publickey.ts index 038eff0..1b12cc0 100755 --- a/single-scripts/publickey.ts +++ b/single-scripts/publickey.ts @@ -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 "); diff --git a/single-scripts/ssh-verify.ts b/single-scripts/ssh-verify.ts new file mode 100755 index 0000000..858917c --- /dev/null +++ b/single-scripts/ssh-verify.ts @@ -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 +`); + 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 = 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."); +}