import { Buffer } from "buffer/"; import { decode as cborDecode } from "cbor-x"; import { bytesToMultibase, multibaseToBytes } from "did-jwt"; import { getWebCrypto } from "@/libs/crypto/vc/passkeyHelpers"; export const PEER_DID_PREFIX = "did:peer:"; const PEER_DID_MULTIBASE_PREFIX = PEER_DID_PREFIX + "0"; /** * * * similar code is in crowd-funder-for-time-pwa libs/crypto/vc/passkeyDidPeer.ts verifyJwtWebCrypto * * @returns {Promise} */ export async function verifyPeerSignature( payloadBytes: Buffer, issuerDid: string, signatureBytes: Uint8Array, ): Promise { const publicKeyBytes = peerDidToPublicKeyBytes(issuerDid); const WebCrypto = await getWebCrypto(); const verifyAlgorithm = { name: "ECDSA", hash: { name: "SHA-256" }, }; const publicKeyJwk = cborToKeys(publicKeyBytes).publicKeyJwk; const keyAlgorithm = { name: "ECDSA", namedCurve: publicKeyJwk.crv, }; const publicKeyCryptoKey = await WebCrypto.subtle.importKey( "jwk", publicKeyJwk, keyAlgorithm, false, ["verify"], ); const verified = await WebCrypto.subtle.verify( verifyAlgorithm, publicKeyCryptoKey, signatureBytes, payloadBytes, ); return verified; } export function cborToKeys(publicKeyBytes: Uint8Array) { const jwkObj = cborDecode(publicKeyBytes); if ( jwkObj[1] != 2 || // kty "EC" jwkObj[3] != -7 || // alg "ES256" jwkObj[-1] != 1 || // crv "P-256" jwkObj[-2].length != 32 || // x jwkObj[-3].length != 32 // y ) { throw new Error("Unable to extract key."); } const publicKeyJwk = { alg: "ES256", crv: "P-256", kty: "EC", x: arrayToBase64Url(jwkObj[-2]), y: arrayToBase64Url(jwkObj[-3]), }; const publicKeyBuffer = Buffer.concat([ Buffer.from(jwkObj[-2]), Buffer.from(jwkObj[-3]), ]); return { publicKeyJwk, publicKeyBuffer }; } export function toBase64Url(anythingB64: string) { return anythingB64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); } export function arrayToBase64Url(anything: Uint8Array) { return toBase64Url(Buffer.from(anything).toString("base64")); } export function peerDidToPublicKeyBytes(did: string) { return multibaseToBytes(did.substring(PEER_DID_MULTIBASE_PREFIX.length)); } export function createPeerDid(publicKeyBytes: Uint8Array) { // https://github.com/decentralized-identity/veramo/blob/next/packages/did-provider-peer/src/peer-did-provider.ts#L67 //const provider = new PeerDIDProvider({ defaultKms: LOCAL_KMS_NAME }); const methodSpecificId = bytesToMultibase( publicKeyBytes, "base58btc", "p256-pub", ); return PEER_DID_MULTIBASE_PREFIX + methodSpecificId; }