@agenticprimitives/key-custody 0.1.0-alpha.2

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/dist/aad.d.ts +2 -0
  4. package/dist/aad.d.ts.map +1 -0
  5. package/dist/aad.js +19 -0
  6. package/dist/aad.js.map +1 -0
  7. package/dist/account.d.ts +23 -0
  8. package/dist/account.d.ts.map +1 -0
  9. package/dist/account.js +54 -0
  10. package/dist/account.js.map +1 -0
  11. package/dist/derive-subject.d.ts +38 -0
  12. package/dist/derive-subject.d.ts.map +1 -0
  13. package/dist/derive-subject.js +137 -0
  14. package/dist/derive-subject.js.map +1 -0
  15. package/dist/factories.d.ts +30 -0
  16. package/dist/factories.d.ts.map +1 -0
  17. package/dist/factories.js +149 -0
  18. package/dist/factories.js.map +1 -0
  19. package/dist/index.d.ts +13 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +17 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/kms-viem-account.d.ts +4 -0
  24. package/dist/kms-viem-account.d.ts.map +1 -0
  25. package/dist/kms-viem-account.js +72 -0
  26. package/dist/kms-viem-account.js.map +1 -0
  27. package/dist/providers/aws.d.ts +13 -0
  28. package/dist/providers/aws.d.ts.map +1 -0
  29. package/dist/providers/aws.js +14 -0
  30. package/dist/providers/aws.js.map +1 -0
  31. package/dist/providers/gcp.d.ts +103 -0
  32. package/dist/providers/gcp.d.ts.map +1 -0
  33. package/dist/providers/gcp.js +490 -0
  34. package/dist/providers/gcp.js.map +1 -0
  35. package/dist/providers/local.d.ts +60 -0
  36. package/dist/providers/local.d.ts.map +1 -0
  37. package/dist/providers/local.js +246 -0
  38. package/dist/providers/local.js.map +1 -0
  39. package/dist/relay-only.d.ts +3 -0
  40. package/dist/relay-only.d.ts.map +1 -0
  41. package/dist/relay-only.js +19 -0
  42. package/dist/relay-only.js.map +1 -0
  43. package/dist/types.d.ts +134 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +70 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +84 -0
  48. package/spec.md +6 -0
