Browse Source

Update with our own SimpleSigner

kb/add-usage-guide
Matthew Aaron Raymer 2 years ago
parent
commit
150b35c4c7
  1. 56
      src/libs/crypto/index.ts
  2. 76
      src/views/NewEditProjectView.vue

56
src/libs/crypto/index.ts

@ -5,8 +5,44 @@ import { entropyToMnemonic } from "ethereum-cryptography/bip39";
import { wordlist } from "ethereum-cryptography/bip39/wordlists/english"; import { wordlist } from "ethereum-cryptography/bip39/wordlists/english";
import { HDNode } from "@ethersproject/hdnode"; import { HDNode } from "@ethersproject/hdnode";
import * as didJwt from "did-jwt"; import * as didJwt from "did-jwt";
import { Signer } from "did-jwt";
import * as u8a from "uint8arrays"; import * as u8a from "uint8arrays";
export function hexToBytes(s: string): Uint8Array {
const input = s.startsWith("0x") ? s.substring(2) : s;
return u8a.fromString(input.toLowerCase(), "base16");
}
export function fromJose(signature: string): {
r: string;
s: string;
recoveryParam?: number;
} {
const signatureBytes: Uint8Array = base64ToBytes(signature);
if (signatureBytes.length < 64 || signatureBytes.length > 65) {
throw new TypeError(
`Wrong size for signature. Expected 64 or 65 bytes, but got ${signatureBytes.length}`
);
}
const r = bytesToHex(signatureBytes.slice(0, 32));
const s = bytesToHex(signatureBytes.slice(32, 64));
const recoveryParam =
signatureBytes.length === 65 ? signatureBytes[64] : undefined;
return { r, s, recoveryParam };
}
export function bytesToHex(b: Uint8Array): string {
return u8a.toString(b, "base16");
}
export function base64ToBytes(s: string): Uint8Array {
const inputBase64Url = s
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
return u8a.fromString(inputBase64Url, "base64url");
}
/** /**
* *
* *
@ -111,3 +147,23 @@ export const sign = async (privateKeyHex: string) => {
return signer; return signer;
}; };
/**
* The SimpleSigner returns a configured function for signing data.
*
* @example
* const signer = SimpleSigner(process.env.PRIVATE_KEY)
* signer(data, (err, signature) => {
* ...
* })
*
* @param {String} hexPrivateKey a hex encoded private key
* @return {Function} a configured signer function
*/
export const SimpleSigner = async (hexPrivateKey: string): Promise<Signer> => {
const signer = didJwt.ES256KSigner(hexToBytes(hexPrivateKey), true);
return async (data) => {
const signature = (await signer(data)) as string;
return fromJose(signature);
};
};

76
src/views/NewEditProjectView.vue

@ -74,8 +74,9 @@
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import { AppString } from "@/constants/app"; import { AppString } from "@/constants/app";
import { db } from "../db"; import { db } from "../db";
import { accessToken, sign } from "@/libs/crypto"; import { accessToken, SimpleSigner } from "@/libs/crypto";
import * as didJwt from "did-jwt"; import * as didJwt from "did-jwt";
import { IIdentifier } from "@veramo/core";
@Options({ @Options({
components: {}, components: {},
@ -84,40 +85,39 @@ export default class NewEditProjectView extends Vue {
projectName = ""; projectName = "";
description = ""; description = "";
public async onSaveProjectClick() { private async SaveProject(identity: IIdentifier) {
await db.open(); const address = identity.did;
const num_accounts = await db.accounts.count(); // Make a claim
if (num_accounts === 0) { const vcClaim = {
console.log("Problem! Should have a profile!"); "@context": "https://schema.org",
} else { "@type": "PlanAction",
const accounts = await db.accounts.toArray(); identifier: address,
const identity = JSON.parse(accounts[0].identity); name: this.projectName,
const address = identity.did; description: this.description,
// Make a claim };
const vcClaim = { // Make a payload for the claim
"@context": "https://schema.org", const vcPayload = {
"@type": "PlanAction", sub: "PlanAction",
identifier: address, vc: {
name: this.projectName, "@context": ["https://www.w3.org/2018/credentials/v1"],
description: this.description, type: ["VerifiableCredential"],
}; credentialSubject: vcClaim,
// Make a payload for the claim },
const vcPayload = { };
sub: "PlanAction", // create a signature using private key of identity
vc: { if (
"@context": ["https://www.w3.org/2018/credentials/v1"], identity.keys[0].privateKeyHex !== "undefined" &&
type: ["VerifiableCredential"], identity.keys[0].privateKeyHex !== null
credentialSubject: vcClaim, ) {
}, // eslint-disable-next-line
}; const privateKeyHex: string = identity.keys[0].privateKeyHex!;
// create a signature using private key of identity const signer = await SimpleSigner(privateKeyHex);
const signer = await sign(identity.keys[0].privateKeyHex);
const alg = undefined; const alg = undefined;
// create a JWT for the request // create a JWT for the request
const vcJwt: string = await didJwt.createJWT(vcPayload, { const vcJwt: string = await didJwt.createJWT(vcPayload, {
alg, alg: alg,
issuer: identity, issuer: identity.did,
signer, signer: signer,
}); });
// Make the xhr request payload // Make the xhr request payload
@ -140,6 +140,18 @@ export default class NewEditProjectView extends Vue {
} }
} }
public async onSaveProjectClick() {
await db.open();
const num_accounts = await db.accounts.count();
if (num_accounts === 0) {
console.log("Problem! Should have a profile!");
} else {
const accounts = await db.accounts.toArray();
const identity = JSON.parse(accounts[0].identity);
this.SaveProject(identity);
}
}
public onCancelClick() { public onCancelClick() {
this.$router.back(); this.$router.back();
} }

Loading…
Cancel
Save