attempt to simply verify something signed with the same library -- doesn't work
This commit is contained in:
9
package-lock.json
generated
9
package-lock.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||||
"@fortawesome/vue-fontawesome": "^3.0.6",
|
"@fortawesome/vue-fontawesome": "^3.0.6",
|
||||||
"@pvermeer/dexie-encrypted-addon": "^3.0.0",
|
"@pvermeer/dexie-encrypted-addon": "^3.0.0",
|
||||||
|
"@simplewebauthn/browser": "^10.0.0",
|
||||||
"@simplewebauthn/server": "^10.0.0",
|
"@simplewebauthn/server": "^10.0.0",
|
||||||
"@tweenjs/tween.js": "^21.1.1",
|
"@tweenjs/tween.js": "^21.1.1",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
@@ -8226,6 +8227,14 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@simplewebauthn/browser": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-hG0JMZD+LiLUbpQcAjS4d+t4gbprE/dLYop/CkE01ugU/9sKXflxV5s0DRjdz3uNMFecatRfb4ZLG3XvF8m5zg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@simplewebauthn/types": "^10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@simplewebauthn/server": {
|
"node_modules/@simplewebauthn/server": {
|
||||||
"version": "10.0.0",
|
"version": "10.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||||
"@fortawesome/vue-fontawesome": "^3.0.6",
|
"@fortawesome/vue-fontawesome": "^3.0.6",
|
||||||
"@pvermeer/dexie-encrypted-addon": "^3.0.0",
|
"@pvermeer/dexie-encrypted-addon": "^3.0.0",
|
||||||
|
"@simplewebauthn/browser": "^10.0.0",
|
||||||
"@simplewebauthn/server": "^10.0.0",
|
"@simplewebauthn/server": "^10.0.0",
|
||||||
"@tweenjs/tween.js": "^21.1.1",
|
"@tweenjs/tween.js": "^21.1.1",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
|||||||
@@ -4,10 +4,18 @@ import { decode as cborDecode } from "cbor-x";
|
|||||||
import { createJWS, JWTPayload, verifyJWT } from "did-jwt";
|
import { createJWS, JWTPayload, verifyJWT } from "did-jwt";
|
||||||
import { DIDResolutionResult, Resolver } from "did-resolver";
|
import { DIDResolutionResult, Resolver } from "did-resolver";
|
||||||
import { bytesToMultibase } from "@veramo/utils";
|
import { bytesToMultibase } from "@veramo/utils";
|
||||||
|
import { startAuthentication } from "@simplewebauthn/browser";
|
||||||
import {
|
import {
|
||||||
|
generateAuthenticationOptions,
|
||||||
|
verifyAuthenticationResponse,
|
||||||
verifyRegistrationResponse,
|
verifyRegistrationResponse,
|
||||||
VerifyRegistrationResponseOpts,
|
VerifyRegistrationResponseOpts,
|
||||||
} from "@simplewebauthn/server";
|
} from "@simplewebauthn/server";
|
||||||
|
import { VerifyAuthenticationResponseOpts } from "@simplewebauthn/server/esm/authentication/verifyAuthenticationResponse";
|
||||||
|
import {
|
||||||
|
Base64URLString,
|
||||||
|
PublicKeyCredentialRequestOptionsJSON,
|
||||||
|
} from "@simplewebauthn/types";
|
||||||
|
|
||||||
export interface JWK {
|
export interface JWK {
|
||||||
kty: string;
|
kty: string;
|
||||||
@@ -61,11 +69,8 @@ export async function registerCredential(
|
|||||||
publicKey: publicKeyOptions,
|
publicKey: publicKeyOptions,
|
||||||
});
|
});
|
||||||
console.log("credential", credential);
|
console.log("credential", credential);
|
||||||
console.log(credential?.id, " is the new Id");
|
console.log(credential?.id, " is the new ID base64-url-encoded");
|
||||||
console.log(
|
console.log(toBase64Url(credential?.rawId), " is the base64 rawId");
|
||||||
Buffer.from(credential?.rawId).toString("base64"),
|
|
||||||
" is the base64 rawId",
|
|
||||||
);
|
|
||||||
const attestationResponse = credential?.response;
|
const attestationResponse = credential?.response;
|
||||||
const verfInput: VerifyRegistrationResponseOpts = {
|
const verfInput: VerifyRegistrationResponseOpts = {
|
||||||
response: {
|
response: {
|
||||||
@@ -78,7 +83,6 @@ export async function registerCredential(
|
|||||||
clientExtensionResults: {},
|
clientExtensionResults: {},
|
||||||
type: "public-key",
|
type: "public-key",
|
||||||
},
|
},
|
||||||
//expectedChallenge: Buffer.from(challenge).toString("base64"),
|
|
||||||
expectedChallenge: toBase64Url(challenge),
|
expectedChallenge: toBase64Url(challenge),
|
||||||
expectedOrigin: window.location.origin,
|
expectedOrigin: window.location.origin,
|
||||||
};
|
};
|
||||||
@@ -98,9 +102,6 @@ export async function registerCredential(
|
|||||||
);
|
);
|
||||||
console.log("attestationObject", attestationObject);
|
console.log("attestationObject", attestationObject);
|
||||||
|
|
||||||
const credData = parseAuthData(attestationObject.authData);
|
|
||||||
console.log("new attempt at publicKey", credData);
|
|
||||||
|
|
||||||
const jwkObj = cborDecode(
|
const jwkObj = cborDecode(
|
||||||
verification.registrationInfo?.credentialPublicKey as Uint8Array,
|
verification.registrationInfo?.credentialPublicKey as Uint8Array,
|
||||||
);
|
);
|
||||||
@@ -129,7 +130,13 @@ export async function registerCredential(
|
|||||||
//const publicKeyBytes = extractPublicKeyCose(attestationObject.authData);
|
//const publicKeyBytes = extractPublicKeyCose(attestationObject.authData);
|
||||||
//const publicKeyJwk = extractPublicKeyJwk(attestationObject.authData);
|
//const publicKeyJwk = extractPublicKeyJwk(attestationObject.authData);
|
||||||
|
|
||||||
return { rawId: credential?.rawId, publicKeyJwk, publicKeyBytes };
|
return {
|
||||||
|
authData: attestationObject.authData,
|
||||||
|
credId: credential?.id,
|
||||||
|
rawId: credential?.rawId,
|
||||||
|
publicKeyJwk,
|
||||||
|
publicKeyBytes,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse authData
|
// parse authData
|
||||||
@@ -148,115 +155,181 @@ export function createPeerDid(publicKeyBytes: Uint8Array) {
|
|||||||
return "did:peer:0" + methodSpecificId;
|
return "did:peer:0" + methodSpecificId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createJwt(
|
export class PeerSetup {
|
||||||
payload: object,
|
public authenticatorData?: ArrayBuffer;
|
||||||
issuerDid: string,
|
public clientDataJsonDecoded?: object;
|
||||||
credentialId: ArrayBuffer,
|
|
||||||
) {
|
|
||||||
const signer = await webAuthnES256KSigner(credentialId);
|
|
||||||
|
|
||||||
// from createJWT in did-jwt/src/JWT.ts
|
public async createJwt(
|
||||||
const header: JWTPayload = { typ: "JWT", alg: "ES256K" };
|
payload: object,
|
||||||
const timestamps: Partial<JWTPayload> = {
|
issuerDid: string,
|
||||||
iat: Math.floor(Date.now() / 1000),
|
credentialId: string,
|
||||||
exp: undefined,
|
) {
|
||||||
};
|
const signer = await this.webAuthnES256KSigner(credentialId);
|
||||||
const fullPayload = { ...timestamps, ...payload, iss: issuerDid };
|
|
||||||
|
|
||||||
return createJWS(fullPayload, signer, header);
|
// from createJWT in did-jwt/src/JWT.ts
|
||||||
}
|
const header: JWTPayload = { typ: "JWT", alg: "ES256K" };
|
||||||
|
const timestamps: Partial<JWTPayload> = {
|
||||||
|
iat: Math.floor(Date.now() / 1000),
|
||||||
|
exp: undefined,
|
||||||
|
};
|
||||||
|
const fullPayload = { ...timestamps, ...payload, iss: issuerDid };
|
||||||
|
|
||||||
async function webAuthnES256KSigner(credentialID: ArrayBuffer) {
|
const jwt = createJWS(fullPayload, signer, header);
|
||||||
return async (data: string | Uint8Array) => {
|
return jwt;
|
||||||
// also has clientDataJSON
|
|
||||||
const { signature } = await generateWebAuthnSignature(data, credentialID);
|
|
||||||
|
|
||||||
// This converts from the browser ArrayBuffer to a Node.js Buffer, which is a requirement for the asn1 library.
|
|
||||||
const signatureBuffer = Buffer.from(signature);
|
|
||||||
console.log("signature inside signer", signature);
|
|
||||||
console.log("buffer signature inside signer", signatureBuffer);
|
|
||||||
// Decode the DER-encoded signature to extract R and S values
|
|
||||||
const reader = new asn1.BerReader(signatureBuffer);
|
|
||||||
console.log("after reader");
|
|
||||||
reader.readSequence();
|
|
||||||
console.log("after read sequence");
|
|
||||||
const r = reader.readString(asn1.Ber.Integer, true);
|
|
||||||
console.log("after r");
|
|
||||||
const s = reader.readString(asn1.Ber.Integer, true);
|
|
||||||
console.log("after r & s");
|
|
||||||
|
|
||||||
// Ensure R and S are 32 bytes each
|
|
||||||
const rBuffer = Buffer.from(r);
|
|
||||||
const sBuffer = Buffer.from(s);
|
|
||||||
console.log("after rBuffer & sBuffer", rBuffer, sBuffer);
|
|
||||||
const rWithoutPrefix = rBuffer.length > 32 ? rBuffer.slice(1) : rBuffer;
|
|
||||||
const sWithoutPrefix = sBuffer.length > 32 ? sBuffer.slice(1) : sBuffer;
|
|
||||||
const rPadded =
|
|
||||||
rWithoutPrefix.length < 32
|
|
||||||
? Buffer.concat([Buffer.alloc(32 - rWithoutPrefix.length), rBuffer])
|
|
||||||
: rWithoutPrefix;
|
|
||||||
const sPadded =
|
|
||||||
rWithoutPrefix.length < 32
|
|
||||||
? Buffer.concat([Buffer.alloc(32 - sWithoutPrefix.length), sBuffer])
|
|
||||||
: sWithoutPrefix;
|
|
||||||
|
|
||||||
// Concatenate R and S to form the 64-byte array (ECDSA signature format expected by JWT)
|
|
||||||
const combinedSignature = Buffer.concat([rPadded, sPadded]);
|
|
||||||
console.log(
|
|
||||||
"combinedSignature",
|
|
||||||
combinedSignature.length,
|
|
||||||
combinedSignature,
|
|
||||||
);
|
|
||||||
|
|
||||||
const combSig64 = combinedSignature.toString("base64");
|
|
||||||
console.log("combSig64", combSig64);
|
|
||||||
const combSig64Url = combSig64
|
|
||||||
.replace(/\+/g, "-")
|
|
||||||
.replace(/\//g, "_")
|
|
||||||
.replace(/=+$/, "");
|
|
||||||
console.log("combSig64Url", combSig64Url);
|
|
||||||
return combSig64Url;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateWebAuthnSignature(
|
|
||||||
dataToSign: string | Uint8Array,
|
|
||||||
credentialId: ArrayBuffer,
|
|
||||||
) {
|
|
||||||
if (!(dataToSign instanceof Uint8Array)) {
|
|
||||||
dataToSign = new TextEncoder().encode(dataToSign as string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
async webAuthnES256KSigner(credentialID: string) {
|
||||||
challenge: dataToSign,
|
return async (data: string | Uint8Array) => {
|
||||||
allowCredentials: [{ id: credentialId, type: "public-key" }],
|
const signature = await this.generateWebAuthnSignature(
|
||||||
userVerification: "preferred",
|
data,
|
||||||
};
|
credentialID,
|
||||||
|
);
|
||||||
|
|
||||||
const assertion = await navigator.credentials.get({ publicKey: options });
|
// This converts from the browser ArrayBuffer to a Node.js Buffer, which is a requirement for the asn1 library.
|
||||||
console.log("assertion", assertion);
|
const signatureBuffer = Buffer.from(signature);
|
||||||
|
console.log("signature inside signer", signature);
|
||||||
|
console.log("buffer signature inside signer", signatureBuffer);
|
||||||
|
// Decode the DER-encoded signature to extract R and S values
|
||||||
|
const reader = new asn1.BerReader(signatureBuffer);
|
||||||
|
console.log("after reader");
|
||||||
|
reader.readSequence();
|
||||||
|
console.log("after read sequence");
|
||||||
|
const r = reader.readString(asn1.Ber.Integer, true);
|
||||||
|
console.log("after r");
|
||||||
|
const s = reader.readString(asn1.Ber.Integer, true);
|
||||||
|
console.log("after r & s");
|
||||||
|
|
||||||
const authenticatorAssertionResponse = assertion?.response;
|
// Ensure R and S are 32 bytes each
|
||||||
console.log(
|
const rBuffer = Buffer.from(r);
|
||||||
"clientDataJSON decoded",
|
const sBuffer = Buffer.from(s);
|
||||||
JSON.parse(
|
console.log("after rBuffer & sBuffer", rBuffer, sBuffer);
|
||||||
|
const rWithoutPrefix = rBuffer.length > 32 ? rBuffer.slice(1) : rBuffer;
|
||||||
|
const sWithoutPrefix = sBuffer.length > 32 ? sBuffer.slice(1) : sBuffer;
|
||||||
|
const rPadded =
|
||||||
|
rWithoutPrefix.length < 32
|
||||||
|
? Buffer.concat([Buffer.alloc(32 - rWithoutPrefix.length), rBuffer])
|
||||||
|
: rWithoutPrefix;
|
||||||
|
const sPadded =
|
||||||
|
rWithoutPrefix.length < 32
|
||||||
|
? Buffer.concat([Buffer.alloc(32 - sWithoutPrefix.length), sBuffer])
|
||||||
|
: sWithoutPrefix;
|
||||||
|
|
||||||
|
// Concatenate R and S to form the 64-byte array (ECDSA signature format expected by JWT)
|
||||||
|
const combinedSignature = Buffer.concat([rPadded, sPadded]);
|
||||||
|
console.log(
|
||||||
|
"combinedSignature",
|
||||||
|
combinedSignature.length,
|
||||||
|
combinedSignature,
|
||||||
|
);
|
||||||
|
|
||||||
|
const combSig64 = combinedSignature.toString("base64");
|
||||||
|
console.log("combSig64", combSig64);
|
||||||
|
const combSig64Url = combSig64
|
||||||
|
.replace(/\+/g, "-")
|
||||||
|
.replace(/\//g, "_")
|
||||||
|
.replace(/=+$/, "");
|
||||||
|
console.log("combSig64Url", combSig64Url);
|
||||||
|
return combSig64Url;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateWebAuthnSignature(
|
||||||
|
dataToSign: string | Uint8Array, // from Signer interface
|
||||||
|
credentialId: string,
|
||||||
|
) {
|
||||||
|
if (dataToSign instanceof Uint8Array) {
|
||||||
|
dataToSign = new TextDecoder("utf-8").decode(dataToSign as Uint8Array);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("credentialId", credentialId);
|
||||||
|
const options = {
|
||||||
|
challenge: new TextEncoder().encode(dataToSign).buffer,
|
||||||
|
//allowCredentials: [{ id: credentialId, type: "public-key" }],
|
||||||
|
userVerification: "preferred",
|
||||||
|
};
|
||||||
|
|
||||||
|
const assertion = await navigator.credentials.get({ publicKey: options });
|
||||||
|
console.log("assertion", assertion);
|
||||||
|
|
||||||
|
const authenticatorAssertionResponse = assertion?.response;
|
||||||
|
this.clientDataJsonDecoded = JSON.parse(
|
||||||
new TextDecoder("utf-8").decode(
|
new TextDecoder("utf-8").decode(
|
||||||
authenticatorAssertionResponse.clientDataJSON,
|
authenticatorAssertionResponse.clientDataJSON,
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
console.log("clientDataJSON decoded", this.clientDataJsonDecoded);
|
||||||
return {
|
this.authenticatorData = authenticatorAssertionResponse.authenticatorData;
|
||||||
signature: authenticatorAssertionResponse.signature,
|
console.log("authenticator data", this.authenticatorData);
|
||||||
clientDataJSON: authenticatorAssertionResponse.clientDataJSON,
|
return authenticatorAssertionResponse.signature;
|
||||||
authenticatorData: authenticatorAssertionResponse.authenticatorData,
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function verifyJwt(
|
export async function verifyJwt(
|
||||||
jwt: string,
|
jwt: string,
|
||||||
issuerDid: string, // eslint-disable-line @typescript-eslint/no-unused-vars
|
credId: Base64URLString,
|
||||||
publicKey: JWK, // eslint-disable-line @typescript-eslint/no-unused-vars
|
rawId: Uint8Array,
|
||||||
|
authenticatorData: ArrayBuffer,
|
||||||
|
clientDataJSON: object,
|
||||||
|
publicKey: Uint8Array,
|
||||||
|
signature: Base64URLString,
|
||||||
) {
|
) {
|
||||||
|
const options: PublicKeyCredentialRequestOptionsJSON =
|
||||||
|
await generateAuthenticationOptions({
|
||||||
|
rpID: window.location.hostname,
|
||||||
|
// Require users to use a previously-registered authenticator
|
||||||
|
// allowCredentials: userPasskeys.map(passkey => ({
|
||||||
|
// id: passkey.id,
|
||||||
|
// transports: passkey.transports,
|
||||||
|
// })),
|
||||||
|
});
|
||||||
|
console.log("authentication options", options);
|
||||||
|
|
||||||
|
const clientAuth = await startAuthentication(options);
|
||||||
|
console.log("clientAuth", clientAuth);
|
||||||
|
|
||||||
|
const verfOpts: VerifyAuthenticationResponseOpts = {
|
||||||
|
response: clientAuth,
|
||||||
|
authenticator: {
|
||||||
|
credentialID: credId,
|
||||||
|
credentialPublicKey: publicKey,
|
||||||
|
counter: 0,
|
||||||
|
},
|
||||||
|
expectedChallenge: () => true, // options.challenge doesn't work
|
||||||
|
expectedOrigin: window.location.origin,
|
||||||
|
expectedRPID: window.location.hostname,
|
||||||
|
};
|
||||||
|
console.log("verfOpts", verfOpts);
|
||||||
|
const verificationFromClient = await verifyAuthenticationResponse(verfOpts);
|
||||||
|
console.log("client auth verification", verificationFromClient);
|
||||||
|
|
||||||
|
const authData = toBase64Url(Buffer.from(authenticatorData));
|
||||||
|
const bufferizedJson = toBase64Url(
|
||||||
|
new TextEncoder().encode(JSON.stringify(clientDataJSON)),
|
||||||
|
);
|
||||||
|
const authOpts: VerifyAuthenticationResponseOpts = {
|
||||||
|
response: {
|
||||||
|
id: credId,
|
||||||
|
rawId: toBase64Url(rawId),
|
||||||
|
response: {
|
||||||
|
authenticatorData: authData,
|
||||||
|
clientDataJSON: bufferizedJson,
|
||||||
|
signature: signature,
|
||||||
|
},
|
||||||
|
clientExtensionResults: {},
|
||||||
|
type: "public-key",
|
||||||
|
},
|
||||||
|
expectedChallenge: () => true, // options.challenge doesn't work
|
||||||
|
expectedOrigin: window.location.origin,
|
||||||
|
expectedRPID: window.location.hostname,
|
||||||
|
authenticator: {
|
||||||
|
credentialID: credId,
|
||||||
|
credentialPublicKey: publicKey,
|
||||||
|
counter: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const verification = await verifyAuthenticationResponse(authOpts);
|
||||||
|
console.log("auth verification", verification);
|
||||||
|
|
||||||
const decoded = verifyJWT(jwt, {
|
const decoded = verifyJWT(jwt, {
|
||||||
resolver: new Resolver({ peer: peerDidToDidDocument }),
|
resolver: new Resolver({ peer: peerDidToDidDocument }),
|
||||||
});
|
});
|
||||||
@@ -266,7 +339,7 @@ export async function verifyJwt(
|
|||||||
async function peerDidToDidDocument(did: string): Promise<DIDResolutionResult> {
|
async function peerDidToDidDocument(did: string): Promise<DIDResolutionResult> {
|
||||||
if (!did.startsWith("did:peer:0z")) {
|
if (!did.startsWith("did:peer:0z")) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"This only verifies a peer DID method 0 encoded base58btc.",
|
"This only verifies a peer DID, method 0, encoded base58btc.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// this is basically hard-coded based on the results from the @aviarytech/did-peer resolver
|
// this is basically hard-coded based on the results from the @aviarytech/did-peer resolver
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
Only click "No" if you have a seed of 12 or 24 words generated
|
Only click "No" if you have a seed of 12 or 24 words generated
|
||||||
elsewhere.
|
elsewhere.
|
||||||
</p>
|
</p>
|
||||||
|
<input type="text" v-model="savedCredentialId" class="border" />
|
||||||
<a
|
<a
|
||||||
@click="onClickYes()"
|
@click="onClickYes()"
|
||||||
class="block w-full text-center text-lg uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md mb-2"
|
class="block w-full text-center text-lg uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md mb-2"
|
||||||
@@ -62,14 +63,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { Base64URLString } from "@simplewebauthn/types";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
|
||||||
import { accountsDB } from "@/db/index";
|
import { accountsDB } from "@/db/index";
|
||||||
import { generateRandomBytes } from "@/libs/crypto";
|
import { generateRandomBytes } from "@/libs/crypto";
|
||||||
import {
|
import {
|
||||||
createJwt,
|
|
||||||
createPeerDid,
|
createPeerDid,
|
||||||
JWK,
|
JWK,
|
||||||
|
PeerSetup,
|
||||||
registerCredential,
|
registerCredential,
|
||||||
verifyJwt,
|
verifyJwt,
|
||||||
} from "@/libs/didPeer";
|
} from "@/libs/didPeer";
|
||||||
@@ -78,10 +80,14 @@ import {
|
|||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class StartView extends Vue {
|
export default class StartView extends Vue {
|
||||||
|
authenticatorData?: ArrayBuffer;
|
||||||
|
credId?: Base64URLString;
|
||||||
numAccounts = 0;
|
numAccounts = 0;
|
||||||
publicKeyJwk?: JWK;
|
publicKeyJwk?: JWK;
|
||||||
publicKeyBytes?: Uint8Array;
|
publicKeyBytes?: Uint8Array;
|
||||||
userId?: Uint8Array;
|
rawId?: Uint8Array;
|
||||||
|
savedCredentialId = "";
|
||||||
|
userId?: ArrayBuffer;
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
await accountsDB.open();
|
await accountsDB.open();
|
||||||
@@ -89,23 +95,30 @@ export default class StartView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onClickYes() {
|
public async onClickYes() {
|
||||||
this.userId = generateRandomBytes(16);
|
this.userId = generateRandomBytes(16).buffer;
|
||||||
const encodedUserId = new TextDecoder("utf-8").decode(this.userId);
|
const encodedUserId = new TextDecoder("utf-8").decode(this.userId);
|
||||||
console.log("encodedUserId", encodedUserId);
|
console.log("encodedUserId", encodedUserId);
|
||||||
|
|
||||||
const cred = await registerCredential(this.userId, generateRandomBytes(32));
|
const challenge = generateRandomBytes(32);
|
||||||
|
const cred = await registerCredential(
|
||||||
|
this.userId as Uint8Array,
|
||||||
|
challenge as Uint8Array,
|
||||||
|
);
|
||||||
console.log("public key", cred);
|
console.log("public key", cred);
|
||||||
this.publicKeyJwk = cred.publicKeyJwk;
|
this.publicKeyJwk = cred.publicKeyJwk;
|
||||||
this.publicKeyBytes = cred.publicKeyBytes;
|
this.publicKeyBytes = cred.publicKeyBytes;
|
||||||
this.userId = cred.rawId as Uint8Array;
|
this.credId = cred.credId as string;
|
||||||
|
this.rawId = cred.rawId as Uint8Array;
|
||||||
|
this.savedCredentialId = this.credId;
|
||||||
//this.$router.push({ name: "new-identifier" });
|
//this.$router.push({ name: "new-identifier" });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async onClickNo() {
|
public async onClickNo() {
|
||||||
const credArrBuff = this.userId;
|
|
||||||
const did = createPeerDid(this.publicKeyBytes as Uint8Array);
|
const did = createPeerDid(this.publicKeyBytes as Uint8Array);
|
||||||
console.log("did", did);
|
console.log("did", did);
|
||||||
const jwt = await createJwt({ a: 1 }, did, credArrBuff as Uint8Array);
|
const payload = { a: 1 };
|
||||||
|
const peerSetup = new PeerSetup();
|
||||||
|
const jwt = await peerSetup.createJwt(payload, did, this.credId as string);
|
||||||
console.log("jwt", jwt);
|
console.log("jwt", jwt);
|
||||||
const jwt4url = jwt
|
const jwt4url = jwt
|
||||||
.replace(/\+/g, "-")
|
.replace(/\+/g, "-")
|
||||||
@@ -113,7 +126,16 @@ export default class StartView extends Vue {
|
|||||||
.replace(/=+$/, "");
|
.replace(/=+$/, "");
|
||||||
console.log("jwt4url", jwt4url);
|
console.log("jwt4url", jwt4url);
|
||||||
|
|
||||||
const decoded = await verifyJwt(jwt4url, did, this.publicKey as JWK);
|
const signature = jwt4url.split(".")[2];
|
||||||
|
const decoded = await verifyJwt(
|
||||||
|
jwt4url,
|
||||||
|
this.credId as Base64URLString,
|
||||||
|
this.rawId as Uint8Array,
|
||||||
|
peerSetup.authenticatorData as ArrayBuffer,
|
||||||
|
peerSetup.clientDataJsonDecoded,
|
||||||
|
this.publicKeyBytes as Uint8Array,
|
||||||
|
signature,
|
||||||
|
);
|
||||||
console.log("decoded", decoded);
|
console.log("decoded", decoded);
|
||||||
//this.$router.push({ name: "import-account" });
|
//this.$router.push({ name: "import-account" });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user