@kya-os/mcp-i 1.7.9 → 1.7.10
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.
|
@@ -254,11 +254,13 @@ class DelegationCredentialVerifier {
|
|
|
254
254
|
durationMs: Date.now() - startTime,
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
|
-
// Extract signature bytes
|
|
258
|
-
//
|
|
257
|
+
// Extract signature bytes and construct signing input
|
|
258
|
+
// Handle both JWS format (header.payload.signature) and proofValue format
|
|
259
259
|
let signatureBase64url;
|
|
260
|
+
let signingInput;
|
|
260
261
|
if (rawProofValue.includes('.')) {
|
|
261
|
-
// JWS format
|
|
262
|
+
// JWS format with b64:false (standard for Ed25519Signature2020)
|
|
263
|
+
// The signing input is: base64url(header) + "." + payload_bytes
|
|
262
264
|
const jwsParts = rawProofValue.split('.');
|
|
263
265
|
if (jwsParts.length !== 3) {
|
|
264
266
|
return {
|
|
@@ -267,36 +269,49 @@ class DelegationCredentialVerifier {
|
|
|
267
269
|
durationMs: Date.now() - startTime,
|
|
268
270
|
};
|
|
269
271
|
}
|
|
270
|
-
|
|
272
|
+
const [headerB64, payloadB64, signatureB64] = jwsParts;
|
|
273
|
+
signatureBase64url = signatureB64;
|
|
274
|
+
// For b64:false JWS, the signing input is the detached payload format:
|
|
275
|
+
// ASCII(BASE64URL(UTF8(JWS Protected Header))) || '.' || JWS Payload
|
|
276
|
+
// The payload is the hash of the document (for Ed25519Signature2020)
|
|
277
|
+
// Per RFC 7797 (JWS Unencoded Payload Option)
|
|
278
|
+
// Construct proof options for hashing (everything in proof except signature fields)
|
|
279
|
+
const proofOptions = { ...vc.proof };
|
|
280
|
+
delete proofOptions.proofValue;
|
|
281
|
+
delete proofOptions.jws;
|
|
282
|
+
delete proofOptions.signatureValue;
|
|
283
|
+
const canonicalDoc = (0, json_canonicalize_1.canonicalize)(vcWithoutProof);
|
|
284
|
+
const canonicalProof = (0, json_canonicalize_1.canonicalize)(proofOptions);
|
|
285
|
+
// Hash both and concatenate (payload for JWS)
|
|
286
|
+
const docHash = (0, crypto_1.createHash)('sha256').update(canonicalDoc, 'utf8').digest();
|
|
287
|
+
const proofHash = (0, crypto_1.createHash)('sha256').update(canonicalProof, 'utf8').digest();
|
|
288
|
+
const payloadBytes = Buffer.concat([proofHash, docHash]);
|
|
289
|
+
// JWS signing input: header + "." + payload_bytes
|
|
290
|
+
const headerBytes = Buffer.from(headerB64, 'utf8');
|
|
291
|
+
const separator = Buffer.from('.', 'utf8');
|
|
292
|
+
signingInput = Buffer.concat([headerBytes, separator, payloadBytes]);
|
|
271
293
|
}
|
|
272
294
|
else {
|
|
273
|
-
// proofValue is raw base64url signature
|
|
295
|
+
// proofValue is raw base64url signature (Ed25519Signature2020 native format)
|
|
274
296
|
signatureBase64url = rawProofValue;
|
|
275
|
-
}
|
|
276
|
-
try {
|
|
277
|
-
// For Ed25519Signature2020, we need to:
|
|
278
|
-
// 1. Canonicalize the VC without proofValue
|
|
279
|
-
// 2. Canonicalize the proof options
|
|
280
|
-
// 3. Hash both and concatenate
|
|
281
|
-
// 4. Verify the signature
|
|
282
297
|
// Construct proof options (everything in proof except proofValue)
|
|
283
298
|
const proofOptions = { ...vc.proof };
|
|
284
299
|
delete proofOptions.proofValue;
|
|
285
300
|
delete proofOptions.jws;
|
|
286
301
|
delete proofOptions.signatureValue;
|
|
287
|
-
// Create signing input: hash(canonicalize(
|
|
302
|
+
// Create signing input: hash(canonicalize(proofOptions)) || hash(canonicalize(document))
|
|
288
303
|
const canonicalDoc = (0, json_canonicalize_1.canonicalize)(vcWithoutProof);
|
|
289
304
|
const canonicalProof = (0, json_canonicalize_1.canonicalize)(proofOptions);
|
|
290
|
-
// For Ed25519Signature2020, signing input is:
|
|
291
|
-
// SHA-256(canonicalize(proofOptions)) || SHA-256(canonicalize(document))
|
|
292
305
|
const docHash = (0, crypto_1.createHash)('sha256').update(canonicalDoc, 'utf8').digest();
|
|
293
306
|
const proofHash = (0, crypto_1.createHash)('sha256').update(canonicalProof, 'utf8').digest();
|
|
294
|
-
|
|
307
|
+
signingInput = Buffer.concat([proofHash, docHash]);
|
|
308
|
+
}
|
|
309
|
+
try {
|
|
295
310
|
// Decode the base64url signature
|
|
296
311
|
const signatureBytes = Buffer.from(signatureBase64url, 'base64url');
|
|
297
312
|
// Use subtle crypto for Ed25519 verification
|
|
298
313
|
const cryptoKey = await globalThis.crypto.subtle.importKey('jwk', publicKeyJwk, { name: 'Ed25519' }, false, ['verify']);
|
|
299
|
-
const isValid = await globalThis.crypto.subtle.verify({ name: 'Ed25519' }, cryptoKey, signatureBytes, signingInput);
|
|
314
|
+
const isValid = await globalThis.crypto.subtle.verify({ name: 'Ed25519' }, cryptoKey, new Uint8Array(signatureBytes), new Uint8Array(signingInput));
|
|
300
315
|
if (!isValid) {
|
|
301
316
|
return {
|
|
302
317
|
valid: false,
|