derive DID for issuer
This commit is contained in:
@@ -10,7 +10,7 @@ See [project.task.yaml](project.task.yaml) for current priorities.
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
We have pkgx.dev set up in package.json, so you can use `dev` to set up the dev environment.
|
We like pkgx: `sh <(curl https://pkgx.sh) +npm sh`
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "TimeSafari",
|
"name": "TimeSafari",
|
||||||
"version": "0.3.14-beta",
|
"version": "0.3.14-beta",
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"serve": "vite preview",
|
"serve": "vite preview",
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { DEFAULT_DID_PROVIDER_NAME } from "../veramo/setup";
|
|||||||
|
|
||||||
export const DEFAULT_ROOT_DERIVATION_PATH = "m/84737769'/0'/0'/0'";
|
export const DEFAULT_ROOT_DERIVATION_PATH = "m/84737769'/0'/0'/0'";
|
||||||
|
|
||||||
|
export const LOCAL_KMS_NAME = "local";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -31,7 +33,7 @@ export const newIdentifier = (
|
|||||||
keys: [
|
keys: [
|
||||||
{
|
{
|
||||||
kid: publicHex,
|
kid: publicHex,
|
||||||
kms: "local",
|
kms: LOCAL_KMS_NAME,
|
||||||
meta: { derivationPath: derivationPath },
|
meta: { derivationPath: derivationPath },
|
||||||
privateKeyHex: privateHex,
|
privateKeyHex: privateHex,
|
||||||
publicKeyHex: publicHex,
|
publicKeyHex: publicHex,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Buffer } from "buffer/";
|
|||||||
import { decode as cborDecode } from "cbor-x";
|
import { decode as cborDecode } from "cbor-x";
|
||||||
import { createJWS, JWTPayload, verifyJWT } from "did-jwt";
|
import { createJWS, JWTPayload, verifyJWT } from "did-jwt";
|
||||||
import { getResolver } from "@veramo/did-provider-peer";
|
import { getResolver } from "@veramo/did-provider-peer";
|
||||||
|
import { bytesToMultibase } from "@veramo/utils";
|
||||||
|
|
||||||
import { generateRandomBytes } from "@/libs/crypto";
|
import { generateRandomBytes } from "@/libs/crypto";
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ export async function registerCredential(
|
|||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
id: userId,
|
id: userId,
|
||||||
name: "current-user",
|
name: "Current-User",
|
||||||
displayName: "Current User",
|
displayName: "Current User",
|
||||||
},
|
},
|
||||||
pubKeyCredParams: [
|
pubKeyCredParams: [
|
||||||
@@ -63,21 +64,27 @@ export async function registerCredential(
|
|||||||
);
|
);
|
||||||
console.log("attestationObject", attestationObject);
|
console.log("attestationObject", attestationObject);
|
||||||
|
|
||||||
const authData = new Uint8Array(attestationObject.authData);
|
const publicKeyCose = extractPublicKeyCose(attestationObject.authData);
|
||||||
const publicKey = extractPublicKey(authData);
|
const publicKeyJwk = extractPublicKeyJwk(attestationObject.authData);
|
||||||
|
|
||||||
return { rawId: credential?.rawId, publicKey };
|
return { rawId: credential?.rawId, publicKeyJwk, publicKeyCose };
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractPublicKey(authData: Uint8Array) {
|
function extractPublicKeyJwk(authData: Uint8Array) {
|
||||||
// Extract the public key from authData using appropriate parsing
|
const publicKeyCose = extractPublicKeyCose(authData); // Example position
|
||||||
// This involves extracting the COSE key format and converting it to JWK
|
|
||||||
// For simplicity, we'll assume the public key is at a certain position in authData
|
|
||||||
const publicKeyCose = authData.slice(authData.length - 77); // Example position
|
|
||||||
const publicKeyJwk = coseToJwk(publicKeyCose);
|
const publicKeyJwk = coseToJwk(publicKeyCose);
|
||||||
return publicKeyJwk;
|
return publicKeyJwk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractPublicKeyCose(authData: Uint8Array) {
|
||||||
|
// Extract the public key from authData using appropriate parsing.
|
||||||
|
// This involves extracting the COSE key format.
|
||||||
|
// For simplicity, we'll assume the public key is at a certain position in authData.
|
||||||
|
// Alternatively, see last answer here: https://chatgpt.com/share/78a5c91d-099d-46dc-aa6d-fc0c916509fa
|
||||||
|
const publicKeyCose = authData.slice(authData.length - 77);
|
||||||
|
return publicKeyCose;
|
||||||
|
}
|
||||||
|
|
||||||
function coseToJwk(coseKey: Uint8Array) {
|
function coseToJwk(coseKey: Uint8Array) {
|
||||||
// Convert COSE key format to JWK
|
// Convert COSE key format to JWK
|
||||||
// This is simplified and needs appropriate parsing and conversion logic
|
// This is simplified and needs appropriate parsing and conversion logic
|
||||||
@@ -89,6 +96,17 @@ function coseToJwk(coseKey: Uint8Array) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createPeerDid(publicKeyCose: 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(
|
||||||
|
publicKeyCose,
|
||||||
|
"base58btc",
|
||||||
|
"ed25519-pub",
|
||||||
|
);
|
||||||
|
return "did:peer:0" + methodSpecificId;
|
||||||
|
}
|
||||||
|
|
||||||
export async function createJwt(
|
export async function createJwt(
|
||||||
payload: object,
|
payload: object,
|
||||||
issuerDid: string,
|
issuerDid: string,
|
||||||
@@ -150,10 +168,15 @@ async function generateWebAuthnSignature(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function verifyJwt(jwt: string, publicKey: JWK) {
|
export async function verifyJwt(
|
||||||
|
jwt: string,
|
||||||
|
issuerDid: string,
|
||||||
|
publicKey: JWK,
|
||||||
|
) {
|
||||||
const decoded = verifyJWT(jwt, {
|
const decoded = verifyJWT(jwt, {
|
||||||
didAuthenticator: {
|
didAuthenticator: {
|
||||||
authenticators: [{ publicKeyJwk: publicKey }],
|
authenticators: [{ publicKeyJwk: publicKey }],
|
||||||
|
issuer: issuerDid,
|
||||||
},
|
},
|
||||||
resolver: getResolver(),
|
resolver: getResolver(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -66,14 +66,21 @@ 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 { createJwt, JWK, registerCredential, verifyJwt } from "@/libs/didPeer";
|
import {
|
||||||
|
createJwt,
|
||||||
|
createPeerDid,
|
||||||
|
JWK,
|
||||||
|
registerCredential,
|
||||||
|
verifyJwt,
|
||||||
|
} from "@/libs/didPeer";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class StartView extends Vue {
|
export default class StartView extends Vue {
|
||||||
numAccounts = 0;
|
numAccounts = 0;
|
||||||
publicKey?: JWK;
|
publicKeyJwk?: JWK;
|
||||||
|
publicKeyCose?: Uint8Array;
|
||||||
userId?: Uint8Array;
|
userId?: Uint8Array;
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@@ -88,15 +95,17 @@ export default class StartView extends Vue {
|
|||||||
|
|
||||||
const cred = await registerCredential(this.userId, generateRandomBytes(32));
|
const cred = await registerCredential(this.userId, generateRandomBytes(32));
|
||||||
console.log("public key", cred);
|
console.log("public key", cred);
|
||||||
this.publicKey = cred.publicKey;
|
this.publicKeyJwk = cred.publicKeyJwk;
|
||||||
|
this.publicKeyCose = cred.publicKeyCose;
|
||||||
this.userId = cred.rawId as Uint8Array;
|
this.userId = cred.rawId as Uint8Array;
|
||||||
//this.$router.push({ name: "new-identifier" });
|
//this.$router.push({ name: "new-identifier" });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async onClickNo() {
|
public async onClickNo() {
|
||||||
const credArrBuff = this.userId;
|
const credArrBuff = this.userId;
|
||||||
|
const did = createPeerDid(this.publicKeyCose as Uint8Array);
|
||||||
const jwt = await createJwt({ a: 1 }, "issuerDid", credArrBuff);
|
console.log("did", did);
|
||||||
|
const jwt = await createJwt({ a: 1 }, did, credArrBuff as Uint8Array);
|
||||||
console.log("jwt", jwt);
|
console.log("jwt", jwt);
|
||||||
const jwt4url = jwt
|
const jwt4url = jwt
|
||||||
.replace(/\+/g, "-")
|
.replace(/\+/g, "-")
|
||||||
@@ -104,7 +113,7 @@ export default class StartView extends Vue {
|
|||||||
.replace(/=+$/, "");
|
.replace(/=+$/, "");
|
||||||
console.log("jwt4url", jwt4url);
|
console.log("jwt4url", jwt4url);
|
||||||
|
|
||||||
const decoded = await verifyJwt(jwt, this.publicKey as JWK);
|
const decoded = await verifyJwt(jwt4url, did, this.publicKey as JWK);
|
||||||
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