UNPKG

signify-ts

Version:

Signing at the edge for KERI, ACDC, and KERIA

234 lines (201 loc) 6.93 kB
import { Matter, MatterArgs, MtrDex } from './matter'; import { EmptyMaterialError } from './kering'; import { Dict, Ilks } from './core'; import { sizeify } from './serder'; import { Verfer } from './verfer'; import { Buffer } from 'buffer'; import { blake3 } from '@noble/hashes/blake3'; const Dummy: string = '#'; export class Prefixer extends Matter { private readonly _derive: Function | undefined; private readonly _verify: Function | undefined; constructor({ raw, code, qb64b, qb64, qb2 }: MatterArgs, ked?: Dict<any>) { try { super({ raw, code, qb64b, qb64, qb2 }); } catch (e) { if (e instanceof EmptyMaterialError) { if (ked == undefined || (code == undefined && !('i' in ked))) { throw e; } if (code == undefined) { super({ qb64: ked['i'], code: code }); code = this.code; } let _derive; if (code == MtrDex.Ed25519N) { _derive = Prefixer._derive_ed25519N; } else if (code == MtrDex.Ed25519) { _derive = Prefixer._derive_ed25519; } else if (code == MtrDex.Blake3_256) { _derive = Prefixer._derive_blake3_256; } else { throw new Error(`Unsupported code = ${code} for prefixer.`); } [raw, code] = _derive(ked); super({ raw: raw, code: code }); this._derive = _derive; } else { throw e; } } if (this.code == MtrDex.Ed25519N) { this._verify = this._verify_ed25519N; } else if (this.code == MtrDex.Ed25519) { this._verify = this._verify_ed25519; } else if (this.code == MtrDex.Blake3_256) { this._verify = this._verify_blake3_256; } else { throw new Error(`Unsupported code = ${code} for prefixer.`); } } derive(ked: Dict<any>): [Uint8Array, string] { if (ked['i'] != Ilks.icp) { throw new Error( `Non-incepting ilk ${ked['i']} for prefix derivation` ); } return this._derive!(ked); } verify(ked: Dict<any>, prefixed: boolean = false): boolean { if (ked['i'] != Ilks.icp) { throw new Error( `Non-incepting ilk ${ked['i']} for prefix derivation` ); } return this._verify!(ked, this.qb64, prefixed); } static _derive_ed25519N(ked: Dict<any>): [Uint8Array, string] { let verfer; const keys = ked['k']; if (keys.length != 1) { throw new Error( `Basic derivation needs at most 1 key got ${keys.length} keys instead` ); } try { verfer = new Verfer({ qb64: keys[0] }); } catch (e) { throw new Error(`Error extracting public key = ${e}`); } if (verfer.code != MtrDex.Ed25519N) { throw new Error(`Mismatch derivation code = ${verfer.code}`); } const next = 'n' in ked ? ked['n'] : []; if (verfer.code == MtrDex.Ed25519N && next.length > 0) { throw new Error( `Non-empty nxt = ${next} for non-transferable code = ${verfer.code}` ); } const backers = 'b' in ked ? ked['b'] : []; if (verfer.code == MtrDex.Ed25519N && backers.length > 0) { throw new Error( `Non-empty b =${backers} for non-transferable code = ${verfer.code}` ); } const anchor = 'a' in ked ? ked['a'] : []; if (verfer.code == MtrDex.Ed25519N && anchor.length > 0) { throw new Error( `Non-empty a = ${verfer.code} for non-transferable code = ${verfer.code}` ); } return [verfer.raw, verfer.code]; } static _derive_ed25519(ked: Dict<any>): [Uint8Array, string] { let verfer; const keys = ked['k']; if (keys.length != 1) { throw new Error( `Basic derivation needs at most 1 key got ${keys.length} keys instead` ); } try { verfer = new Verfer({ qb64: keys[0] }); } catch (e) { throw new Error(`Error extracting public key = ${e}`); } if (verfer.code in [MtrDex.Ed25519]) { throw new Error(`Mismatch derivation code = ${verfer.code}`); } return [verfer.raw, verfer.code]; } static _derive_blake3_256(ked: Dict<any>): [Uint8Array, string] { const kd = ked; const ilk = ked['t']; if (![Ilks.icp, Ilks.dip, Ilks.vcp, Ilks.dip].includes(ilk)) { throw new Error(`Invalid ilk = ${ilk} to derive pre.`); } kd['i'] = ''.padStart(Matter.Sizes.get(MtrDex.Blake3_256)!.fs!, Dummy); kd['d'] = ked['i']; const [raw] = sizeify(ked); const dig = Buffer.from( blake3.create({ dkLen: 32 }).update(raw).digest() ); return [dig, MtrDex.Blake3_256]; } _verify_ed25519N( ked: Dict<any>, pre: string, prefixed: boolean = false ): boolean { try { const keys = ked['k']; if (keys.length != 1) { return false; } if (keys[0] != pre) { return false; } if (prefixed && ked['i'] != pre) { return false; } const next = 'n' in ked ? ked['n'] : []; if (next.length > 0) { // must be empty return false; } } catch (e) { return false; } return true; } _verify_ed25519( ked: Dict<any>, pre: string, prefixed: boolean = false ): boolean { try { const keys = ked['k']; if (keys.length != 1) { return false; } if (keys[0] != pre) { return false; } if (prefixed && ked['i'] != pre) { return false; } } catch (e) { return false; } return true; } _verify_blake3_256( ked: Dict<any>, pre: string, prefixed: boolean = false ): boolean { try { const [raw] = Prefixer._derive_blake3_256(ked); const crymat = new Matter({ raw: raw, code: MtrDex.Blake3_256 }); if (crymat.qb64 != pre) { return false; } if (prefixed && ked['i'] != pre) { return false; } } catch (e) { return false; } return true; } }