Browse Source

finally get something other that simplewebauthn working

pull/116/head
Trent Larson 5 months ago
parent
commit
8cf8b9f837
  1. 61
      package-lock.json
  2. 6
      package.json
  3. 102
      src/libs/crypto/passkeyHelpers.ts
  4. 251
      src/libs/didPeer.ts
  5. 8
      src/views/TestView.vue

61
package-lock.json

@ -14,12 +14,12 @@
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.6",
"@peculiar/asn1-ecc": "^2.3.8",
"@peculiar/asn1-schema": "^2.3.8",
"@pvermeer/dexie-encrypted-addon": "^3.0.0",
"@simplewebauthn/browser": "^10.0.0",
"@simplewebauthn/server": "^10.0.0",
"@tweenjs/tween.js": "^21.1.1",
"@types/js-yaml": "^4.0.9",
"@types/luxon": "^3.4.2",
"@veramo/core": "^5.6.0",
"@veramo/credential-w3c": "^5.6.0",
"@veramo/data-store": "^5.6.0",
@ -69,7 +69,9 @@
"web-did-resolver": "^2.0.27"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/leaflet": "^1.9.8",
"@types/luxon": "^3.4.2",
"@types/ramda": "^0.29.11",
"@types/three": "^0.155.1",
"@types/ua-parser-js": "^0.7.39",
@ -6009,21 +6011,11 @@
}
},
"node_modules/@noble/curves": {
"version": "1.2.0",
"license": "MIT",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz",
"integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==",
"dependencies": {
"@noble/hashes": "1.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/curves/node_modules/@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
"engines": {
"node": ">= 16"
"@noble/hashes": "1.4.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
@ -6106,7 +6098,8 @@
},
"node_modules/@peculiar/asn1-ecc": {
"version": "2.3.8",
"license": "MIT",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.8.tgz",
"integrity": "sha512-Ah/Q15y3A/CtxbPibiLM/LKcMbnLTdUdLHUgdpB5f60sSvGkXzxJCu5ezGTFHogZXWNX3KSmYqilCrfdmBc6pQ==",
"dependencies": {
"@peculiar/asn1-schema": "^2.3.8",
"@peculiar/asn1-x509": "^2.3.8",
@ -6126,7 +6119,8 @@
},
"node_modules/@peculiar/asn1-schema": {
"version": "2.3.8",
"license": "MIT",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz",
"integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==",
"dependencies": {
"asn1js": "^3.0.5",
"pvtsutils": "^1.3.5",
@ -8752,6 +8746,7 @@
},
"node_modules/@types/js-yaml": {
"version": "4.0.9",
"dev": true,
"license": "MIT"
},
"node_modules/@types/json-schema": {
@ -8768,6 +8763,7 @@
},
"node_modules/@types/luxon": {
"version": "3.4.2",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
@ -10601,11 +10597,12 @@
}
},
"node_modules/braces": {
"version": "3.0.2",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.0.1"
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@ -12741,6 +12738,17 @@
"node": ">=14.0.0"
}
},
"node_modules/ethers/node_modules/@noble/curves": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
"dependencies": {
"@noble/hashes": "1.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/ethers/node_modules/@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
@ -13455,9 +13463,10 @@
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@ -14614,8 +14623,9 @@
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@ -20676,8 +20686,9 @@
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},

6
package.json

@ -16,12 +16,12 @@
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.6",
"@peculiar/asn1-ecc": "^2.3.8",
"@peculiar/asn1-schema": "^2.3.8",
"@pvermeer/dexie-encrypted-addon": "^3.0.0",
"@simplewebauthn/browser": "^10.0.0",
"@simplewebauthn/server": "^10.0.0",
"@tweenjs/tween.js": "^21.1.1",
"@types/js-yaml": "^4.0.9",
"@types/luxon": "^3.4.2",
"@veramo/core": "^5.6.0",
"@veramo/credential-w3c": "^5.6.0",
"@veramo/data-store": "^5.6.0",
@ -71,7 +71,9 @@
"web-did-resolver": "^2.0.27"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/leaflet": "^1.9.8",
"@types/luxon": "^3.4.2",
"@types/ramda": "^0.29.11",
"@types/three": "^0.155.1",
"@types/ua-parser-js": "^0.7.39",

102
src/libs/crypto/passkeyHelpers.ts

@ -0,0 +1,102 @@
// from https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/helpers/iso/isoCrypto/unwrapEC2Signature.ts
import { AsnParser } from "@peculiar/asn1-schema";
import { ECDSASigValue } from "@peculiar/asn1-ecc";
/**
* In WebAuthn, EC2 signatures are wrapped in ASN.1 structure so we need to peel r and s apart.
*
* See https://www.w3.org/TR/webauthn-2/#sctn-signature-attestation-types
*/
export function unwrapEC2Signature(signature: Uint8Array): Uint8Array {
const parsedSignature = AsnParser.parse(signature, ECDSASigValue);
let rBytes = new Uint8Array(parsedSignature.r);
let sBytes = new Uint8Array(parsedSignature.s);
if (shouldRemoveLeadingZero(rBytes)) {
rBytes = rBytes.slice(1);
}
if (shouldRemoveLeadingZero(sBytes)) {
sBytes = sBytes.slice(1);
}
const finalSignature = isoUint8ArrayConcat([rBytes, sBytes]);
return finalSignature;
}
/**
* Determine if the DER-specific `00` byte at the start of an ECDSA signature byte sequence
* should be removed based on the following logic:
*
* "If the leading byte is 0x0, and the the high order bit on the second byte is not set to 0,
* then remove the leading 0x0 byte"
*/
function shouldRemoveLeadingZero(bytes: Uint8Array): boolean {
return bytes[0] === 0x0 && (bytes[1] & (1 << 7)) !== 0;
}
// from https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/helpers/iso/isoUint8Array.ts#L49
/**
* Combine multiple Uint8Arrays into a single Uint8Array
*/
export function isoUint8ArrayConcat(arrays: Uint8Array[]): Uint8Array {
let pointer = 0;
const totalLength = arrays.reduce((prev, curr) => prev + curr.length, 0);
const toReturn = new Uint8Array(totalLength);
arrays.forEach((arr) => {
toReturn.set(arr, pointer);
pointer += arr.length;
});
return toReturn;
}
// from https://github.com/MasterKale/SimpleWebAuthn/blob/master/packages/server/src/helpers/iso/isoCrypto/getWebCrypto.ts
let webCrypto: unknown = undefined;
export function getWebCrypto() {
/**
* Hello there! If you came here wondering why this method is asynchronous when use of
* `globalThis.crypto` is not, it's to minimize a bunch of refactor related to making this
* synchronous. For example, `generateRegistrationOptions()` and `generateAuthenticationOptions()`
* become synchronous if we make this synchronous (since nothing else in that method is async)
* which represents a breaking API change in this library's core API.
*
* TODO: If it's after February 2025 when you read this then consider whether it still makes sense
* to keep this method asynchronous.
*/
const toResolve = new Promise((resolve, reject) => {
if (webCrypto) {
return resolve(webCrypto);
}
/**
* Naively attempt to access Crypto as a global object, which popular ESM-centric run-times
* support (and Node v20+)
*/
const _globalThisCrypto = _getWebCryptoInternals.stubThisGlobalThisCrypto();
if (_globalThisCrypto) {
webCrypto = _globalThisCrypto;
return resolve(webCrypto);
}
// We tried to access it both in Node and globally, so bail out
return reject(new MissingWebCrypto());
});
return toResolve;
}
export class MissingWebCrypto extends Error {
constructor() {
const message = "An instance of the Crypto API could not be located";
super(message);
this.name = "MissingWebCrypto";
}
}
// Make it possible to stub return values during testing
export const _getWebCryptoInternals = {
stubThisGlobalThisCrypto: () => globalThis.crypto,
// Make it possible to reset the `webCrypto` at the top of the file
setCachedCrypto: (newCrypto: unknown) => {
webCrypto = newCrypto;
},
};

251
src/libs/didPeer.ts

@ -1,8 +1,8 @@
import asn1 from "asn1-ber";
import { Buffer } from "buffer/";
import { decode as cborDecode } from "cbor-x";
import { createJWS, JWTPayload, verifyJWT } from "did-jwt";
import { DIDResolutionResult, Resolver } from "did-resolver";
import { createJWS, JWTPayload } from "did-jwt";
import { DIDResolutionResult } from "did-resolver";
import { sha256 } from "ethereum-cryptography/sha256.js";
import { bytesToMultibase } from "@veramo/utils";
import {
@ -24,6 +24,7 @@ import {
} from "@simplewebauthn/types";
import { generateRandomBytes } from "@/libs/crypto";
import { getWebCrypto, unwrapEC2Signature } from "@/libs/crypto/passkeyHelpers";
export interface JWK {
kty: string;
@ -77,12 +78,24 @@ export async function registerCredential(userId: Uint8Array) {
expectedRPID: window.location.hostname,
});
console.log("verification", verification);
const jwkObj = cborDecode(
verification.registrationInfo?.credentialPublicKey as Uint8Array,
);
console.log("jwkObj from verification", jwkObj);
console.log(
"[1]==2 => kty EC",
"[3]==-7 => alg ES256",
"[-1]==1 => crv P-256",
);
const { publicKeyJwk } = cborToKeys(
verification.registrationInfo?.credentialPublicKey as Uint8Array,
);
return {
authData: verification.registrationInfo?.attestationObject,
credId: verification.registrationInfo?.credentialID as string,
rawId: new Uint8Array(new Buffer(attResp.rawId, "base64")),
publicKeyJwk: undefined,
publicKeyJwk: publicKeyJwk,
publicKeyBytes: verification.registrationInfo
?.credentialPublicKey as Uint8Array,
};
@ -153,30 +166,9 @@ export async function registerCredential2(userId: Uint8Array) {
);
console.log("attestationObject", attestationObject);
const jwkObj = cborDecode(
const { publicKeyJwk, publicKeyBuffer } = cborToKeys(
verification.registrationInfo?.credentialPublicKey as Uint8Array,
);
console.log("jwkObj from verification", jwkObj);
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 publicKeyBytes = Buffer.concat([
Buffer.from(jwkObj[-2]),
Buffer.from(jwkObj[-3]),
]);
//const publicKeyBytes = extractPublicKeyCose(attestationObject.authData);
//const publicKeyJwk = extractPublicKeyJwk(attestationObject.authData);
@ -186,7 +178,7 @@ export async function registerCredential2(userId: Uint8Array) {
credId: credential?.id,
rawId: credential?.rawId,
publicKeyJwk,
publicKeyBytes,
publicKeyBytes: publicKeyBuffer,
};
}
@ -208,9 +200,12 @@ export function createPeerDid(publicKeyBytes: Uint8Array) {
export class PeerSetup {
public authenticatorData?: ArrayBuffer;
public authenticatorDataBase64Url?: Base64URLString;
public challenge?: Uint8Array;
public clientDataJsonDecoded?: object;
public clientDataJsonBase64Url?: Base64URLString;
public signature?: Base64URLString;
public publicKeyJwk?: JWK;
public async createJwt(
payload: object,
@ -244,16 +239,23 @@ export class PeerSetup {
const clientAuth = await startAuthentication(options);
console.log("custom clientAuth", clientAuth);
this.authenticatorDataBase64Url = clientAuth.response.authenticatorData;
this.authenticatorData = Buffer.from(
clientAuth.response.authenticatorData,
"base64",
).buffer;
this.challenge = payloadHash;
this.clientDataJsonBase64Url = clientAuth.response.clientDataJSON;
this.clientDataJsonDecoded = JSON.parse(
Buffer.from(clientAuth.response.clientDataJSON, "base64").toString(
"utf-8",
),
);
console.log("authenticatorData for signing", this.authenticatorData);
console.log(
"clientDataJSON for signing",
Buffer.from(clientAuth.response.clientDataJSON, "base64"),
);
this.signature = clientAuth.response.signature;
const headerBase64 = Buffer.from(JSON.stringify(header)).toString("base64");
@ -373,9 +375,12 @@ export async function verifyJwt(
credId: Base64URLString,
rawId: Uint8Array,
authenticatorData: ArrayBuffer,
authenticatorDataBase64Url: Base64URLString,
challenge: Uint8Array,
clientDataJSON: object,
publicKey: Uint8Array,
clientDataJsonBase64Url: Base64URLString,
publicKeyBytes: Uint8Array,
publicKeyJwk: JWK,
signature: Base64URLString,
) {
// Here's a combined auth & verify process, based on some of the inputs.
@ -397,7 +402,7 @@ export async function verifyJwt(
// const verfOpts: VerifyAuthenticationResponseOpts = {
// authenticator: {
// credentialID: credId,
// credentialPublicKey: publicKey,
// credentialPublicKey: publicKeyBytes,
// counter: 0,
// },
// expectedChallenge: options.challenge,
@ -413,7 +418,7 @@ export async function verifyJwt(
const authOpts: VerifyAuthenticationResponseOpts = {
authenticator: {
credentialID: credId,
credentialPublicKey: publicKey,
credentialPublicKey: publicKeyBytes,
counter: 0,
},
expectedChallenge: arrayToBase64Url(challenge),
@ -438,10 +443,107 @@ export async function verifyJwt(
const verification = await verifyAuthenticationResponse(authOpts);
console.log("auth verification", verification);
const decoded = verifyJWT(jwt, {
resolver: new Resolver({ peer: peerDidToDidDocument }),
});
return decoded;
// It doesn't work to use the did-jwt verifyJWT with did-resolver Resolver
// const decoded = verifyJWT(jwt, {
// resolver: new Resolver({ peer: peerDidToDidDocument }),
// });
// return decoded;
// const [headerB64, concatenatedPayloadB64, signatureB64] = jwt.split(".");
//
// const header = JSON.parse(atob(headerB64));
// const jsonPayload = JSON.parse(atob(concatenatedPayloadB64));
// const [jsonPayloadB64, otherDataHashB64] = concatenatedPayloadB64.split(".");
//
// const otherDataHash = base64urlDecode(otherDataHashB64);
// const signature = base64urlDecode(signatureB64);
//
// const dataToVerify = new TextEncoder().encode(`${headerB64}.${concatenatedPayloadB64}`);
// const dataHash = await sha256(dataToVerify);
//
// const authenticatorData = base64urlDecode(jsonPayload.authenticatorData);
// const clientDataJSON = jsonPayload.clientDataJSON;
/////////
// const clientBuffer = clientDataJsonBase64Url
// .replace(/-/g, "+")
// .replace(/_/g, "/");
// const clientData = new Uint8Array(Buffer.from(clientBuffer, "base64"));
// const clientDataHash = sha256(clientData);
//
// const verifyData = new Uint8Array([
// ...new Uint8Array(authenticatorData),
// ...new Uint8Array(clientDataHash),
// ]);
// console.log("verifyData", verifyData);
// const sigBase64Raw = signature.replace(/-/g, "+").replace(/_/g, "/");
//
// const sigHex = new Uint8Array(Buffer.from(sigBase64Raw, "base64")); //Buffer.from(sigBase64Raw, "base64").toString("hex");
// const msgHex = verifyData; //new Buffer(verifyData).toString("hex");
// const pubHex = publicKeyBytes; //new Buffer(publicKeyBytes).toString("hex");
// console.log("sig msg pub", sigHex, msgHex, pubHex);
// const isValid = p256.verify(sigHex, msgHex, pubHex);
/////////
const authDataFromBase = Buffer.from(authenticatorDataBase64Url, "base64");
const clientDataFromBase = Buffer.from(clientDataJsonBase64Url, "base64");
const sigBuffer = Buffer.from(signature, "base64");
const finalSigBuffer = unwrapEC2Signature(sigBuffer);
// Hash the client data
const hash = sha256(clientDataFromBase);
// Construct the preimage
const preimage = Buffer.concat([authDataFromBase, hash]);
console.log("finalSigBuffer", finalSigBuffer);
console.log("preimage", preimage);
console.log("publicKeyBytes", publicKeyBytes);
// This uses p256 from @noble/curves/p256, which I would prefer but it's returning false.
// const isValid = p256.verify(
// finalSigBuffer,
// new Uint8Array(preimage),
// publicKeyBytes,
// );
// console.log("isValid", isValid);
/////////
const WebCrypto = await getWebCrypto();
const verifyAlgorithm = {
name: "ECDSA",
hash: { name: "SHA-256" },
};
const keyAlgorithm = {
name: "ECDSA",
namedCurve: publicKeyJwk.crv,
};
// const publicKeyCryptoKey = await importKey({
// publicKeyJwk,
// algorithm: keyAlgorithm,
// });
const publicKeyCryptoKey = await WebCrypto.subtle.importKey(
"jwk",
publicKeyJwk,
keyAlgorithm,
false,
["verify"],
);
console.log("verifyAlgorithm", verifyAlgorithm);
console.log("publicKeyCryptoKey", publicKeyCryptoKey);
console.log("finalSigBuffer", finalSigBuffer);
console.log("preimage", preimage);
const verified = await WebCrypto.subtle.verify(
verifyAlgorithm,
publicKeyCryptoKey,
finalSigBuffer,
preimage,
);
console.log("verified", verified);
return verified;
}
async function peerDidToDidDocument(did: string): Promise<DIDResolutionResult> {
@ -481,3 +583,86 @@ async function peerDidToDidDocument(did: string): Promise<DIDResolutionResult> {
didResolutionMetadata: { contentType: "application/did+ld+json" },
};
}
// convert COSE public key to PEM format
function COSEtoPEM(cose: Buffer) {
// const alg = cose.get(3); // Algorithm
const x = cose[-2]; // x-coordinate
const y = cose[-3]; // y-coordinate
// Ensure the coordinates are in the correct format
const pubKeyBuffer = Buffer.concat([Buffer.from([0x04]), x, y]);
// Convert to PEM format
const pem = `-----BEGIN PUBLIC KEY-----
${pubKeyBuffer.toString("base64")}
-----END PUBLIC KEY-----`;
return pem;
}
function base64urlDecode(input: string) {
input = input.replace(/-/g, "+").replace(/_/g, "/");
const pad = input.length % 4 === 0 ? "" : "====".slice(input.length % 4);
const str = atob(input + pad);
const bytes = new Uint8Array(str.length);
for (let i = 0; i < str.length; i++) {
bytes[i] = str.charCodeAt(i);
}
return bytes.buffer;
}
function base64urlEncode(buffer: ArrayBuffer) {
const str = String.fromCharCode(...new Uint8Array(buffer));
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
function cborToKeys(publicKeyBytes: Uint8Array) {
const jwkObj = cborDecode(publicKeyBytes);
console.log("jwkObj from verification", jwkObj);
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 };
}
async function pemToCryptoKey(pem: string) {
const binaryDerString = atob(
pem
.split("\n")
.filter((x) => !x.includes("-----"))
.join(""),
);
const binaryDer = new Uint8Array(binaryDerString.length);
for (let i = 0; i < binaryDerString.length; i++) {
binaryDer[i] = binaryDerString.charCodeAt(i);
}
console.log("binaryDer", binaryDer.buffer);
return await window.crypto.subtle.importKey(
"spki",
binaryDer.buffer,
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
},
true,
["verify"],
);
}

8
src/views/TestView.vue

@ -265,9 +265,7 @@ export default class Help extends Vue {
const encodedUserId = Buffer.from(this.userId).toString("base64");
console.log("encodedUserId", encodedUserId);
const cred = await registerCredential(
this.userId as Uint8Array
);
const cred = await registerCredential(this.userId as Uint8Array);
console.log("public key", cred);
this.publicKeyJwk = cred.publicKeyJwk;
this.publicKeyBytes = cred.publicKeyBytes;
@ -277,6 +275,7 @@ export default class Help extends Vue {
}
public async create() {
console.log("Starting a create");
const did = createPeerDid(this.publicKeyBytes as Uint8Array);
console.log("did", did);
this.peerSetup = new PeerSetup();
@ -303,9 +302,12 @@ export default class Help extends Vue {
this.credId as Base64URLString,
this.rawId as Uint8Array,
this.peerSetup.authenticatorData as ArrayBuffer,
this.peerSetup.authenticatorDataBase64Url as Base64URLString,
this.peerSetup.challenge as Uint8Array,
this.peerSetup.clientDataJsonDecoded,
this.peerSetup.clientDataJsonBase64Url as Base64URLString,
this.publicKeyBytes as Uint8Array,
this.publicKeyJwk as JWK,
this.peerSetup.signature as Base64URLString,
);
console.log("decoded", decoded);

Loading…
Cancel
Save