@ai-dossier/core 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -2
- package/dist/agent-usage.d.ts +103 -0
- package/dist/agent-usage.d.ts.map +1 -0
- package/dist/agent-usage.js +493 -0
- package/dist/agent-usage.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/run-log-entry.d.ts +88 -0
- package/dist/run-log-entry.d.ts.map +1 -0
- package/dist/run-log-entry.js +50 -0
- package/dist/run-log-entry.js.map +1 -0
- package/dist/signature.d.ts +87 -0
- package/dist/signature.d.ts.map +1 -1
- package/dist/signature.js +189 -28
- package/dist/signature.js.map +1 -1
- package/dist/signing-payload.d.ts +19 -1
- package/dist/signing-payload.d.ts.map +1 -1
- package/dist/signing-payload.js +90 -30
- package/dist/signing-payload.js.map +1 -1
- package/package.json +1 -1
package/dist/signature.js
CHANGED
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
* supporting multiple signature schemes (Ed25519 and AWS KMS).
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.parseTrustedKeys = parseTrustedKeys;
|
|
10
|
+
exports.reportTrustedKeyProblems = reportTrustedKeyProblems;
|
|
11
|
+
exports.trustedKeysFromContent = trustedKeysFromContent;
|
|
9
12
|
exports.loadTrustedKeys = loadTrustedKeys;
|
|
13
|
+
exports.isKmsKeyIdentifier = isKmsKeyIdentifier;
|
|
14
|
+
exports.findTrustedIdentifier = findTrustedIdentifier;
|
|
10
15
|
exports.verifyWithEd25519 = verifyWithEd25519;
|
|
11
16
|
exports.verifyWithKms = verifyWithKms;
|
|
12
17
|
exports.verifySignature = verifySignature;
|
|
@@ -18,6 +23,141 @@ const signers_1 = require("./signers");
|
|
|
18
23
|
const signing_payload_1 = require("./signing-payload");
|
|
19
24
|
const crypto_1 = require("./utils/crypto");
|
|
20
25
|
const fs_1 = require("./utils/fs");
|
|
26
|
+
/** Whether a line reads as an entry in its own right. */
|
|
27
|
+
function looksLikeKeyEntry(line) {
|
|
28
|
+
const parts = line.trim().split(/\s+/);
|
|
29
|
+
return parts.length >= 2 && (0, signing_payload_1.isSupportedPublicKey)(parts[0]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Split a trusted-keys file into `<public-key> <key-id>` pairs.
|
|
33
|
+
*
|
|
34
|
+
* One entry per line, except for PEM blocks: `dossier keys add` used to write its
|
|
35
|
+
* argument verbatim, so passing a PEM appended four lines that a line-oriented
|
|
36
|
+
* parse then shredded into entries matching nothing. Those blocks are rejoined so
|
|
37
|
+
* an already written file works without hand-editing — this only reassembles what
|
|
38
|
+
* the user wrote, it cannot widen a match.
|
|
39
|
+
*
|
|
40
|
+
* This is the single definition of what the trusted-key file format is: anything
|
|
41
|
+
* that lists, counts, or matches trusted keys must go through it, so `keys list`
|
|
42
|
+
* can never disagree with what verification actually trusts.
|
|
43
|
+
*
|
|
44
|
+
* Skipped lines come back alongside the entries rather than being dropped: every
|
|
45
|
+
* skip is a key the user thinks is trusted and isn't, so callers that can show
|
|
46
|
+
* the user something — `keys list`, and verification via `loadTrustedKeys` —
|
|
47
|
+
* report them instead of failing mute.
|
|
48
|
+
*/
|
|
49
|
+
function parseTrustedKeys(content) {
|
|
50
|
+
const entries = [];
|
|
51
|
+
const problems = [];
|
|
52
|
+
const lines = content.split('\n');
|
|
53
|
+
for (let i = 0; i < lines.length; i++) {
|
|
54
|
+
const line = lines[i].trim();
|
|
55
|
+
if (!line || line.startsWith('#')) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!line.startsWith('-----BEGIN')) {
|
|
59
|
+
const parts = line.split(/\s+/);
|
|
60
|
+
if (parts.length >= 2) {
|
|
61
|
+
entries.push({ publicKey: parts[0], keyId: parts.slice(1).join(' ') });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
problems.push({
|
|
65
|
+
line: i + 1,
|
|
66
|
+
message: 'public key has no identifier — expected "<public-key> <identifier>"',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const blockStart = i;
|
|
72
|
+
const block = [line];
|
|
73
|
+
while (i + 1 < lines.length && !block[block.length - 1].includes('-----END')) {
|
|
74
|
+
i++;
|
|
75
|
+
block.push(lines[i].trim());
|
|
76
|
+
}
|
|
77
|
+
// The identifier trails the END marker, or sits on the next line when the
|
|
78
|
+
// PEM carried its own trailing newline.
|
|
79
|
+
const endLine = block[block.length - 1];
|
|
80
|
+
const endMarker = /-----END [^-]*-----/.exec(endLine);
|
|
81
|
+
if (!endMarker) {
|
|
82
|
+
// The scan above ran to end-of-file looking for the END marker, so every
|
|
83
|
+
// later entry was swallowed with it. Say so explicitly: otherwise one
|
|
84
|
+
// truncated paste revokes trust for the whole file with no visible cause.
|
|
85
|
+
problems.push({
|
|
86
|
+
line: blockStart + 1,
|
|
87
|
+
message: 'public key block has no "-----END" marker — this block and every entry after it were ignored',
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
let keyId = endLine.slice(endMarker.index + endMarker[0].length).trim();
|
|
92
|
+
// Drop the identifier back off the END line, so the reassembled block is a
|
|
93
|
+
// bare PEM. Key parsing requires one block and nothing around it — trailing
|
|
94
|
+
// text would make this key unreadable and therefore untrusted.
|
|
95
|
+
block[block.length - 1] = endLine.slice(0, endMarker.index + endMarker[0].length);
|
|
96
|
+
// Only adopt the next line as the identifier when it is not plainly an entry
|
|
97
|
+
// of its own, or a bare PEM block would swallow the key that follows it.
|
|
98
|
+
if (!keyId && i + 1 < lines.length && !looksLikeKeyEntry(lines[i + 1])) {
|
|
99
|
+
i++;
|
|
100
|
+
keyId = lines[i].trim();
|
|
101
|
+
}
|
|
102
|
+
if (keyId) {
|
|
103
|
+
entries.push({ publicKey: block.join('\n'), keyId });
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
problems.push({
|
|
107
|
+
line: blockStart + 1,
|
|
108
|
+
message: 'public key block has no identifier after the "-----END" marker — entry ignored',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { entries, problems };
|
|
113
|
+
}
|
|
114
|
+
/** Cap on printed problems, so a mangled file cannot flood every verify run. */
|
|
115
|
+
const MAX_REPORTED_TRUSTED_KEY_PROBLEMS = 3;
|
|
116
|
+
/**
|
|
117
|
+
* Print unusable trusted-key entries to stderr, bounded.
|
|
118
|
+
*
|
|
119
|
+
* `loadTrustedKeys` runs on every `dossier verify`, so this stays silent unless
|
|
120
|
+
* the file is genuinely malformed — and a malformed trust file is precisely when
|
|
121
|
+
* the user needs to hear about it.
|
|
122
|
+
*/
|
|
123
|
+
function reportTrustedKeyProblems(problems, source) {
|
|
124
|
+
if (problems.length === 0) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const where = source ? ` in ${source}` : '';
|
|
128
|
+
console.warn(`Warning: ${problems.length} unusable trusted-key entry(s)${where}:`);
|
|
129
|
+
for (const problem of problems.slice(0, MAX_REPORTED_TRUSTED_KEY_PROBLEMS)) {
|
|
130
|
+
console.warn(` line ${problem.line}: ${problem.message}`);
|
|
131
|
+
}
|
|
132
|
+
if (problems.length > MAX_REPORTED_TRUSTED_KEY_PROBLEMS) {
|
|
133
|
+
console.warn(` ...and ${problems.length - MAX_REPORTED_TRUSTED_KEY_PROBLEMS} more`);
|
|
134
|
+
}
|
|
135
|
+
console.warn(' Those keys are NOT trusted. Re-add each with: ai-dossier keys add <public-key> <identifier>');
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Build the trusted-key map from the contents of a trusted-keys file.
|
|
139
|
+
*
|
|
140
|
+
* Keys are indexed under both the form they were written in and their normalized
|
|
141
|
+
* form, so a key registered in one encoding still matches a signature that
|
|
142
|
+
* carries another.
|
|
143
|
+
*
|
|
144
|
+
* @param source - Path named in warnings about unusable entries. Omit to stay silent.
|
|
145
|
+
*/
|
|
146
|
+
function trustedKeysFromContent(content, source) {
|
|
147
|
+
const keys = new Map();
|
|
148
|
+
const { entries, problems } = parseTrustedKeys(content);
|
|
149
|
+
for (const { publicKey, keyId } of entries) {
|
|
150
|
+
keys.set(publicKey, keyId);
|
|
151
|
+
const normalized = (0, signing_payload_1.normalizePublicKey)(publicKey);
|
|
152
|
+
if (normalized !== publicKey) {
|
|
153
|
+
keys.set(normalized, keyId);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (source) {
|
|
157
|
+
reportTrustedKeyProblems(problems, source);
|
|
158
|
+
}
|
|
159
|
+
return keys;
|
|
160
|
+
}
|
|
21
161
|
/**
|
|
22
162
|
* Load trusted keys from file
|
|
23
163
|
* Default location: ~/.dossier/trusted-keys.txt
|
|
@@ -25,37 +165,58 @@ const fs_1 = require("./utils/fs");
|
|
|
25
165
|
*/
|
|
26
166
|
function loadTrustedKeys(filePath) {
|
|
27
167
|
const keysPath = filePath || (0, node_path_1.join)((0, node_os_1.homedir)(), '.dossier', 'trusted-keys.txt');
|
|
28
|
-
const keys = new Map();
|
|
29
168
|
const content = (0, fs_1.readFileIfExists)(keysPath);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
169
|
+
// Pass the path so unusable entries name the file the user has to fix.
|
|
170
|
+
return content ? trustedKeysFromContent(content, keysPath) : new Map();
|
|
171
|
+
}
|
|
172
|
+
/** The algorithm `KmsVerifier` claims, whose key material is the KMS key ARN. */
|
|
173
|
+
const KMS_ALGORITHM = 'ECDSA-SHA-256';
|
|
174
|
+
function isKmsAlgorithm(algorithm) {
|
|
175
|
+
return algorithm === KMS_ALGORITHM;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Whether a string identifies an AWS KMS key, and so is a usable trust-list entry
|
|
179
|
+
* for a KMS-signed dossier.
|
|
180
|
+
*/
|
|
181
|
+
function isKmsKeyIdentifier(value) {
|
|
182
|
+
return /^arn:aws[a-z-]*:kms:/.test(value.trim());
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Resolve the identifier a signature is trusted under, or `undefined` if none of
|
|
186
|
+
* its key forms appear in the trust list.
|
|
187
|
+
*
|
|
188
|
+
* The signature and the trust list need not agree on encoding, so every form the
|
|
189
|
+
* *verifying* key carries is tried: the public key as written and normalized to
|
|
190
|
+
* raw base64. Every trust decision goes through here so "is it trusted" and "who
|
|
191
|
+
* is it" can never drift apart.
|
|
192
|
+
*
|
|
193
|
+
* Only the key material the verifier actually used is eligible, which is decided
|
|
194
|
+
* by the algorithm, not by which fields happen to be populated. `KmsVerifier`
|
|
195
|
+
* verifies against `key_id` and ignores `public_key` — which KMS signatures carry
|
|
196
|
+
* anyway — so for KMS only `key_id` can confer trust. Everything else verifies
|
|
197
|
+
* against `public_key`, so only that may.
|
|
198
|
+
*
|
|
199
|
+
* Letting a field the verifier ignored confer trust would hand it out for free:
|
|
200
|
+
* the trust list is keyed by public key and public keys are public, so an Ed25519
|
|
201
|
+
* dossier carrying `key_id: "<any trusted public key>"` would be trusted as that
|
|
202
|
+
* signer while verifying under an attacker's `public_key`.
|
|
203
|
+
*/
|
|
204
|
+
function findTrustedIdentifier(trustedKeys, signature) {
|
|
205
|
+
const candidates = isKmsAlgorithm(signature.algorithm)
|
|
206
|
+
? [signature.key_id]
|
|
207
|
+
: signature.public_key
|
|
208
|
+
? [signature.public_key, (0, signing_payload_1.normalizePublicKey)(signature.public_key)]
|
|
209
|
+
: [];
|
|
210
|
+
for (const candidate of candidates) {
|
|
211
|
+
if (!candidate) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const identifier = trustedKeys.get(candidate);
|
|
215
|
+
if (identifier !== undefined) {
|
|
216
|
+
return identifier;
|
|
53
217
|
}
|
|
54
218
|
}
|
|
55
|
-
|
|
56
|
-
console.error(`Warning: failed to parse trusted keys: ${err.message}`);
|
|
57
|
-
}
|
|
58
|
-
return keys;
|
|
219
|
+
return undefined;
|
|
59
220
|
}
|
|
60
221
|
/**
|
|
61
222
|
* Verify signature using Ed25519
|
package/dist/signature.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;
|
|
1
|
+
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,9 +35,27 @@ export declare function signatureCoverage(signature: {
|
|
|
35
35
|
* comparison against whatever the source actually contained.
|
|
36
36
|
*/
|
|
37
37
|
export declare function normalizePublicKey(publicKey: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Whether a public key is one this project can actually verify against.
|
|
40
|
+
*
|
|
41
|
+
* True for anything that normalizes to a raw 32-byte Ed25519 key (raw base64,
|
|
42
|
+
* SPKI PEM, base64 SPKI DER) and for minisign keys, which are passed through.
|
|
43
|
+
*
|
|
44
|
+
* `normalizePublicKey` deliberately returns uninterpretable input unchanged so
|
|
45
|
+
* exact-match comparison still works on the read path. On the *write* path —
|
|
46
|
+
* `dossier keys add` — that same leniency would silently store a typo, a
|
|
47
|
+
* truncated key, or a file path as if it were a trusted key, and the only
|
|
48
|
+
* symptom would be `dossier verify` reporting "not trusted" forever after. Use
|
|
49
|
+
* this to reject before writing.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isSupportedPublicKey(publicKey: string): boolean;
|
|
38
52
|
/**
|
|
39
53
|
* Build an SPKI PEM from any accepted public-key form, for use with node:crypto.
|
|
40
|
-
*
|
|
54
|
+
*
|
|
55
|
+
* Always rebuilt from the parsed key rather than passed through, so the bytes a
|
|
56
|
+
* signature is verified against are the bytes the trust check matched. Returns
|
|
57
|
+
* the input unchanged only when it denotes no Ed25519 key at all, leaving
|
|
58
|
+
* `crypto` to report the error.
|
|
41
59
|
*/
|
|
42
60
|
export declare function toSpkiPem(publicKey: string): string;
|
|
43
61
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing-payload.d.ts","sourceRoot":"","sources":["../src/signing-payload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,kBAAkB,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAAG,iBAAiB,CAE/F;
|
|
1
|
+
{"version":3,"file":"signing-payload.d.ts","sourceRoot":"","sources":["../src/signing-payload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,kBAAkB,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAAG,iBAAiB,CAE/F;AAmFD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAG/D;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKrF;AAuBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAGpF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,iBAAsC,GAC/C,MAAM,CAKR"}
|
package/dist/signing-payload.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.signatureCoverage = signatureCoverage;
|
|
25
25
|
exports.normalizePublicKey = normalizePublicKey;
|
|
26
|
+
exports.isSupportedPublicKey = isSupportedPublicKey;
|
|
26
27
|
exports.toSpkiPem = toSpkiPem;
|
|
27
28
|
exports.publicKeysMatch = publicKeysMatch;
|
|
28
29
|
exports.canonicalizeFrontmatter = canonicalizeFrontmatter;
|
|
@@ -38,57 +39,116 @@ function signatureCoverage(signature) {
|
|
|
38
39
|
return signature?.covers === 'frontmatter+body' ? 'frontmatter+body' : 'body';
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
+
* One PEM block and nothing else: no content before BEGIN or after END, matching
|
|
43
|
+
* labels, and only base64 in between.
|
|
42
44
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
45
|
+
* Anchoring both ends is load-bearing. OpenSSL — so `crypto.createPublicKey` —
|
|
46
|
+
* skips whatever precedes the BEGIN line and ignores whatever follows END, so a
|
|
47
|
+
* blob with padding around a real block still parses, as the key inside the
|
|
48
|
+
* block. If normalization read that same blob more loosely it could conclude the
|
|
49
|
+
* string denotes a *different* key than the one `createPublicKey` will hand to
|
|
50
|
+
* `verify`, and a trust check is exactly the place where those two answers must
|
|
51
|
+
* never differ.
|
|
46
52
|
*/
|
|
47
|
-
|
|
53
|
+
const SINGLE_PEM_BLOCK = /^-----BEGIN ([A-Za-z0-9 ]+)-----([A-Za-z0-9+/=\s]*)-----END \1-----$/;
|
|
54
|
+
/**
|
|
55
|
+
* Decode base64 only when the input is exactly what re-encoding those bytes gives.
|
|
56
|
+
*
|
|
57
|
+
* Node's base64 decoder is lenient by design: it silently discards characters it
|
|
58
|
+
* does not recognize and stops at the first `=` padding. That leniency is a
|
|
59
|
+
* key-substitution primitive here, because every raw Ed25519 key is 44 base64
|
|
60
|
+
* characters ending in `=` — meaning `<any key><arbitrary trailing text>` decodes
|
|
61
|
+
* to that key. Requiring a byte-exact round trip collapses each string onto at
|
|
62
|
+
* most one key.
|
|
63
|
+
*/
|
|
64
|
+
function decodeExactBase64(value) {
|
|
65
|
+
const decoded = Buffer.from(value, 'base64');
|
|
66
|
+
return decoded.toString('base64') === value ? decoded : undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The raw 32 key bytes a public-key string denotes, or `undefined` when it does
|
|
70
|
+
* not unambiguously denote an Ed25519 key.
|
|
71
|
+
*
|
|
72
|
+
* The single source of truth behind `normalizePublicKey`, `toSpkiPem` and
|
|
73
|
+
* `isSupportedPublicKey`, so the key a trust check matches on and the key a
|
|
74
|
+
* signature is verified against are derived from one parse and cannot drift.
|
|
75
|
+
*/
|
|
76
|
+
function ed25519RawKey(publicKey) {
|
|
48
77
|
const trimmed = publicKey.trim();
|
|
49
78
|
if (!trimmed) {
|
|
50
|
-
return
|
|
79
|
+
return undefined;
|
|
51
80
|
}
|
|
52
81
|
// minisign keys are a different encoding entirely (and carry a key id); nothing
|
|
53
82
|
// has produced them since 2025-11-18. Leave them untouched.
|
|
54
83
|
if (trimmed.startsWith('RWT')) {
|
|
55
|
-
return
|
|
84
|
+
return undefined;
|
|
56
85
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
86
|
+
// `-` is not in the base64 alphabet, so this cannot misread a raw key as PEM —
|
|
87
|
+
// whereas testing for the word "BEGIN" would, since B, E, G, I and N all are.
|
|
88
|
+
let base64Body;
|
|
89
|
+
if (trimmed.includes('-----')) {
|
|
90
|
+
const block = SINGLE_PEM_BLOCK.exec(trimmed);
|
|
91
|
+
if (!block) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
base64Body = block[2].replace(/\s+/g, '');
|
|
66
95
|
}
|
|
67
|
-
|
|
68
|
-
|
|
96
|
+
else {
|
|
97
|
+
base64Body = trimmed.replace(/\s+/g, '');
|
|
98
|
+
}
|
|
99
|
+
const decoded = decodeExactBase64(base64Body);
|
|
100
|
+
if (!decoded) {
|
|
101
|
+
return undefined;
|
|
69
102
|
}
|
|
70
103
|
if (decoded.length === ED25519_RAW_KEY_BYTES) {
|
|
71
|
-
return decoded
|
|
104
|
+
return decoded;
|
|
72
105
|
}
|
|
73
106
|
if (decoded.length === ED25519_SPKI_PREFIX.length + ED25519_RAW_KEY_BYTES &&
|
|
74
107
|
decoded.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)) {
|
|
75
|
-
return decoded.subarray(ED25519_SPKI_PREFIX.length)
|
|
108
|
+
return decoded.subarray(ED25519_SPKI_PREFIX.length);
|
|
76
109
|
}
|
|
77
|
-
return
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Normalize an Ed25519 public key to raw 32-byte base64.
|
|
114
|
+
*
|
|
115
|
+
* Accepts SPKI PEM, raw base64, and base64 SPKI DER. Returns the input trimmed
|
|
116
|
+
* when it cannot be interpreted, so callers can still do an exact-match
|
|
117
|
+
* comparison against whatever the source actually contained.
|
|
118
|
+
*/
|
|
119
|
+
function normalizePublicKey(publicKey) {
|
|
120
|
+
const raw = ed25519RawKey(publicKey);
|
|
121
|
+
return raw ? raw.toString('base64') : publicKey.trim();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Whether a public key is one this project can actually verify against.
|
|
125
|
+
*
|
|
126
|
+
* True for anything that normalizes to a raw 32-byte Ed25519 key (raw base64,
|
|
127
|
+
* SPKI PEM, base64 SPKI DER) and for minisign keys, which are passed through.
|
|
128
|
+
*
|
|
129
|
+
* `normalizePublicKey` deliberately returns uninterpretable input unchanged so
|
|
130
|
+
* exact-match comparison still works on the read path. On the *write* path —
|
|
131
|
+
* `dossier keys add` — that same leniency would silently store a typo, a
|
|
132
|
+
* truncated key, or a file path as if it were a trusted key, and the only
|
|
133
|
+
* symptom would be `dossier verify` reporting "not trusted" forever after. Use
|
|
134
|
+
* this to reject before writing.
|
|
135
|
+
*/
|
|
136
|
+
function isSupportedPublicKey(publicKey) {
|
|
137
|
+
const trimmed = publicKey.trim();
|
|
138
|
+
return trimmed.startsWith('RWT') || ed25519RawKey(trimmed) !== undefined;
|
|
78
139
|
}
|
|
79
140
|
/**
|
|
80
141
|
* Build an SPKI PEM from any accepted public-key form, for use with node:crypto.
|
|
81
|
-
*
|
|
142
|
+
*
|
|
143
|
+
* Always rebuilt from the parsed key rather than passed through, so the bytes a
|
|
144
|
+
* signature is verified against are the bytes the trust check matched. Returns
|
|
145
|
+
* the input unchanged only when it denotes no Ed25519 key at all, leaving
|
|
146
|
+
* `crypto` to report the error.
|
|
82
147
|
*/
|
|
83
148
|
function toSpkiPem(publicKey) {
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
const raw = Buffer.from(normalizePublicKey(trimmed), 'base64');
|
|
89
|
-
if (raw.length !== ED25519_RAW_KEY_BYTES) {
|
|
90
|
-
// Not something we can rebuild; hand it back and let crypto report the error.
|
|
91
|
-
return trimmed;
|
|
149
|
+
const raw = ed25519RawKey(publicKey);
|
|
150
|
+
if (!raw) {
|
|
151
|
+
return publicKey.trim();
|
|
92
152
|
}
|
|
93
153
|
const der = Buffer.concat([ED25519_SPKI_PREFIX, raw]);
|
|
94
154
|
const body = der
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing-payload.js","sourceRoot":"","sources":["../src/signing-payload.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AAaH,8CAEC;
|
|
1
|
+
{"version":3,"file":"signing-payload.js","sourceRoot":"","sources":["../src/signing-payload.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED