// @ts-ignore import 'text-encoding-polyfill'; // @ts-ignore import vc from '@digitalcredentials/vc'; // @ts-ignore import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020'; // @ts-ignore import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020'; // @ts-ignore import { UniResolver } from '@sphereon/did-uni-client'; // @ts-ignore import documentLoaderXhr from '@digitalcredentials/jsonld/lib/documentLoaders/xhr'; // @ts-ignore import { frame } from '@digitalcredentials/jsonld'; // @ts-ignore import jsonld from '@digitalcredentials/jsonld'; // @ts-ignore import TangemSdk from 'tangem-sdk'; // @ts-ignore import type { Credential, Presentation } from './types'; export default class Sign { /** * Gets the suit required to sign * * @param cardId the card Id * @param keyId the public key * @returns The suit */ private static async getSuite( cardId: string, keyId: string, controller?: string ) { const keyPair = await Ed25519VerificationKey2020.from({ type: 'Ed25519VerificationKey2020', controller: controller, id: controller + '#controllerKey', }); const suite = new Ed25519Signature2020({ key: keyPair }); suite.signer = { async sign({ data }: any) { const dataHash = Array.from(data) // @ts-ignore .map((byte) => byte.toString(16).padStart(2, '0')) .join(''); const response = await TangemSdk.signHashes([dataHash], keyId, cardId); // @ts-ignore return response.signature; }, id: keyPair.id, }; suite.date = new Date().toISOString(); return suite; } /** * Gets the document * * @param url the document url * @returns The suit */ private static async documentLoader(url: string) { if (url && url.startsWith('did:')) { const didResolver = new UniResolver(); const result = await didResolver.resolve(url); if (result.didResolutionMetadata.error || !result.didDocument) { throw new Error(`Unable to resolve DID: ${url}`); } const framed = await frame(result.didDocument, { '@context': result.didDocument['@context'], '@embed': '@never', 'id': url, }); return { contextUrl: null, documentUrl: url, document: framed, }; } const loader = documentLoaderXhr.apply(jsonld, []); const response = await loader(url); return response; } /** * Sign the credential * * @param * @returns The signed credential */ public static async credential( unsignedCredential: Credential, keyId: string, cardId: string, controller: string ): Promise { const suite = await this.getSuite(cardId, keyId, controller); const signedCredential = await vc.issue({ credential: unsignedCredential, suite, documentLoader: this.documentLoader, }); return signedCredential; } /** * Sign the presentation * * @param * @returns The signed presentation */ public static async presentation( presentation: Presentation, keyId: string, cardId: string, controller: string, challenge: string ): Promise { const suite = await this.getSuite(cardId, keyId, controller); try { const signedPresentation = await vc.signPresentation({ presentation, suite, challenge, documentLoader: this.documentLoader, }); return signedPresentation; } catch (err: any) { //TODO improve error handling throw new Error(err.message); } } /** * Verify a credential * * Currently in development * * @param signedVC a signed credential * @returns wheter the credential is valid or not */ public static async verifyCredential( signedVC: Credential, keyId: string, cardId: string, controller: string ): Promise { const suite = await this.getSuite(cardId, keyId, controller); const result = await vc.verifyCredential({ credential: signedVC, suite, documentLoader: this.documentLoader, }); return result; } /** * Verify a presentation * * Currently in development * * @param signedPresentation a signed presentation * @returns wheter the presentation is valid or not */ public static async verifyPresentation( signedPresentation: Presentation, keyId: string, cardId: string, controller: string, challenge: string ): Promise { const suite = await this.getSuite(cardId, keyId, controller); const result = await vc.verify({ presentation: signedPresentation, challenge, suite, documentLoader: this.documentLoader, }); return result; } }