@@ -0,0 +1,490 @@
1
+ // GcpKmsSigner — production GCP Cloud KMS asymmetric-sign backend.
2
+ //
3
+ // Cloudflare-Workers-compatible: drives the Cloud KMS REST API directly via
4
+ // fetch + Web Crypto for JWT auth. The @google-cloud/kms SDK uses gRPC and
5
+ // won't run on Workers; this implementation avoids gRPC entirely.
6
+ //
7
+ // Auth: service-account JSON → RS256 JWT (signed via crypto.subtle) →
8
+ // exchanged for an OAuth access token at oauth2.googleapis.com/token.
9
+ // Token cached with expiry buffer.
10
+ //
11
+ // Signing: POST cryptoKeyVersions/N:asymmetricSign with `digest.sha256`
12
+ // carrying our 32-byte keccak256 digest. Cloud KMS signs it as-is
13
+ // (does NOT re-hash) for `EC_SIGN_SECP256K1_SHA256` keys. Response is
14
+ // DER-encoded ECDSA (r,s). We:
15
+ // 1. parse DER → (r, s)
16
+ // 2. normalize s to low-s form (EIP-2)
17
+ // 3. search recovery byte by trying v∈{27,28} against the known pubkey
18
+ // (Cloud KMS doesn't return the recovery bit)
19
+ //
20
+ // Public key: GET cryptoKeyVersions/N/publicKey returns PEM SPKI. We parse
21
+ // the trailing 65-byte uncompressed point (0x04||X||Y), compute
22
+ // keccak256(X||Y), take last 20 bytes → Ethereum address. Cached forever.
23
+ //
24
+ // GcpKmsProvider (envelope encryption via GCP KMS Encrypt/Decrypt) remains a
25
+ // stub — that's a separate v0.2 follow-up. The signer covers the production
26
+ // path for the agent's master-key requirement.
27
+ import { secp256k1 } from '@noble/curves/secp256k1';
28
+ import { keccak_256 } from '@noble/hashes/sha3';
29
+ import { bytesToHex } from 'viem';
30
+ import { buildEvent } from '@agenticprimitives/audit';
31
+ import { canonicalContextBytes } from '../aad';
32
+ // ─────────────────────────────────────────────────────────────────────
33
+ // Constants
34
+ // ─────────────────────────────────────────────────────────────────────
35
+ const GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token';
36
+ const CLOUDKMS_SCOPE = 'https://www.googleapis.com/auth/cloudkms';
37
+ const CLOUDKMS_BASE = 'https://cloudkms.googleapis.com/v1/';
38
+ const TOKEN_EXPIRY_BUFFER_SECONDS = 60;
39
+ const SECP256K1_N = secp256k1.CURVE.n;
40
+ const SECP256K1_HALF_N = SECP256K1_N >> 1n;
41
+ // ─────────────────────────────────────────────────────────────────────
42
+ // Base64 / PEM helpers
43
+ // ─────────────────────────────────────────────────────────────────────
44
+ export function base64UrlEncode(bytes) {
45
+ let str = '';
46
+ for (let i = 0; i < bytes.length; i++)
47
+ str += String.fromCharCode(bytes[i]);
48
+ return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
49
+ }
50
+ function base64Decode(s) {
51
+ const binary = atob(s);
52
+ const out = new Uint8Array(binary.length);
53
+ for (let i = 0; i < binary.length; i++)
54
+ out[i] = binary.charCodeAt(i);
55
+ return out;
56
+ }
57
+ function base64Encode(bytes) {
58
+ let str = '';
59
+ for (let i = 0; i < bytes.length; i++)
60
+ str += String.fromCharCode(bytes[i]);
61
+ return btoa(str);
62
+ }
63
+ export function pemToDer(pem) {
64
+ const lines = pem
65
+ .split('\n')
66
+ .filter((l) => !l.startsWith('-----') && l.trim().length > 0)
67
+ .join('');
68
+ return base64Decode(lines);
69
+ }
70
+ // ─────────────────────────────────────────────────────────────────────
71
+ // JWT signing + token exchange
72
+ // ─────────────────────────────────────────────────────────────────────
73
+ export async function signJwt(serviceAccount, scope) {
74
+ const now = Math.floor(Date.now() / 1000);
75
+ const header = { alg: 'RS256', typ: 'JWT' };
76
+ const payload = {
77
+ iss: serviceAccount.client_email,
78
+ scope,
79
+ aud: GOOGLE_TOKEN_URL,
80
+ iat: now,
81
+ exp: now + 3600,
82
+ };
83
+ const encoder = new TextEncoder();
84
+ const headerB64 = base64UrlEncode(encoder.encode(JSON.stringify(header)));
85
+ const payloadB64 = base64UrlEncode(encoder.encode(JSON.stringify(payload)));
86
+ const signingInput = `${headerB64}.${payloadB64}`;
87
+ const keyDer = pemToDer(serviceAccount.private_key);
88
+ // Copy into a fresh ArrayBuffer so the typing satisfies BufferSource
89
+ // (TS lib.dom narrowed Uint8Array.buffer to ArrayBufferLike in 5.7).
90
+ const keyBuffer = new ArrayBuffer(keyDer.byteLength);
91
+ new Uint8Array(keyBuffer).set(keyDer);
92
+ const key = await globalThis.crypto.subtle.importKey('pkcs8', keyBuffer, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign']);
93
+ const signature = await globalThis.crypto.subtle.sign({ name: 'RSASSA-PKCS1-v1_5' }, key, encoder.encode(signingInput));
94
+ return `${signingInput}.${base64UrlEncode(new Uint8Array(signature))}`;
95
+ }
96
+ export async function fetchAccessToken(serviceAccount) {
97
+ const assertion = await signJwt(serviceAccount, CLOUDKMS_SCOPE);
98
+ const body = `grant_type=${encodeURIComponent('urn:ietf:params:oauth:grant-type:jwt-bearer')}&assertion=${encodeURIComponent(assertion)}`;
99
+ const res = await fetch(GOOGLE_TOKEN_URL, {
100
+ method: 'POST',
101
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
102
+ body,
103
+ });
104
+ if (!res.ok) {
105
+ const text = await res.text();
106
+ throw new Error(`GCP token exchange failed: HTTP ${res.status}: ${text.slice(0, 300)}`);
107
+ }
108
+ const json = (await res.json());
109
+ if (!json.access_token || typeof json.expires_in !== 'number') {
110
+ throw new Error('GCP token exchange: response missing access_token or expires_in');
111
+ }
112
+ return {
113
+ accessToken: json.access_token,
114
+ expiresAt: Math.floor(Date.now() / 1000) + json.expires_in - TOKEN_EXPIRY_BUFFER_SECONDS,
115
+ };
116
+ }
117
+ // ─────────────────────────────────────────────────────────────────────
118
+ // Cloud KMS REST calls
119
+ // ─────────────────────────────────────────────────────────────────────
120
+ async function callKms(token, pathRelativeToBase, options = { method: 'GET' }) {
121
+ const url = `${CLOUDKMS_BASE}${pathRelativeToBase}`;
122
+ const init = {
123
+ method: options.method,
124
+ headers: {
125
+ authorization: `Bearer ${token}`,
126
+ ...(options.body ? { 'content-type': 'application/json' } : {}),
127
+ },
128
+ };
129
+ if (options.body)
130
+ init.body = JSON.stringify(options.body);
131
+ const res = await fetch(url, init);
132
+ if (!res.ok) {
133
+ const text = await res.text();
134
+ // Don't leak the Authorization header. URL path is safe to include.
135
+ throw new Error(`Cloud KMS API error: HTTP ${res.status} on ${pathRelativeToBase}: ${text.slice(0, 300)}`);
136
+ }
137
+ return (await res.json());
138
+ }
139
+ // ─────────────────────────────────────────────────────────────────────
140
+ // SPKI public-key parsing (uncompressed secp256k1 point extraction)
141
+ // ─────────────────────────────────────────────────────────────────────
142
+ export function parseSpkiUncompressedSecp256k1PubKey(spkiDer) {
143
+ // The SPKI structure ends with a BIT STRING containing the public key.
144
+ // For secp256k1, the public key is 65 bytes: 0x04 || X(32) || Y(32).
145
+ // The BIT STRING wrapping adds a single zero "unused bits" byte before
146
+ // the 0x04 marker. So the last 66 bytes of the DER should be:
147
+ // [0x00 (unused bits)] [0x04 (uncompressed marker)] [X 32 bytes] [Y 32 bytes]
148
+ if (spkiDer.length < 66) {
149
+ throw new Error(`SPKI too short to contain uncompressed secp256k1 pubkey: ${spkiDer.length} bytes`);
150
+ }
151
+ const tail = spkiDer.slice(spkiDer.length - 65);
152
+ const marker = tail[0];
153
+ if (marker !== 0x04) {
154
+ throw new Error(`SPKI does not end with uncompressed point marker (0x04). Wrong key algorithm? ` +
155
+ `Found 0x${(marker ?? 0).toString(16).padStart(2, '0')} at position ${spkiDer.length - 65}.`);
156
+ }
157
+ return tail;
158
+ }
159
+ export function publicKeyToAddress(pubKey65) {
160
+ // pubKey65: 0x04 || X(32) || Y(32). Strip prefix; keccak256 over X||Y; last 20 bytes.
161
+ const raw = pubKey65.slice(1);
162
+ const hash = keccak_256(raw);
163
+ return bytesToHex(hash.slice(12));
164
+ }
165
+ // ─────────────────────────────────────────────────────────────────────
166
+ // DER signature parsing + low-s + recovery byte search
167
+ // ─────────────────────────────────────────────────────────────────────
168
+ export function parseDerEcdsa(der) {
169
+ const at = (idx) => {
170
+ const b = der[idx];
171
+ if (b === undefined)
172
+ throw new Error(`DER: unexpected end of buffer at offset ${idx}`);
173
+ return b;
174
+ };
175
+ let i = 0;
176
+ if (at(i++) !== 0x30)
177
+ throw new Error('DER: expected SEQUENCE tag (0x30)');
178
+ // Skip length. Handle short and long form.
179
+ const lenByte = at(i++);
180
+ if (lenByte & 0x80) {
181
+ const lenBytes = lenByte & 0x7f;
182
+ i += lenBytes;
183
+ }
184
+ if (at(i++) !== 0x02)
185
+ throw new Error('DER: expected INTEGER tag for r');
186
+ const rLen = at(i++);
187
+ const rBytes = der.slice(i, i + rLen);
188
+ i += rLen;
189
+ if (at(i++) !== 0x02)
190
+ throw new Error('DER: expected INTEGER tag for s');
191
+ const sLen = at(i++);
192
+ const sBytes = der.slice(i, i + sLen);
193
+ const r = bytesToBigInt(rBytes);
194
+ const s = bytesToBigInt(sBytes);
195
+ // Range-validate (audit F-7): a malformed/compromised KMS response with
196
+ // r/s = 0 or ≥ n is never a valid ECDSA signature — fail closed here
197
+ // rather than letting a degenerate value flow into recovery.
198
+ if (r <= 0n || r >= SECP256K1_N || s <= 0n || s >= SECP256K1_N) {
199
+ throw new Error('DER: r/s out of range (require 0 < r,s < n)');
200
+ }
201
+ return { r, s };
202
+ }
203
+ function bytesToBigInt(bytes) {
204
+ let n = 0n;
205
+ for (const b of bytes)
206
+ n = (n << 8n) | BigInt(b);
207
+ return n;
208
+ }
209
+ export function bigIntTo32Bytes(n) {
210
+ const out = new Uint8Array(32);
211
+ let v = n;
212
+ for (let i = 31; i >= 0; i--) {
213
+ out[i] = Number(v & 0xffn);
214
+ v >>= 8n;
215
+ }
216
+ return out;
217
+ }
218
+ export function normalizeLowS(s) {
219
+ return s > SECP256K1_HALF_N ? SECP256K1_N - s : s;
220
+ }
221
+ function bytesEqual(a, b) {
222
+ if (a.length !== b.length)
223
+ return false;
224
+ for (let i = 0; i < a.length; i++)
225
+ if (a[i] !== b[i])
226
+ return false;
227
+ return true;
228
+ }
229
+ export function findRecoveryByte(r, s, digest, knownPubKey65) {
230
+ const rBytes = bigIntTo32Bytes(r);
231
+ const sBytes = bigIntTo32Bytes(s);
232
+ const compact = new Uint8Array(64);
233
+ compact.set(rBytes, 0);
234
+ compact.set(sBytes, 32);
235
+ const attempts = [];
236
+ for (let recovery = 0; recovery < 2; recovery++) {
237
+ try {
238
+ const sig = secp256k1.Signature.fromCompact(compact).addRecoveryBit(recovery);
239
+ const recovered = sig.recoverPublicKey(digest).toRawBytes(false);
240
+ attempts.push(`v=${recovery + 27} recovered=${bytesToHex(recovered)}`);
241
+ if (bytesEqual(recovered, knownPubKey65))
242
+ return recovery + 27;
243
+ }
244
+ catch (e) {
245
+ attempts.push(`v=${recovery + 27} threw ${e instanceof Error ? e.message : String(e)}`);
246
+ }
247
+ }
248
+ // eslint-disable-next-line no-console
249
+ console.error('[gcp-kms findRecoveryByte] mismatch:', {
250
+ digest: bytesToHex(digest),
251
+ r: bytesToHex(rBytes),
252
+ s: bytesToHex(sBytes),
253
+ knownPubKey: bytesToHex(knownPubKey65),
254
+ attempts,
255
+ });
256
+ throw new Error('Recovery byte search failed: neither v=27 nor v=28 recovers the known public key. ' +
257
+ attempts.join(' | '));
258
+ }
259
+ // ─────────────────────────────────────────────────────────────────────
260
+ // GcpKmsSigner — the public class
261
+ // ─────────────────────────────────────────────────────────────────────
262
+ export class GcpKmsSigner {
263
+ provider = 'gcp-kms';
264
+ keyName;
265
+ serviceAccount;
266
+ auditSink;
267
+ cachedToken;
268
+ cachedPubKey65;
269
+ cachedAddress;
270
+ constructor(opts) {
271
+ const keyName = opts?.cryptoKeyVersionName ?? process.env.GCP_KMS_KEY_NAME;
272
+ const jsonStr = opts?.serviceAccountJson ?? process.env.GCP_SERVICE_ACCOUNT_JSON;
273
+ this.auditSink = opts?.auditSink;
274
+ if (!keyName) {
275
+ throw new Error('GcpKmsSigner: GCP_KMS_KEY_NAME (projects/<P>/locations/<L>/keyRings/<R>/cryptoKeys/<K>/cryptoKeyVersions/<V>) is required.');
276
+ }
277
+ if (!jsonStr) {
278
+ throw new Error('GcpKmsSigner: GCP_SERVICE_ACCOUNT_JSON (service-account JSON string) is required.');
279
+ }
280
+ let parsed;
281
+ try {
282
+ parsed = JSON.parse(jsonStr);
283
+ }
284
+ catch {
285
+ throw new Error('GcpKmsSigner: GCP_SERVICE_ACCOUNT_JSON is not valid JSON.');
286
+ }
287
+ if (!parsed.client_email || !parsed.private_key) {
288
+ throw new Error('GcpKmsSigner: service-account JSON missing client_email or private_key.');
289
+ }
290
+ this.keyName = keyName;
291
+ this.serviceAccount = parsed;
292
+ }
293
+ async getAccessToken() {
294
+ const now = Math.floor(Date.now() / 1000);
295
+ if (this.cachedToken && this.cachedToken.expiresAt > now) {
296
+ return this.cachedToken.accessToken;
297
+ }
298
+ this.cachedToken = await fetchAccessToken(this.serviceAccount);
299
+ return this.cachedToken.accessToken;
300
+ }
301
+ async getPublicKeyBytes() {
302
+ if (this.cachedPubKey65)
303
+ return this.cachedPubKey65;
304
+ const token = await this.getAccessToken();
305
+ const res = await callKms(token, `${this.keyName}/publicKey`);
306
+ // Algorithm guard: signatures from any other curve (e.g. P-256) won't
307
+ // recover to an Ethereum-compatible pubkey. Catch the mistake at first
308
+ // pubkey fetch instead of producing nonsense signatures later.
309
+ if (res.algorithm !== 'EC_SIGN_SECP256K1_SHA256') {
310
+ throw new Error(`GcpKmsSigner: key ${this.keyName} has algorithm "${res.algorithm}", but ` +
311
+ `EC_SIGN_SECP256K1_SHA256 is required for Ethereum-compatible signing. ` +
312
+ `Recreate with: gcloud kms keys create <NAME> --purpose=asymmetric-signing ` +
313
+ `--default-algorithm=ec-sign-secp256k1-sha256 --protection-level=hsm. ` +
314
+ `Note: secp256k1 in GCP requires --protection-level=hsm; Software is not ` +
315
+ `supported. The Console dropdown greys out secp256k1 when Software is ` +
316
+ `selected. GCP doesn't allow changing the algorithm or protection level ` +
317
+ `of an existing key.`);
318
+ }
319
+ const spkiDer = pemToDer(res.pem);
320
+ this.cachedPubKey65 = parseSpkiUncompressedSecp256k1PubKey(spkiDer);
321
+ return this.cachedPubKey65;
322
+ }
323
+ async getSignerAddress() {
324
+ if (this.cachedAddress)
325
+ return this.cachedAddress;
326
+ const pub = await this.getPublicKeyBytes();
327
+ this.cachedAddress = publicKeyToAddress(pub);
328
+ return this.cachedAddress;
329
+ }
330
+ async signA2AAction(input) {
331
+ if (input.digest.length !== 32) {
332
+ throw new Error(`GcpKmsSigner.signA2AAction expects a 32-byte digest; got ${input.digest.length}.`);
333
+ }
334
+ const [token, pubKey] = await Promise.all([this.getAccessToken(), this.getPublicKeyBytes()]);
335
+ const res = await callKms(token, `${this.keyName}:asymmetricSign`, {
336
+ method: 'POST',
337
+ body: { digest: { sha256: base64Encode(input.digest) } },
338
+ });
339
+ const derBytes = base64Decode(res.signature);
340
+ const parsed = parseDerEcdsa(derBytes);
341
+ const s = normalizeLowS(parsed.s);
342
+ const v = findRecoveryByte(parsed.r, s, input.digest, pubKey);
343
+ const sig65 = new Uint8Array(65);
344
+ sig65.set(bigIntTo32Bytes(parsed.r), 0);
345
+ sig65.set(bigIntTo32Bytes(s), 32);
346
+ sig65[64] = v;
347
+ const signerAddress = await this.getSignerAddress();
348
+ // Audit emit. Per key-custody CLAUDE.md invariant:
349
+ // raw sessionId MUST NEVER be logged — hash it.
350
+ if (this.auditSink) {
351
+ const ctx = input.auditContext ?? {};
352
+ try {
353
+ await this.auditSink.write(buildEvent({
354
+ action: 'key-custody.sign',
355
+ outcome: 'success',
356
+ actor: { type: 'system', id: 'gcp-kms-signer' },
357
+ subject: { type: 'sign-digest', id: bytesToHex(input.digest) },
358
+ context: {
359
+ keyId: this.keyName,
360
+ signerAddress,
361
+ toolId: ctx.toolId ?? null,
362
+ actionId: ctx.actionId ?? null,
363
+ sessionHash: ctx.sessionId
364
+ ? bytesToHex(keccak_256(new TextEncoder().encode(ctx.sessionId))).slice(0, 18)
365
+ : null,
366
+ },
367
+ }));
368
+ }
369
+ catch {
370
+ /* fail-soft */
371
+ }
372
+ }
373
+ return {
374
+ signature: sig65,
375
+ keyId: this.keyName,
376
+ signerAddress,
377
+ };
378
+ }
379
+ }
380
+ /**
381
+ * H7-F.4 / PKG-KEY-CUSTODY-008 closure — derive `keyVersion` from the
382
+ * GCP encryption response instead of a hardcoded string. The GCP KMS
383
+ * `encrypt` endpoint returns `name` = the full versioned resource path
384
+ * (`projects/<P>/locations/<L>/keyRings/<R>/cryptoKeys/<K>/cryptoKeyVersions/<V>`).
385
+ * The version suffix is what GCP uses to identify the actual key version
386
+ * that encrypted the ciphertext.
387
+ *
388
+ * Previously this class returned `'gcp-kms:v1'` regardless of the actual
389
+ * rotation state — so on a GCP key rotation (under the same cryptoKey
390
+ * NAME, different VERSION), any encrypted payload was still tagged with
391
+ * the meaningless `'gcp-kms:v1'` marker. The `decryptSessionDataKey`
392
+ * equality check then incorrectly accepted ciphertext from BOTH the old
393
+ * and the new key version as if they were the same, with no audit trail
394
+ * of which version produced which.
395
+ */
396
+ function parseCryptoKeyVersion(responseName) {
397
+ if (!responseName)
398
+ return null;
399
+ const m = /\/cryptoKeyVersions\/(\d+)$/.exec(responseName);
400
+ return m ? `gcp-kms:v${m[1]}` : null;
401
+ }
402
+ export class GcpKmsProvider {
403
+ /**
404
+ * H7-F.4: this default is now ONLY used when the GCP encrypt response
405
+ * doesn't carry a `name` field (test fixtures + offline mocks). Real
406
+ * runs derive `keyVersion` from the response per call.
407
+ */
408
+ keyVersion = 'gcp-kms:unknown';
409
+ keyName;
410
+ serviceAccount;
411
+ cachedToken;
412
+ constructor(opts) {
413
+ const keyName = opts?.cryptoKeyName ?? process.env.GCP_KMS_ENCRYPT_KEY_NAME;
414
+ const jsonStr = opts?.serviceAccountJson ?? process.env.GCP_SERVICE_ACCOUNT_JSON;
415
+ if (!keyName) {
416
+ throw new Error('GcpKmsProvider: GCP_KMS_ENCRYPT_KEY_NAME (projects/<P>/locations/<L>/keyRings/<R>/cryptoKeys/<K>) is required.');
417
+ }
418
+ if (!jsonStr) {
419
+ throw new Error('GcpKmsProvider: GCP_SERVICE_ACCOUNT_JSON (service-account JSON string) is required.');
420
+ }
421
+ let parsed;
422
+ try {
423
+ parsed = JSON.parse(jsonStr);
424
+ }
425
+ catch {
426
+ throw new Error('GcpKmsProvider: GCP_SERVICE_ACCOUNT_JSON is not valid JSON.');
427
+ }
428
+ if (!parsed.client_email || !parsed.private_key) {
429
+ throw new Error('GcpKmsProvider: service-account JSON missing client_email or private_key.');
430
+ }
431
+ this.keyName = keyName;
432
+ this.serviceAccount = parsed;
433
+ }
434
+ async getAccessToken() {
435
+ const now = Math.floor(Date.now() / 1000);
436
+ if (this.cachedToken && this.cachedToken.expiresAt > now) {
437
+ return this.cachedToken.accessToken;
438
+ }
439
+ this.cachedToken = await fetchAccessToken(this.serviceAccount);
440
+ return this.cachedToken.accessToken;
441
+ }
442
+ async generateSessionDataKey(input) {
443
+ const plaintextDataKey = new Uint8Array(32);
444
+ globalThis.crypto.getRandomValues(plaintextDataKey);
445
+ const aadBytes = canonicalContextBytes(input.aadContext);
446
+ const token = await this.getAccessToken();
447
+ const res = await callKms(token, `${this.keyName}:encrypt`, {
448
+ method: 'POST',
449
+ body: {
450
+ plaintext: base64Encode(plaintextDataKey),
451
+ additionalAuthenticatedData: base64Encode(aadBytes),
452
+ },
453
+ });
454
+ const encryptedDataKey = base64Decode(res.ciphertext);
455
+ // H7-F.4: derive keyVersion from the response. GCP returns the full
456
+ // versioned cryptoKeyVersions/<N> resource path in `name`. When
457
+ // absent (test fixtures), fall back to the legacy 'gcp-kms:unknown'
458
+ // marker so callers can spot misconfigured mocks.
459
+ const keyVersion = parseCryptoKeyVersion(res.name) ?? this.keyVersion;
460
+ return {
461
+ plaintextDataKey,
462
+ encryptedDataKey,
463
+ keyId: this.keyName,
464
+ keyVersion,
465
+ };
466
+ }
467
+ async decryptSessionDataKey(input) {
468
+ // H7-F.4: validate the `keyVersion` MARKER shape (must be
469
+ // 'gcp-kms:v<N>' or 'gcp-kms:unknown'). GCP's decrypt endpoint
470
+ // itself resolves the actual version from the ciphertext metadata,
471
+ // so the marker is operational ("which version produced this
472
+ // payload?") rather than a security gate. A null / arbitrary string
473
+ // here is a signal of cross-backend confusion — fail fast.
474
+ if (!/^gcp-kms:(v\d+|unknown)$/.test(input.keyVersion)) {
475
+ throw new Error(`GcpKmsProvider: input.keyVersion "${input.keyVersion}" doesn't match the expected ` +
476
+ `'gcp-kms:v<N>' or 'gcp-kms:unknown' shape (H7-F.4).`);
477
+ }
478
+ const aadBytes = canonicalContextBytes(input.aadContext);
479
+ const token = await this.getAccessToken();
480
+ const res = await callKms(token, `${this.keyName}:decrypt`, {
481
+ method: 'POST',
482
+ body: {
483
+ ciphertext: base64Encode(input.encryptedDataKey),
484
+ additionalAuthenticatedData: base64Encode(aadBytes),
485
+ },
486
+ });
487
+ return base64Decode(res.plaintext);
488
+ }
489
+ }
490
+ //# sourceMappingURL=gcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp.js","sourceRoot":"","sources":["../../src/providers/gcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { hexToBytes, bytesToHex, toHex, type Address, type Hex } from 'viem';
2
+ import type { A2AKeyProvider, KmsAccountBackend } from '../types';
3
+ import { type AuditSink } from '@agenticprimitives/audit';
4
+ export declare class LocalAesProvider implements A2AKeyProvider {
5
+ readonly keyVersion = "local-v1";
6
+ private readonly master;
7
+ constructor(opts?: {
8
+ sessionSecretHex?: string;
9
+ });
10
+ generateSessionDataKey(input: {
11
+ aadContext: Record<string, string>;
12
+ }): Promise<{
13
+ plaintextDataKey: Uint8Array<ArrayBufferLike>;
14
+ encryptedDataKey: Uint8Array<ArrayBufferLike>;
15
+ keyId: string;
16
+ keyVersion: string;
17
+ }>;
18
+ decryptSessionDataKey(input: {
19
+ encryptedDataKey: Uint8Array;
20
+ aadContext: Record<string, string>;
21
+ keyId: string;
22
+ keyVersion: string;
23
+ }): Promise<Uint8Array<ArrayBufferLike>>;
24
+ generateMac(input: {
25
+ canonicalMessage: Uint8Array;
26
+ service: string;
27
+ audience: string;
28
+ }): Promise<{
29
+ mac: Uint8Array<ArrayBufferLike>;
30
+ keyId: string;
31
+ }>;
32
+ }
33
+ export declare class LocalSecp256k1Signer implements KmsAccountBackend {
34
+ readonly provider: "local-aes";
35
+ private readonly priv;
36
+ private readonly addr;
37
+ private readonly auditSink?;
38
+ constructor(opts?: {
39
+ privateKeyHex?: string;
40
+ auditSink?: AuditSink;
41
+ });
42
+ signA2AAction(input: {
43
+ digest: Uint8Array;
44
+ auditContext?: {
45
+ toolId?: string;
46
+ sessionId?: string;
47
+ actionId?: string;
48
+ };
49
+ }): Promise<{
50
+ signature: Uint8Array<ArrayBuffer>;
51
+ keyId: string;
52
+ signerAddress: `0x${string}`;
53
+ }>;
54
+ getSignerAddress(): Promise<Address>;
55
+ /** Internal: returns the address as a hex string for use by adapters. */
56
+ addressHex(): Address;
57
+ }
58
+ export type { Address, Hex };
59
+ export { hexToBytes, bytesToHex, toHex };
60
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/providers/local.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAiHtE,qBAAa,gBAAiB,YAAW,cAAc;IACrD,QAAQ,CAAC,UAAU,cAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAExB,IAAI,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE;IAe1C,sBAAsB,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;;;;;;IAiBpE,qBAAqB,CAAC,KAAK,EAAE;QACjC,gBAAgB,EAAE,UAAU,CAAC;QAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB;IAmBK,WAAW,CAAC,KAAK,EAAE;QAAE,gBAAgB,EAAE,UAAU,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;;;;CAW7F;AAED,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,QAAQ,CAAC,QAAQ,EAAG,WAAW,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAY;gBAE3B,IAAI,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,SAAS,CAAA;KAAE;IAQ9D,aAAa,CAAC,KAAK,EAAE;QACzB,MAAM,EAAE,UAAU,CAAC;QACnB,YAAY,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3E;;;;;IA8CK,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1C,yEAAyE;IACzE,UAAU,IAAI,OAAO;CAGtB;AAaD,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC"}