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.
150 lines
4.3 KiB
150 lines
4.3 KiB
import { IIdentifier } from "@veramo/core";
|
|
import { DEFAULT_DID_PROVIDER_NAME } from "../veramo/setup";
|
|
import { getRandomBytesSync } from "ethereum-cryptography/random";
|
|
import { entropyToMnemonic } from "ethereum-cryptography/bip39";
|
|
import { wordlist } from "ethereum-cryptography/bip39/wordlists/english";
|
|
import { HDNode } from "@ethersproject/hdnode";
|
|
import * as didJwt from "did-jwt";
|
|
import * as u8a from "uint8arrays";
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @param {string} address
|
|
* @param {string} publicHex
|
|
* @param {string} privateHex
|
|
* @param {string} derivationPath
|
|
* @return {*} {Omit<IIdentifier, 'provider'>}
|
|
*/
|
|
export const newIdentifier = (
|
|
address: string,
|
|
publicHex: string,
|
|
privateHex: string,
|
|
derivationPath: string
|
|
): Omit<IIdentifier, keyof "provider"> => {
|
|
return {
|
|
did: DEFAULT_DID_PROVIDER_NAME + ":" + address,
|
|
keys: [
|
|
{
|
|
kid: publicHex,
|
|
kms: "local",
|
|
meta: { derivationPath: derivationPath },
|
|
privateKeyHex: privateHex,
|
|
publicKeyHex: publicHex,
|
|
type: "Secp256k1",
|
|
},
|
|
],
|
|
provider: DEFAULT_DID_PROVIDER_NAME,
|
|
services: [],
|
|
};
|
|
};
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @param {string} mnemonic
|
|
* @return {*} {[string, string, string, string]}
|
|
*/
|
|
export const deriveAddress = (
|
|
mnemonic: string
|
|
): [string, string, string, string] => {
|
|
const UPORT_ROOT_DERIVATION_PATH = "m/7696500'/0'/0'/0'";
|
|
mnemonic = mnemonic.trim().toLowerCase();
|
|
|
|
const hdnode: HDNode = HDNode.fromMnemonic(mnemonic);
|
|
const rootNode: HDNode = hdnode.derivePath(UPORT_ROOT_DERIVATION_PATH);
|
|
const privateHex = rootNode.privateKey.substring(2); // original starts with '0x'
|
|
const publicHex = rootNode.publicKey.substring(2); // original starts with '0x'
|
|
const address = rootNode.address;
|
|
|
|
return [address, privateHex, publicHex, UPORT_ROOT_DERIVATION_PATH];
|
|
};
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @return {*} {string}
|
|
*/
|
|
export const generateSeed = (): string => {
|
|
const entropy: Uint8Array = getRandomBytesSync(32);
|
|
const mnemonic = entropyToMnemonic(entropy, wordlist);
|
|
|
|
return mnemonic;
|
|
};
|
|
|
|
/**
|
|
* Retreive an access token
|
|
*
|
|
* @param {IIdentifier} identifier
|
|
* @return {*}
|
|
*/
|
|
export const accessToken = async (identifier: IIdentifier) => {
|
|
const did: string = identifier.did;
|
|
const privateKeyHex: string = identifier.keys[0].privateKeyHex as string;
|
|
|
|
const signer = SimpleSigner(privateKeyHex);
|
|
|
|
const nowEpoch = Math.floor(Date.now() / 1000);
|
|
const endEpoch = nowEpoch + 60; // add one minute
|
|
|
|
const tokenPayload = { exp: endEpoch, iat: nowEpoch, iss: did };
|
|
const alg = undefined; // defaults to 'ES256K', more standardized but harder to verify vs ES256K-R
|
|
const jwt: string = await didJwt.createJWT(tokenPayload, {
|
|
alg,
|
|
issuer: did,
|
|
signer,
|
|
});
|
|
return jwt;
|
|
};
|
|
|
|
export const sign = async (privateKeyHex: string) => {
|
|
const signer = SimpleSigner(privateKeyHex);
|
|
|
|
return signer;
|
|
};
|
|
|
|
/**
|
|
* Copied out of did-jwt since it's deprecated in that library.
|
|
*
|
|
* 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 function SimpleSigner(hexPrivateKey: string): didJwt.Signer {
|
|
const signer = didJwt.ES256KSigner(didJwt.hexToBytes(hexPrivateKey), true);
|
|
return async (data) => {
|
|
const signature = (await signer(data)) as string;
|
|
return fromJose(signature);
|
|
};
|
|
}
|
|
|
|
// from did-jwt/util; see SimpleSigner above
|
|
export function fromJose(signature: string): {
|
|
r: string;
|
|
s: string;
|
|
recoveryParam?: number;
|
|
} {
|
|
const signatureBytes: Uint8Array = didJwt.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 };
|
|
}
|
|
|
|
// from did-jwt/util; see SimpleSigner above
|
|
export function bytesToHex(b: Uint8Array): string {
|
|
return u8a.toString(b, "base16");
|
|
}
|
|
|