From d3f653390059b4e7d7491d4eb187aefbeda38b8c Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 26 Jun 2024 17:47:21 -0700 Subject: [PATCH 1/3] attached payloads and presentations --- index.html | 34 ++++++++++++++++++++++++++++++++++ index.js | 28 +++++++++++++++++++--------- src/cose.js | 19 ++++++------------- src/jose.js | 12 ++++-------- src/sd-jwt.js | 20 +++----------------- 5 files changed, 66 insertions(+), 47 deletions(-) diff --git a/index.html b/index.html index 927f62e..753bfba 100644 --- a/index.html +++ b/index.html @@ -81,6 +81,40 @@

Basic Example

} } + +
+{
+  // set the context, which establishes the special terms we will be using.
+  "@context": [
+    "https://www.w3.org/ns/credentials/v2",
+    "https://www.w3.org/ns/credentials/examples/v2"
+  ],
+  // specify the identifier for the presentation
+  "id": "http://example.edu/presentations/1872",
+  // the presentation type, which declare what data to expect in the presentation
+  "type": "VerifiablePresentation",
+  // when the presentation was issued
+  "validFrom": "2010-01-01T19:23:24Z",
+  // credentials in the presentation
+  "verifiableCredential": [
+    {
+      "@context": "https://www.w3.org/ns/credentials/v2",
+      "id": "data:application/vc+cose;base64url,UXpWalYuLi5STWpV",
+      "type": "EnvelopedVerifiableCredential"
+    },
+    {
+      "@context": "https://www.w3.org/ns/credentials/v2",
+      "id": "data:application/vc+jwt;eyVjV...RMjU",
+      "type": "EnvelopedVerifiableCredential"
+    },
+    {
+      "@context": "https://www.w3.org/ns/credentials/v2",
+      "id": "data:application/vc+sd-jwt;eyVjV...RMjU",
+      "type": "EnvelopedVerifiableCredential"
+    }
+  ]
+}
+  
diff --git a/index.js b/index.js index 175517f..1618c08 100644 --- a/index.js +++ b/index.js @@ -616,11 +616,12 @@ async function createVcExamples() { try { verifiableCredentialProof = await attachProof({credential, suite}); const mediaType = - (verifiableCredentialProof.type.includes('VerifiablePresentation')) - ? 'application/vp' : 'application/vc'; + (verifiableCredentialProof.type + .includes('VerifiablePresentation')) ? + 'application/vp' : 'application/vc'; return `

${mediaType}

${JSON.stringify(verifiableCredentialProof, null, 2)
-            .match(/.{1,75}/g).join('\n')}
`; + .match(/.{1,75}/g).join('\n')}`; } catch(e) { console.error( 'respec-vc error: Failed to attach proof to Verifiable Credential.', @@ -634,12 +635,21 @@ async function createVcExamples() { } // set up the unsigned button - addTab( - 'unsigned', - 'Unsecured credential', - 'Credential', - () => example.outerHTML, - ); + if(credential.type.includes('VerifiablePresentation')) { + addTab( + 'unsigned', + 'Unsecured presentation', + 'Presentation', + () => example.outerHTML, + ); + } else { + addTab( + 'unsigned', + 'Unsecured credential', + 'Credential', + () => example.outerHTML, + ); + } for(const {proof, key, label} of exampleProofs) { if(hasTab(proof.cryptosuite)) { diff --git a/src/cose.js b/src/cose.js index bb21a49..78aa714 100644 --- a/src/cose.js +++ b/src/cose.js @@ -11,15 +11,11 @@ function buf2hex(buffer) { const getCredential = async ( privateKey, byteSigner, - messageType, messageJson, ) => { - let oldMessageType = (messageType === 'application/vc+cose') - ? 'application/vc+ld+json+cose' : 'application/vp+ld+json+cose'; - return issuer({ alg: privateKey.alg, - type: oldMessageType, + type: 'application/vc+ld+json+cose', signer: byteSigner, }).issue({ claimset: new TextEncoder().encode(JSON.stringify(messageJson, null, 2)), @@ -29,7 +25,6 @@ const getCredential = async ( const getPresentation = async ( privateKey, byteSigner, - messageType, message, ) => { const disclosures = (message.verifiableCredential || []).map(enveloped => { @@ -45,11 +40,9 @@ const getPresentation = async ( credential: content, }; }); - let oldMessageType = (messageType === 'application/vc+cose') - ? 'application/vc+ld+json+cose' : 'application/vp+ld+json+cose'; return holder({ alg: privateKey.alg, - type: oldMessageType, + type: 'application/vp+ld+json+cose', }).issue({ signer: byteSigner, presentation: message, @@ -58,7 +51,7 @@ const getPresentation = async ( }; const getBinaryMessage = async (privateKey, messageType, messageJson) => { - const signer = cose.detached.signer({ + const signer = cose.signer({ remote: cose.crypto.signer({ secretKeyJwk: privateKey, }), @@ -74,10 +67,10 @@ const getBinaryMessage = async (privateKey, messageType, messageJson) => { }; switch(messageType) { case 'application/vc+cose': { - return getCredential(privateKey, byteSigner, messageType, messageJson); + return getCredential(privateKey, byteSigner, messageJson); } case 'application/vp+cose': { - return getPresentation(privateKey, byteSigner, messageType, messageJson); + return getPresentation(privateKey, byteSigner, messageJson); } default: { throw new Error('Unknown message type'); @@ -104,7 +97,7 @@ ${JSON.stringify(messageJson, null, 2)}
${diagnostic.trim()}
-

${messageType} (detached payload)

+

${messageType}

${messageHex}
diff --git a/src/jose.js b/src/jose.js index b4401f0..57bf18b 100644 --- a/src/jose.js +++ b/src/jose.js @@ -10,14 +10,11 @@ import * as jose from 'jose'; const getCredential = async ( privateKey, byteSigner, - messageType, messageJson ) => { - let oldMessageType = (messageType === 'application/vc+jwt') - ? 'application/vc+ld+json+jwt' : 'application/vp+ld+json+jwt'; return issuer({ alg: privateKey.alg, - type: oldMessageType, + type: 'application/vc+ld+json+jwt', signer: byteSigner, }).issue({ claimset: new TextEncoder().encode(JSON.stringify(messageJson, null, 2)), @@ -27,7 +24,6 @@ const getCredential = async ( const getPresentation = async ( privateKey, byteSigner, - messageType, message ) => { const disclosures = (message.verifiableCredential || []).map(enveloped => { @@ -44,7 +40,7 @@ const getPresentation = async ( }); return holder({ alg: privateKey.alg, - type: messageType, + type: 'application/vp+ld+json+jwt', }).issue({ signer: byteSigner, presentation: message, @@ -76,10 +72,10 @@ const getBinaryMessage = async (privateKey, messageType, messageJson) => { }; switch(messageType) { case 'application/vc+jwt': { - return getCredential(privateKey, byteSigner, messageType, messageJson); + return getCredential(privateKey, byteSigner, messageJson); } case 'application/vp+jwt': { - return getPresentation(privateKey, byteSigner, messageType, messageJson); + return getPresentation(privateKey, byteSigner, messageJson); } default: { throw new Error('Unknown message type'); diff --git a/src/sd-jwt.js b/src/sd-jwt.js index 82c8d40..606fbfb 100644 --- a/src/sd-jwt.js +++ b/src/sd-jwt.js @@ -77,31 +77,17 @@ export const generateIssuerClaims = example => { const getCredential = async ( privateKey, byteSigner, - messageType, messageJson, ) => { - let oldMessageType = (messageType === 'application/vc+sd-jwt') - ? 'application/vc+ld+json+sd-jwt' : 'application/vp+ld+json+sd-jwt'; - return issuer({ alg: privateKey.alg, - type: oldMessageType, + type: 'application/vc+ld+json+sd-jwt', signer: byteSigner, }).issue({ claimset: new TextEncoder().encode(generateIssuerClaims(messageJson)), }); }; -const getPresentation = async ( - privateKey, - byteSigner, - messageType, - messageJson, -) => { - const mediaType = 'application/vc+sd-jwt'; - return getCredential(privateKey, byteSigner, mediaType, messageJson); -}; - export const getBinaryMessage = async ( privateKey, messageType, @@ -120,10 +106,10 @@ export const getBinaryMessage = async ( }; switch(messageType) { case 'application/vc+sd-jwt': { - return getCredential(privateKey, byteSigner, messageType, messageJson); + return getCredential(privateKey, byteSigner, messageJson); } case 'application/vp+sd-jwt': { - return getPresentation(privateKey, byteSigner, messageType, messageJson); + return getCredential(privateKey, byteSigner, messageJson); } default: { throw new Error('Unknown message type'); From baba62180822f3dccb07ae5f0929cb9c49315b0e Mon Sep 17 00:00:00 2001 From: Gabe <7622243+decentralgabe@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:24:48 -0700 Subject: [PATCH 2/3] Update index.html Co-authored-by: Ted Thibodeau Jr --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 753bfba..41f75b8 100644 --- a/index.html +++ b/index.html @@ -91,7 +91,7 @@

Basic Example

], // specify the identifier for the presentation "id": "http://example.edu/presentations/1872", - // the presentation type, which declare what data to expect in the presentation + // the presentation type, which declares what data to expect in the presentation "type": "VerifiablePresentation", // when the presentation was issued "validFrom": "2010-01-01T19:23:24Z", From 674a5b38f83d4a1268ecce21f1ef3e0a376c4de0 Mon Sep 17 00:00:00 2001 From: gabe Date: Mon, 1 Jul 2024 10:30:51 -0700 Subject: [PATCH 3/3] update media types to match vc-jose-cose --- src/cose.js | 6 +++--- src/jose.js | 6 +++--- src/sd-jwt.js | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cose.js b/src/cose.js index 78aa714..f796cd2 100644 --- a/src/cose.js +++ b/src/cose.js @@ -66,10 +66,10 @@ const getBinaryMessage = async (privateKey, messageType, messageJson) => { }, }; switch(messageType) { - case 'application/vc+cose': { + case 'application/vc-ld+cose': { return getCredential(privateKey, byteSigner, messageJson); } - case 'application/vp+cose': { + case 'application/vp-ld+cose': { return getPresentation(privateKey, byteSigner, messageJson); } default: { @@ -82,7 +82,7 @@ export const getCoseExample = async (privateKey, messageJson) => { const type = Array.isArray(messageJson.type) ? messageJson.type : [messageJson.type]; const messageType = type.includes('VerifiableCredential') ? - 'application/vc+cose' : 'application/vp+cose'; + 'application/vc-ld+cose' : 'application/vp-ld+cose'; const message = await getBinaryMessage(privateKey, messageType, messageJson); const messageHex = buf2hex(message); const messageBuffer = Buffer.from(messageHex, 'hex'); diff --git a/src/jose.js b/src/jose.js index 57bf18b..c12ce1a 100644 --- a/src/jose.js +++ b/src/jose.js @@ -71,10 +71,10 @@ const getBinaryMessage = async (privateKey, messageType, messageJson) => { }, }; switch(messageType) { - case 'application/vc+jwt': { + case 'application/vc-ld+jwt': { return getCredential(privateKey, byteSigner, messageJson); } - case 'application/vp+jwt': { + case 'application/vp-ld+jwt': { return getPresentation(privateKey, byteSigner, messageJson); } default: { @@ -87,7 +87,7 @@ export const getJoseExample = async (privateKey, messageJson) => { const type = Array.isArray(messageJson.type) ? messageJson.type : [messageJson.type]; const messageType = type.includes('VerifiableCredential') ? - 'application/vc+jwt' : 'application/vp+jwt'; + 'application/vc-ld+jwt' : 'application/vp-ld+jwt'; const message = await getBinaryMessage(privateKey, messageType, messageJson); const messageEncoded = new TextDecoder().decode(message); const decodedHeader = jose.decodeProtectedHeader(messageEncoded); diff --git a/src/sd-jwt.js b/src/sd-jwt.js index 606fbfb..a1a9e22 100644 --- a/src/sd-jwt.js +++ b/src/sd-jwt.js @@ -105,10 +105,10 @@ export const getBinaryMessage = async ( }, }; switch(messageType) { - case 'application/vc+sd-jwt': { + case 'application/vc-ld+sd-jwt': { return getCredential(privateKey, byteSigner, messageJson); } - case 'application/vp+sd-jwt': { + case 'application/vp-ld+sd-jwt': { return getCredential(privateKey, byteSigner, messageJson); } default: { @@ -126,7 +126,7 @@ export const getSdJwtExample = async ( const type = Array.isArray(messageJson.type) ? messageJson.type : [messageJson.type]; const messageType = type.includes('VerifiableCredential') ? - 'application/vc+sd-jwt' : 'application/vp+sd-jwt'; + 'application/vc-ld+sd-jwt' : 'application/vp-ld+sd-jwt'; const binaryMessage = await getBinaryMessage(privateKey, messageType, messageJson); const message = new TextDecoder().decode(binaryMessage);