Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support attached COSE payloads and presentations #33

Merged
merged 3 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,40 @@ <h1>Basic Example</h1>
}
}
</pre>
</pre>
<pre class="example nohighlight vc" data-vc-tabs="jose sd-jwt cose" title="A Verifiable Presentation example">
{
<span class='comment'>// set the context, which establishes the special terms we will be using.</span>
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
<span class='comment'>// specify the identifier for the presentation</span>
"id": "http://example.edu/presentations/1872",
<span class='comment'>// the presentation type, which declare what data to expect in the presentation</span>
decentralgabe marked this conversation as resolved.
Show resolved Hide resolved
"type": "VerifiablePresentation",
<span class='comment'>// when the presentation was issued</span>
"validFrom": "2010-01-01T19:23:24Z",
<span class='comment'>// credentials in the presentation</span>
"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"
}
]
}
</pre>
</section>

<section>
Expand Down
28 changes: 19 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<h1>${mediaType}</h1>
<pre>${JSON.stringify(verifiableCredentialProof, null, 2)
.match(/.{1,75}/g).join('\n')}</pre>`;
.match(/.{1,75}/g).join('\n')}</pre>`;
} catch(e) {
console.error(
'respec-vc error: Failed to attach proof to Verifiable Credential.',
Expand All @@ -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)) {
Expand Down
19 changes: 6 additions & 13 deletions src/cose.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand All @@ -29,7 +25,6 @@ const getCredential = async (
const getPresentation = async (
privateKey,
byteSigner,
messageType,
message,
) => {
const disclosures = (message.verifiableCredential || []).map(enveloped => {
Expand All @@ -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,
Expand All @@ -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,
}),
Expand All @@ -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');
Expand All @@ -104,7 +97,7 @@ ${JSON.stringify(messageJson, null, 2)}
<div class="cose-text">
<pre><code>${diagnostic.trim()}</code></pre>
</div>
<h1>${messageType} (detached payload)</h1>
<h1>${messageType}</h1>
<div class="cose-text">
${messageHex}
</div>
Expand Down
12 changes: 4 additions & 8 deletions src/jose.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand All @@ -27,7 +24,6 @@ const getCredential = async (
const getPresentation = async (
privateKey,
byteSigner,
messageType,
message
) => {
const disclosures = (message.verifiableCredential || []).map(enveloped => {
Expand All @@ -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,
Expand Down Expand Up @@ -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');
Expand Down
20 changes: 3 additions & 17 deletions src/sd-jwt.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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');
Expand Down