UNPKG

signify-ts

Version:

Signing at the edge for KERI, ACDC, and KERIA

187 lines (160 loc) 5.06 kB
import { DigiDex, Matter, MatterArgs, MtrDex } from './matter'; import { deversify, Dict, Serials } from './core'; import { EmptyMaterialError } from './kering'; import { dumps, sizeify } from './serder'; import { Buffer } from 'buffer'; import { blake3 } from '@noble/hashes/blake3'; const Dummy = '#'; export enum Ids { d = 'd', } class Digestage { public klas: any = undefined; public size: number | undefined = 0; public length: number | undefined = 0; constructor(klas: any, size?: number, length?: number) { this.klas = klas; this.size = size; this.length = length; } } export class Saider extends Matter { static Digests = new Map<string, Digestage>([ [ MtrDex.Blake3_256, new Digestage(Saider._derive_blake3_256, undefined, undefined), ], ]); constructor( { raw, code, qb64b, qb64, qb2 }: MatterArgs, sad?: Dict<any>, kind?: Serials, label: string = Ids.d ) { try { super({ raw, code, qb64b, qb64, qb2 }); } catch (e) { if (e instanceof EmptyMaterialError) { if (sad == undefined || !(label in sad)) { throw e; } if (code == undefined) { if (sad[label] != '') { super({ qb64: sad[label], code: code }); code = this.code; } else { code = MtrDex.Blake3_256; } } if (!DigiDex.has(code)) { throw new Error(`Unsupported digest code = ${code}`); } [raw] = Saider._derive({ ...sad }, code, kind, label); super({ raw: raw, code: code }); } else { throw e; } } if (!this.digestive) { throw new Error(`Unsupported digest code = ${this.code}.`); } } static _derive_blake3_256( ser: Uint8Array, _digest_size: number, _length: number ) { return Buffer.from(blake3.create({ dkLen: 32 }).update(ser).digest()); } private static _derive( sad: Dict<any>, code: string, kind: Serials | undefined, label: string ): [Uint8Array, Dict<any>] { if (!DigiDex.has(code) || !Saider.Digests.has(code)) { throw new Error(`Unsupported digest code = ${code}.`); } sad = { ...sad }; sad[label] = ''.padStart(Matter.Sizes.get(code)!.fs!, Dummy); if ('v' in sad) { [, , kind, sad] = sizeify(sad, kind); } const ser = { ...sad }; const digestage = Saider.Digests.get(code); const cpa = Saider._serialze(ser, kind); const args: any[] = []; if (digestage!.size != undefined) { args.push(digestage!.size); } if (digestage!.length != undefined) { args.push(digestage!.length); } return [digestage!.klas(cpa, ...args), sad]; } public derive( sad: Dict<any>, code: string, kind: Serials | undefined, label: string ): [Uint8Array, Dict<any>] { code = code != undefined ? code : this.code; return Saider._derive(sad, code, kind, label); } public verify( sad: Dict<any>, prefixed: boolean = false, versioned: boolean = false, kind?: Serials, label: string = Ids.d ): boolean { try { const [raw, dsad] = Saider._derive(sad, this.code, kind, label); const saider = new Saider({ raw: raw, code: this.code }); if (this.qb64 != saider.qb64) { return false; } if ('v' in sad && versioned) { if (sad['v'] != dsad['v']) { return false; } } if (prefixed && sad[label] != this.qb64) { return false; } } catch (e) { return false; } return true; } private static _serialze(sad: Dict<any>, kind?: Serials): string { let knd = Serials.JSON; if ('v' in sad) { [, knd] = deversify(sad['v']); } if (kind == undefined) { kind = knd; } return dumps(sad, kind); } public static saidify( sad: Dict<any>, code: string = MtrDex.Blake3_256, kind: Serials = Serials.JSON, label: string = Ids.d ): [Saider, Dict<any>] { if (!(label in sad)) { throw new Error(`Missing id field labeled=${label} in sad.`); } let raw; [raw, sad] = Saider._derive(sad, code, kind, label); const saider = new Saider( { raw: raw, code: code }, undefined, kind, label ); sad[label] = saider.qb64; return [saider, sad]; } }