-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: F-Node-Karlsruhe <christian.fries@eecc.de>
- Loading branch information
1 parent
cc6447a
commit 0f47aee
Showing
5 changed files
with
174 additions
and
149 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
// @ts-ignore | ||
import { verifyCredential, verify } from '@digitalbazaar/vc'; | ||
// @ts-ignore | ||
import { Ed25519Signature2018 } from '@digitalbazaar/ed25519-signature-2018'; | ||
// @ts-ignore | ||
import { Ed25519Signature2020 } from '@digitalbazaar/ed25519-signature-2020'; | ||
// @ts-ignore | ||
import { checkStatus as checkStatus2020 } from '@digitalbazaar/vc-revocation-list'; | ||
// @ts-ignore | ||
import { checkStatus as checkStatus2021 } from '@digitalbazaar/vc-status-list'; | ||
// @ts-ignore | ||
import * as ecdsaSd2023Cryptosuite from '@digitalbazaar/ecdsa-sd-2023-cryptosuite'; | ||
// @ts-ignore | ||
import { DataIntegrityProof } from '@digitalbazaar/data-integrity'; | ||
// @ts-ignore | ||
import jsigs from 'jsonld-signatures'; | ||
|
||
import { documentLoader } from '../documentLoader/index.js'; | ||
|
||
const { createVerifyCryptosuite } = ecdsaSd2023Cryptosuite; | ||
const { purposes: { AssertionProofPurpose } } = jsigs; | ||
|
||
|
||
function getSuite(proof: Proof): unknown[] { | ||
|
||
switch (proof.type) { | ||
|
||
case 'Ed25519Signature2018': return new Ed25519Signature2018(); | ||
|
||
case 'Ed25519Signature2020': return new Ed25519Signature2020(); | ||
|
||
case 'DataIntegrityProof': return new DataIntegrityProof({ | ||
cryptosuite: createVerifyCryptosuite() | ||
}); | ||
|
||
default: throw new Error(`${proof.type} not implemented`); | ||
} | ||
|
||
} | ||
|
||
function getSuites(proof: Proof | Proof[]): unknown[] { | ||
|
||
var suites: unknown[] = [] | ||
|
||
if (Array.isArray(proof)) { | ||
proof.forEach((proof: Proof) => suites.push(getSuite(proof))); | ||
} else { | ||
suites = [getSuite(proof)] | ||
} | ||
|
||
return suites; | ||
|
||
} | ||
|
||
function getPresentationStatus(presentation: VerifiablePresentation): CredentialStatus[] | CredentialStatus | undefined { | ||
|
||
const credentials = ( | ||
Array.isArray(presentation.verifiableCredential) | ||
? presentation.verifiableCredential | ||
: [presentation.verifiableCredential] | ||
) | ||
.filter((credential: VerifiableCredential) => credential.credentialStatus); | ||
|
||
if (credentials.length == 0) return undefined; | ||
|
||
if (credentials.length == 1) return credentials[0].credentialStatus; | ||
|
||
const statusTypes = credentials.map((credential: VerifiableCredential) => { | ||
return Array.isArray(credential.credentialStatus) | ||
? credential.credentialStatus.map((credentialStatus: CredentialStatus) => credentialStatus.type) | ||
: credential.credentialStatus.type | ||
}); | ||
|
||
// disallow multiple status types | ||
if (new Set(statusTypes.flat(1)).size > 1) throw new Error('Currently only on status type is allowed within one presentation!'); | ||
|
||
return credentials[0].credentialStatus; | ||
|
||
} | ||
|
||
function getCheckStatus(credentialStatus?: CredentialStatus[] | CredentialStatus): any | undefined { | ||
// no status provided | ||
if (!credentialStatus) return undefined; | ||
|
||
let statusTypes = []; | ||
|
||
if (Array.isArray(credentialStatus)) { | ||
statusTypes = credentialStatus.map(cs => cs.type); | ||
} | ||
else statusTypes = [credentialStatus.type] | ||
|
||
if (statusTypes.includes('StatusList2021Entry')) return checkStatus2021; | ||
|
||
if (statusTypes.includes('RevocationList2020Status')) return checkStatus2020; | ||
|
||
throw new Error(`${statusTypes} not implemented`); | ||
|
||
} | ||
|
||
export async function verifyDataIntegrityProof(verifiable: Verifiable, challenge?: string, domain?: string): Promise<VerificationResult> { | ||
|
||
const suite = getSuites(verifiable.proof); | ||
|
||
let result; | ||
|
||
if (verifiable.type.includes('VerifiableCredential')) { | ||
|
||
const credential = verifiable as VerifiableCredential; | ||
|
||
const checkStatus = getCheckStatus(credential.credentialStatus); | ||
|
||
if ((Array.isArray(credential.proof) ? credential.proof[0].type : credential.proof.type) == 'DataIntegrityProof') { | ||
|
||
result = await jsigs.verify(credential, { | ||
suite, | ||
purpose: new AssertionProofPurpose(), | ||
documentLoader, | ||
// give it to jsigs anyway - does not get verified | ||
checkStatus | ||
}); | ||
|
||
} else { | ||
|
||
result = await verifyCredential({ credential, suite, documentLoader, checkStatus }); | ||
|
||
} | ||
} | ||
|
||
if (verifiable.type.includes('VerifiablePresentation')) { | ||
|
||
const presentation = verifiable as VerifiablePresentation; | ||
|
||
// try to use challenge in proof if not provided in case no exchange protocol is used | ||
if (!challenge) challenge = (Array.isArray(presentation.proof) ? presentation.proof[0].challenge : presentation.proof.challenge); | ||
|
||
|
||
const checkStatus = getCheckStatus( | ||
getPresentationStatus(presentation) | ||
); | ||
|
||
result = await verify({ presentation, suite, documentLoader, challenge, domain, checkStatus }); | ||
|
||
} | ||
|
||
if (!result) throw Error('Provided verifiable object is of unknown type!'); | ||
|
||
// make non enumeratable errors enumeratable for the respsonse | ||
if (result.error && !result.error.errors) result.error.name = result.error.message; | ||
|
||
return result; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,155 +1,17 @@ | ||
// @ts-ignore | ||
import { verifyCredential, verify } from '@digitalbazaar/vc'; | ||
// @ts-ignore | ||
import { Ed25519Signature2018 } from '@digitalbazaar/ed25519-signature-2018'; | ||
// @ts-ignore | ||
import { Ed25519Signature2020 } from '@digitalbazaar/ed25519-signature-2020'; | ||
// @ts-ignore | ||
import { checkStatus as checkStatus2020 } from '@digitalbazaar/vc-revocation-list'; | ||
// @ts-ignore | ||
import { checkStatus as checkStatus2021 } from '@digitalbazaar/vc-status-list'; | ||
// @ts-ignore | ||
import * as ecdsaSd2023Cryptosuite from '@digitalbazaar/ecdsa-sd-2023-cryptosuite'; | ||
// @ts-ignore | ||
import { DataIntegrityProof } from '@digitalbazaar/data-integrity'; | ||
// @ts-ignore | ||
import jsigs from 'jsonld-signatures'; | ||
|
||
import { documentLoader } from '../documentLoader/index.js'; | ||
|
||
const { createVerifyCryptosuite } = ecdsaSd2023Cryptosuite; | ||
const { purposes: { AssertionProofPurpose } } = jsigs; | ||
|
||
function getSuite(proof: Proof): unknown[] { | ||
|
||
switch (proof.type) { | ||
|
||
case 'Ed25519Signature2018': return new Ed25519Signature2018(); | ||
|
||
case 'Ed25519Signature2020': return new Ed25519Signature2020(); | ||
|
||
case 'DataIntegrityProof': return new DataIntegrityProof({ | ||
cryptosuite: createVerifyCryptosuite() | ||
}); | ||
|
||
default: throw new Error(`${proof.type} not implemented`); | ||
} | ||
|
||
} | ||
|
||
function getSuites(proof: Proof | Proof[]): unknown[] { | ||
|
||
var suites: unknown[] = [] | ||
|
||
if (Array.isArray(proof)) { | ||
proof.forEach((proof: Proof) => suites.push(getSuite(proof))); | ||
} else { | ||
suites = [getSuite(proof)] | ||
} | ||
|
||
return suites; | ||
|
||
} | ||
|
||
function getPresentationStatus(presentation: VerifiablePresentation): CredentialStatus[] | CredentialStatus | undefined { | ||
|
||
const credentials = ( | ||
Array.isArray(presentation.verifiableCredential) | ||
? presentation.verifiableCredential | ||
: [presentation.verifiableCredential] | ||
) | ||
.filter((credential: VerifiableCredential) => credential.credentialStatus); | ||
|
||
if (credentials.length == 0) return undefined; | ||
|
||
if (credentials.length == 1) return credentials[0].credentialStatus; | ||
|
||
const statusTypes = credentials.map((credential: VerifiableCredential) => { | ||
return Array.isArray(credential.credentialStatus) | ||
? credential.credentialStatus.map((credentialStatus: CredentialStatus) => credentialStatus.type) | ||
: credential.credentialStatus.type | ||
}); | ||
|
||
// disallow multiple status types | ||
if (new Set(statusTypes.flat(1)).size > 1) throw new Error('Currently only on status type is allowed within one presentation!'); | ||
|
||
return credentials[0].credentialStatus; | ||
|
||
} | ||
|
||
function getCheckStatus(credentialStatus?: CredentialStatus[] | CredentialStatus): any | undefined { | ||
// no status provided | ||
if (!credentialStatus) return undefined; | ||
|
||
let statusTypes = []; | ||
|
||
if (Array.isArray(credentialStatus)) { | ||
statusTypes = credentialStatus.map(cs => cs.type); | ||
} | ||
else statusTypes = [credentialStatus.type] | ||
|
||
if (statusTypes.includes('StatusList2021Entry')) return checkStatus2021; | ||
|
||
if (statusTypes.includes('RevocationList2020Status')) return checkStatus2020; | ||
|
||
throw new Error(`${statusTypes} not implemented`); | ||
|
||
} | ||
import { verifyDataIntegrityProof } from './dataintegrity.js'; | ||
import { verifySDJWT } from './sdjwt.js'; | ||
|
||
|
||
export class Verifier { | ||
|
||
static async verify(verifiable: Verifiable, challenge?: string, domain?: string): Promise<any> { | ||
|
||
const suite = getSuites(verifiable.proof); | ||
|
||
let result; | ||
|
||
if (verifiable.type.includes('VerifiableCredential')) { | ||
|
||
const credential = verifiable as VerifiableCredential; | ||
|
||
const checkStatus = getCheckStatus(credential.credentialStatus); | ||
|
||
if ((Array.isArray(credential.proof) ? credential.proof[0].type : credential.proof.type) == 'DataIntegrityProof') { | ||
|
||
result = await jsigs.verify(credential, { | ||
suite, | ||
purpose: new AssertionProofPurpose(), | ||
documentLoader, | ||
// give it to jsigs anyway - does not get verified | ||
checkStatus | ||
}); | ||
|
||
} else { | ||
|
||
result = await verifyCredential({ credential, suite, documentLoader, checkStatus }); | ||
|
||
} | ||
} | ||
|
||
if (verifiable.type.includes('VerifiablePresentation')) { | ||
|
||
const presentation = verifiable as VerifiablePresentation; | ||
|
||
// try to use challenge in proof if not provided in case no exchange protocol is used | ||
if (!challenge) challenge = (Array.isArray(presentation.proof) ? presentation.proof[0].challenge : presentation.proof.challenge); | ||
|
||
|
||
const checkStatus = getCheckStatus( | ||
getPresentationStatus(presentation) | ||
); | ||
|
||
result = await verify({ presentation, suite, documentLoader, challenge, domain, checkStatus }); | ||
|
||
} | ||
|
||
if (!result) throw Error('Provided verifiable object is of unknown type!'); | ||
|
||
// make non enumeratable errors enumeratable for the respsonse | ||
if (result.error && !result.error.errors) result.error.name = result.error.message; | ||
static async verify(verifiable: Verifiable | string, challenge?: string, domain?: string): Promise<VerificationResult> { | ||
|
||
return result; | ||
// vc-jwt or sd-jwt | ||
if (typeof verifiable == 'string') return await verifySDJWT(verifiable, challenge, domain) | ||
|
||
// DataIntegrityProof | ||
return await verifyDataIntegrityProof(verifiable, challenge, domain); | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
|
||
export async function verifySDJWT(verifiable: string, nonce?: string, aud?: string): Promise<VerificationResult> { | ||
|
||
return {verified: false}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters