-
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathdecryptKeyPart.ts
More file actions
101 lines (95 loc) · 3.3 KB
/
decryptKeyPart.ts
File metadata and controls
101 lines (95 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env node
import { spawn } from "node:child_process";
import { once } from "node:events";
import { argv, env, exit, stdin, stdout } from "node:process";
import * as yaml from "js-yaml";
import type { VoteFileFormat } from "@node-core/caritat/parser";
import runChildProcessAsync from "../utils/runChildProcessAsync.js";
if (argv.length > 3 && argv[3] !== "--post-comment") {
console.warn("Unknown flag:", argv[3]);
argv[2] = "-h"; // print help message
}
let yamlString: string;
if (argv[2] === "-h" || argv[2] === "--help") {
console.log("Usage:");
console.log("decryptKeyPath < path/to/vote.yml");
console.log("curl -L http://example.com/vote.yml | decryptKeyPath | base64");
console.log(
"decryptKeyPath https://github.com/owner/repo/pull/1 # requires gh CLI tool"
);
console.log(
"decryptKeyPath https://github.com/owner/repo/pull/1 --post-comment # requires gh CLI tool"
);
console.log(
"Upon success, this tool will output to stdout a base64 representation of the decrypted key part."
);
exit(0);
} else if (argv[2]) {
//github.com/stduhpf/pleaseignore/raw/15f8e6ae5d2c417d7bc68ec1ea6db35d00cc263c/voteTest/nodejstest/vote.yml
const gh_PR_URL =
/^https?:\/\/github.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/.exec(argv[2]);
if (gh_PR_URL == null) throw new Error("Invalid PR URL format");
const [, owner, repo, prId] = gh_PR_URL;
const filesData = JSON.parse(
await runChildProcessAsync(
env.GH_BIN || "gh",
[
"api",
"-H",
"Accept: application/vnd.github+json",
`/repos/${owner}/${repo}/pulls/${prId}/files`,
],
{ captureStdout: true }
)
);
const { contents_url } = filesData.find(({ filename }) =>
/(^|\/)vote.yml$/.test(filename)
);
yamlString = await runChildProcessAsync(
env.GH_BIN || "gh",
["api", "-H", "Accept: application/vnd.github.raw", contents_url],
{ captureStdout: true }
);
} else {
yamlString = (await stdin.toArray()).join();
}
const { shares } = yaml.load(yamlString) as VoteFileFormat;
const ac = new AbortController();
const gpgParams = (process.env.CARITAT_GPG_PARAMS ?? "").split(/\s/g);
const out = await Promise.any(
shares.map(async (share) => {
const cp = spawn(env.GPG_BIN || "gpg", ["-d", ...gpgParams], {
stdio: [
"pipe",
"pipe",
process.env.CARITAT_SHOW_ERRORS ? "inherit" : "ignore",
],
signal: ac.signal,
});
const stdout = cp.stdout.toArray();
// @ts-expect-error potential errors would be handled below
stdout.catch(Function.prototype);
cp.stdin.end(share);
const [code] = await Promise.race([
once(cp, "exit"),
once(cp, "error").then((er) => Promise.reject(er)),
]);
if (code !== 0) throw new Error("failed", { cause: code });
return Buffer.concat(await stdout);
})
);
ac.abort();
if (argv[3] === "--post-comment") {
await runChildProcessAsync(env.GH_BIN || "gh", [
"pr",
"comment",
argv[2],
"-b",
`I would like to close this vote, and for this effect, I'm revealing my ` +
`key part:\n\n${"```"}\n-----BEGIN SHAMIR KEY PART-----\n${out.toString(
"base64"
)}\n-----END SHAMIR KEY PART-----\n${"```"}\n`,
]);
} else {
stdout.write(out);
}