You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.6 KiB
96 lines
2.6 KiB
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<boolean>}
|
|
*/
|
|
export async function verifyPeerSignature(
|
|
payloadBytes: Buffer,
|
|
issuerDid: string,
|
|
signatureBytes: Uint8Array,
|
|
): Promise<boolean> {
|
|
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;
|
|
}
|
|
|