UNPKG

signify-ts

Version:

Signing at the edge for KERI, ACDC, and KERIA

1,184 lines (1,011 loc) 34.8 kB
import { Encrypter } from './encrypter'; import { Decrypter } from './decrypter'; import { Salter, Tier } from './salter'; import { Signer } from './signer'; import { Verfer } from './verfer'; import { MtrDex } from './matter'; import { Diger } from './diger'; import { Cigar } from './cigar'; import { Siger } from './siger'; import { b } from './core'; export enum Algos { randy = 'randy', salty = 'salty', group = 'group', extern = 'extern', } class PubLot { public pubs: Array<string> = new Array<string>(); // list qb64 public keys. public ridx: number = 0; // index of rotation (est event) that uses public key set public kidx: number = 0; // index of key in sequence of public keys public dt: string = ''; // datetime ISO8601 when key set created } class PreSit { public old: PubLot = new PubLot(); //previous publot public new: PubLot = new PubLot(); //newly current publot public nxt: PubLot = new PubLot(); //next public publot } class PrePrm { public pidx: number = 0; // prefix index for this keypair sequence public algo: Algos = Algos.salty; // salty default uses indices and salt to create new key pairs public salt: string = ''; // empty salt used for salty algo. public stem: string = ''; // default unique path stem for salty algo public tier: string = ''; // security tier for stretch index salty algo } class PubSet { pubs: Array<string> = new Array<string>(); // list qb64 public keys. } class PubPath { path: string = ''; code: string = ''; tier: string = Tier.high; temp: boolean = false; } class Keys { private readonly _signers: Array<Signer>; private readonly _paths?: Array<string>; constructor(signers: Array<Signer>, paths?: Array<string>) { this._signers = signers; if (paths != undefined) { if (signers.length != paths.length) { throw new Error( 'If paths are provided, they must be the same length as signers' ); } } this._paths = paths; } get paths(): Array<string> | undefined { return this._paths; } get signers(): Array<Signer> { return this._signers; } } export interface Creator { create( codes: Array<string> | undefined, count: number, code: string, transferable: boolean, pidx: number, ridx: number, kidx: number, temp: boolean ): Keys; salt: string; stem: string; tier: Tier; } export class RandyCreator implements Creator { create( codes: Array<string> | undefined = undefined, count: number = 1, code: string = MtrDex.Ed25519_Seed, transferable: boolean = true ): Keys { const signers = new Array<Signer>(); if (codes == undefined) { codes = new Array(count).fill(code); } codes.forEach(function (code) { signers.push( new Signer({ code: code, transferable: transferable }) ); }); return new Keys(signers); } get salt(): string { return ''; } get stem(): string { return ''; } get tier(): Tier { return '' as Tier; } } export class SaltyCreator implements Creator { public salter: Salter; private readonly _stem: string; constructor( salt: string | undefined = undefined, tier: Tier | undefined = undefined, stem: string | undefined = undefined ) { this.salter = new Salter({ qb64: salt, tier: tier }); this._stem = stem == undefined ? '' : stem; } get salt(): string { return this.salter.qb64; } get stem(): string { return this._stem; } get tier(): Tier { return this.salter.tier!; } create( codes: Array<string> | undefined = undefined, count: number = 1, code: string = MtrDex.Ed25519_Seed, transferable: boolean = true, pidx: number = 0, ridx: number = 0, kidx: number = 0, temp: boolean = false ): Keys { const signers = new Array<Signer>(); const paths = new Array<string>(); if (codes == undefined) { codes = new Array<string>(count).fill(code); } codes.forEach((code, idx) => { // Previuos definition of path // let path = this.stem + pidx.toString(16) + ridx.toString(16) + (kidx+idx).toString(16) const path = this.stem == '' ? pidx.toString(16) : this.stem + ridx.toString(16) + (kidx + idx).toString(16); signers.push( this.salter.signer(code, transferable, path, this.tier, temp) ); paths.push(path); }); return new Keys(signers, paths); } } export class Creatory { private readonly _make: any; constructor(algo: Algos = Algos.salty) { switch (algo) { case Algos.randy: this._make = this._makeRandy; break; case Algos.salty: this._make = this._makeSalty; break; default: throw new Error(`unsupported algo=${algo}`); } } make(...args: any[]): Creator { return this._make(...args); } _makeRandy(): Creator { return new RandyCreator(); } _makeSalty(...args: any[]): Creator { return new SaltyCreator(...args); } } export function openManager(passcode: string, salt?: string) { if (passcode.length < 21) { throw new Error('Bran (passcode seed material) too short.'); } const bran = MtrDex.Salt_128 + 'A' + passcode.substring(0, 21); // qb64 salt for seed const signer = new Salter({ qb64: bran }).signer( MtrDex.Ed25519_Seed, false ); const seed = signer.qb64; const aeid = signer.verfer.qb64; // lest it remove encryption let algo; const salter = salt != undefined ? new Salter({ qb64: salt }) : undefined; if (salt != undefined) { algo = Algos.salty; } else { algo = Algos.randy; } return new Manager({ seed: seed, aeid: aeid, algo: algo, salter: salter }); } export interface ManagerArgs { ks?: KeyStore | undefined; seed?: string | undefined; aeid?: string | undefined; pidx?: number | undefined; algo?: Algos | undefined; salter?: Salter | undefined; tier?: string | undefined; } export interface ManagerInceptArgs { icodes?: any | undefined; icount?: number; icode?: string; ncodes?: any | undefined; ncount?: number; ncode?: string; dcode?: string; algo?: Algos | undefined; salt?: string | undefined; stem?: string | undefined; tier?: string | undefined; rooted?: boolean; transferable?: boolean; temp?: boolean; } interface RotateArgs { pre: string; ncodes?: any | undefined; ncount?: number; ncode?: string; dcode?: string; transferable?: boolean; temp?: boolean; erase?: boolean; } interface SignArgs { ser: Uint8Array; pubs?: Array<string> | undefined; verfers?: Array<Verfer> | undefined; indexed?: boolean; indices?: Array<number> | undefined; ondices?: Array<number> | undefined; } export class Manager { private _seed?: string; private _salt?: string; private _encrypter: Encrypter | undefined; private _decrypter: Decrypter | undefined; private readonly _ks: KeyStore; constructor({ ks, seed, aeid, pidx, algo, salter, tier }: ManagerArgs) { this._ks = ks == undefined ? new Keeper() : ks; this._seed = seed; this._encrypter = undefined; this._decrypter = undefined; aeid = aeid == undefined ? undefined : aeid; pidx = pidx == undefined ? 0 : pidx; algo = algo == undefined ? Algos.salty : algo; const salt = salter?.qb64; tier = tier == undefined ? Tier.low : tier; if (this.pidx == undefined) { this.pidx = pidx; } if (this.algo == undefined) { this.algo = algo; } if (this.salt == undefined) { this.salt = salt; } if (this.tier == undefined) { this.tier = tier; } if (this.aeid == undefined) { this.updateAeid(aeid, this._seed); } } get ks(): KeyStore { return this._ks; } get encrypter(): Encrypter | undefined { return this._encrypter; } get decrypter(): Decrypter | undefined { return this._decrypter; } get seed(): string | undefined { return this._seed; } get aeid(): string | undefined { return this.ks.getGbls('aeid'); } get pidx(): number | undefined { const pidx = this.ks.getGbls('pidx'); if (pidx != undefined) { return parseInt(pidx, 16); } return undefined; } set pidx(pidx: number | undefined) { this.ks.pinGbls('pidx', pidx!.toString(16)); } get salt(): string | undefined { if (this._decrypter == undefined) { return this._salt; } else { const salt = this.ks.getGbls('salt'); return this._decrypter.decrypt(b(salt)).qb64; } } set salt(salt: string | undefined) { if (this._encrypter == undefined) { this._salt = salt; } else { salt = this._encrypter.encrypt(b(salt)).qb64; this.ks.pinGbls('salt', salt!); } } get tier(): string | undefined { return this.ks.getGbls('tier'); } set tier(tier: string | undefined) { this.ks.pinGbls('tier', tier!); } get algo(): Algos | undefined { const a = this.ks.getGbls('algo'); const ta = a as keyof typeof Algos; return Algos[ta]; } set algo(algo: Algos | undefined) { this.ks.pinGbls('algo', algo! as string); } private updateAeid(aeid: string | undefined, seed?: string) { if (this.aeid != undefined) { const seed = b(this._seed); if (this._seed == undefined || !this._encrypter?.verifySeed(seed)) { throw new Error(`Last seed missing or provided last seed " "not associated with last aeid=${this.aeid}.`); } } if (aeid != '' && aeid != undefined) { if (aeid != this.aeid) { this._encrypter = new Encrypter({}, b(aeid)); if (seed == undefined || !this._encrypter.verifySeed(b(seed))) { throw new Error(`Seed missing or provided seed not associated" " with provided aeid=${aeid}.`); } } } else if (this.algo == Algos.randy) { // Unlike KERIpy, we don't support unencrypted secrets throw new Error( 'Invalid Manager configuration, encryption must be used with Randy key creation.' ); } else { this._encrypter = undefined; } const salt = this.salt; if (salt != undefined) { this.salt = salt; } if (this._decrypter != undefined) { for (const [keys, data] of this.ks.prmsElements()) { if (data.salt != undefined) { const salter = this._decrypter.decrypt(b(data.salt)); data.salt = this._encrypter == undefined ? salter.qb64 : this._encrypter.encrypt(null, salter); this.ks.pinPrms(keys, data); } } for (const [pubKey, signer] of this.ks.prisElements( this._decrypter )) { this.ks.pinPris(pubKey, signer, this._encrypter!); } } this.ks.pinGbls('aeid', aeid!); // set aeid in db this._seed = seed; // set .seed in memory // update .decrypter this._decrypter = seed != undefined ? new Decrypter({}, b(seed)) : undefined; } incept({ icodes = undefined, icount = 1, icode = MtrDex.Ed25519_Seed, ncodes = undefined, ncount = 1, ncode = MtrDex.Ed25519_Seed, dcode = MtrDex.Blake3_256, algo = undefined, salt = undefined, stem = undefined, tier = undefined, rooted = true, transferable = true, temp = false, }: ManagerInceptArgs): [Array<Verfer>, Array<Diger>] { if (rooted && algo == undefined) { algo = this.algo; } if (rooted && salt == undefined) { salt = this.salt; } if (rooted && tier == undefined) { tier = this.tier; } const pidx = this.pidx!; const ridx = 0; const kidx = 0; const creator = new Creatory(algo).make(salt, tier, stem); if (icodes == undefined) { if (icount < 0) { throw new Error(`Invalid icount=${icount} must be >= 0.`); } icodes = new Array<string>(icount).fill(icode); } const ikeys = creator.create( icodes, 0, MtrDex.Ed25519_Seed, transferable, pidx, ridx, kidx, temp ); const verfers = Array.from( ikeys.signers, (signer: Signer) => signer.verfer ); if (ncodes == undefined) { if (ncount < 0) { throw new Error(`Invalid ncount=${ncount} must be >= 0.`); } ncodes = new Array<string>(ncount).fill(ncode); } const nkeys = creator.create( ncodes, 0, MtrDex.Ed25519_Seed, transferable, pidx, ridx + 1, kidx + icodes.length, temp ); const digers = Array.from( nkeys.signers, (signer: Signer) => new Diger({ code: dcode }, signer.verfer.qb64b) ); const pp = new PrePrm(); pp.pidx = pidx!; pp.algo = algo!; pp.salt = creator.salt.length == 0 || this.encrypter == undefined ? '' : this.encrypter.encrypt(b(creator.salt)).qb64; pp.stem = creator.stem; pp.tier = creator.tier; const dt = new Date().toString(); const nw = new PubLot(); nw.pubs = Array.from(verfers, (verfer: Verfer) => verfer.qb64); nw.ridx = ridx; nw.kidx = kidx; nw.dt = dt; const nt = new PubLot(); nt.pubs = Array.from( nkeys.signers, (signer: Signer) => signer.verfer.qb64 ); nt.ridx = ridx + 1; nt.kidx = kidx + icodes.length; nt.dt = dt; const ps = new PreSit(); ps.new = nw; ps.nxt = nt; const pre = verfers[0].qb64; if (!this.ks.putPres(pre, verfers[0].qb64b)) { throw new Error(`Already incepted pre=${pre}.`); } if (!this.ks.putPrms(pre, pp)) { throw new Error(`Already incepted prm for pre=${pre}.`); } this.pidx = pidx! + 1; if (!this.ks.putSits(pre, ps)) { throw new Error(`Already incepted sit for pre=${pre}.`); } if (this.encrypter != undefined) { // Only store encrypted keys if we have an encrypter, otherwise regenerate ikeys.signers.forEach((signer: Signer) => { this.ks.putPris(signer.verfer.qb64, signer, this.encrypter!); }); nkeys.signers.forEach((signer: Signer) => { this.ks.putPris(signer.verfer.qb64, signer, this.encrypter!); }); } else if ( this._encrypter == undefined && ikeys.paths != undefined && nkeys.paths != undefined ) { ikeys.paths.forEach((path: string, idx: number) => { const signer = ikeys.signers[idx]; const ppt = new PubPath(); ppt.path = path; ppt.code = icodes[idx]; ppt.tier = pp.tier; ppt.temp = temp; this.ks.putPths(signer.verfer.qb64, ppt); }); nkeys.paths.forEach((path: string, idx: number) => { const signer = nkeys.signers[idx]; const ppt = new PubPath(); ppt.path = path; ppt.code = ncodes[idx]; ppt.tier = pp.tier; ppt.temp = temp; this.ks.putPths(signer.verfer.qb64, ppt); }); } else { throw new Error( 'invalid configuration, randy keys without encryption' ); } const pubSet = new PubSet(); pubSet.pubs = ps.new.pubs; this.ks.putPubs(riKey(pre, ridx), pubSet); const nxtPubSet = new PubSet(); nxtPubSet.pubs = ps.nxt.pubs; this.ks.putPubs(riKey(pre, ridx + 1), nxtPubSet); return [verfers, digers]; } move(old: string, gnu: string) { if (old == gnu) { return; } if (this.ks.getPres(old) == undefined) { throw new Error(`Nonexistent old pre=${old}, nothing to assign.`); } if (this.ks.getPres(gnu) != undefined) { throw new Error(`Preexistent new pre=${gnu} may not clobber.`); } const oldprm = this.ks.getPrms(old); if (oldprm == undefined) { throw new Error( `Nonexistent old prm for pre=${old}, nothing to move.` ); } if (this.ks.getPrms(gnu) != undefined) { throw new Error( `Preexistent new prm for pre=${gnu} may not clobber.` ); } const oldsit = this.ks.getSits(old); if (oldsit == undefined) { throw new Error( `Nonexistent old sit for pre=${old}, nothing to move.` ); } if (this.ks.getSits(gnu) != undefined) { throw new Error( `Preexistent new sit for pre=${gnu} may not clobber.` ); } if (!this.ks.putPrms(gnu, oldprm)) { throw new Error( `Failed moving prm from old pre=${old} to new pre=${gnu}.` ); } else { this.ks.remPrms(old); } if (!this.ks.putSits(gnu, oldsit)) { throw new Error( `Failed moving sit from old pre=${old} to new pre=${gnu}.` ); } else { this.ks.remSits(old); } let i = 0; while (true) { const pl = this.ks.getPubs(riKey(old, i)); if (pl == undefined) { break; } if (!this.ks.putPubs(riKey(gnu, i), pl)) { throw new Error( `Failed moving pubs at pre=${old} ri=${i} to new pre=${gnu}` ); } i = i + 1; } if (!this.ks.pinPres(old, b(gnu))) { throw new Error( `Failed assiging new pre=${gnu} to old pre=${old}.` ); } if (!this.ks.putPres(gnu, b(gnu))) { throw new Error(`Failed assiging new pre=${gnu}.`); } } rotate({ pre, ncodes = undefined, ncount = 1, ncode = MtrDex.Ed25519_Seed, dcode = MtrDex.Blake3_256, transferable = true, temp = false, erase = true, }: RotateArgs): [Array<Verfer>, Array<Diger>] { const pp = this.ks.getPrms(pre); if (pp == undefined) { throw new Error(`Attempt to rotate nonexistent pre=${pre}.`); } const ps = this.ks.getSits(pre); if (ps == undefined) { throw new Error(`Attempt to rotate nonexistent pre=${pre}.`); } if (ps.nxt.pubs == undefined || ps.nxt.pubs.length == 0) { throw new Error(`Attempt to rotate nontransferable pre=${pre}.`); } const old = ps.old; ps.old = ps.new; ps.new = ps.nxt; if (this.aeid != undefined && this.decrypter == undefined) { throw new Error( 'Unauthorized decryption attempt. Aeid but no decrypter.' ); } const verfers = new Array<Verfer>(); ps.new.pubs.forEach((pub) => { if (this.decrypter != undefined) { const signer = this.ks.getPris(pub, this.decrypter); if (signer == undefined) { throw new Error(`Missing prikey in db for pubkey=${pub}`); } verfers.push(signer.verfer); } else { // Should we regenerate from salt here since this.decryptor is undefined verfers.push(new Verfer({ qb64: pub })); } }); let salt = pp.salt; if (salt != undefined && salt != '') { // If you provded a Salt for an AID but don't have encryption, pitch a fit if (this.decrypter == undefined) { throw new Error( 'Invalid configuration: AID salt with no encryption' ); } salt = this.decrypter.decrypt(b(salt)).qb64; } else { salt = this.salt!; } const creator = new Creatory(pp.algo).make(salt, pp.tier, pp.stem); if (ncodes == undefined) { if (ncount < 0) { throw new Error(`Invalid count=${ncount} must be >= 0`); } ncodes = new Array<string>(ncount).fill(ncode); } const pidx = pp.pidx; const ridx = ps.new.ridx + 1; const kidx = ps.nxt.kidx + ps.new.pubs.length; const keys = creator.create( ncodes, 0, '', transferable, pidx, ridx, kidx, temp ); const digers = Array.from( keys.signers, (signer: Signer) => new Diger({ code: dcode }, signer.verfer.qb64b) ); const dt = new Date().toString(); ps.nxt = new PubLot(); ps.nxt.pubs = Array.from( keys.signers, (signer: Signer) => signer.verfer.qb64 ); ps.nxt.ridx = ridx; ps.nxt.kidx = kidx; ps.nxt.dt = dt; if (!this.ks.pinSits(pre, ps)) { throw new Error(`Problem updating pubsit db for pre=${pre}.`); } if (this.encrypter != undefined) { // Only store encrypted keys if we have an encrypter, otherwise regenerate keys.signers.forEach((signer: Signer) => { this.ks.putPris(signer.verfer.qb64, signer, this.encrypter!); }); } else if (this._encrypter == undefined && keys.paths != undefined) { keys.paths.forEach((path: string, idx: number) => { const signer = keys.signers[idx]; const ppt = new PubPath(); ppt.path = path; ppt.tier = pp!.tier; ppt.temp = temp; this.ks.putPths(signer.verfer.qb64, ppt); }); } else { throw new Error( 'invalid configuration, randy keys without encryption' ); } const newPs = new PubSet(); newPs.pubs = ps.nxt.pubs; this.ks.putPubs(riKey(pre, ps.nxt.ridx), newPs); if (erase) { old.pubs.forEach((pub) => { this.ks.remPris(pub); }); } return [verfers, digers]; } sign({ ser, pubs = undefined, verfers = undefined, indexed = true, indices = undefined, ondices = undefined, }: SignArgs) { const signers = new Array<Signer>(); if (pubs == undefined && verfers == undefined) { throw new Error('pubs or verfers required'); } if (pubs != undefined) { if (this.aeid != undefined && this.decrypter == undefined) { throw new Error( 'Unauthorized decryption attempt. Aeid but no decrypter.' ); } pubs.forEach((pub) => { //If no decrypter then get SaltyState and regenerate prikey if (this.decrypter != undefined) { const signer = this.ks.getPris(pub, this.decrypter); if (signer == undefined) { throw new Error( `Missing prikey in db for pubkey=${pub}` ); } signers.push(signer); } else { const verfer = new Verfer({ qb64: pub }); const ppt = this.ks.getPths(pub); if (ppt == undefined) { throw new Error( `Missing prikey in db for pubkey=${pub}` ); } const salter = new Salter({ qb64: this.salt }); signers.push( salter.signer( ppt.code, verfer.transferable, ppt.path, ppt.tier as Tier, ppt.temp ) ); } }); } else { verfers!.forEach((verfer: Verfer) => { if (this.decrypter != undefined) { const signer = this.ks.getPris(verfer.qb64, this.decrypter); if (signer == undefined) { throw new Error( `Missing prikey in db for pubkey=${verfer.qb64}` ); } signers.push(signer); } else { const ppt = this.ks.getPths(verfer.qb64); if (ppt == undefined) { throw new Error( `Missing prikey in db for pubkey=${verfer.qb64}` ); } const salter = new Salter({ qb64: this.salt }); signers.push( salter.signer( ppt.code, verfer.transferable, ppt.path, ppt.tier as Tier, ppt.temp ) ); } }); } if (indices != undefined && indices.length != signers.length) { throw new Error( `Mismatch indices length=${indices.length} and resultant signers length=${signers.length}` ); } if (ondices != undefined && ondices.length != signers.length) { throw new Error( `Mismatch ondices length=${ondices.length} and resultant signers length=${signers.length}` ); } if (indexed) { const sigers = new Array<Siger>(); signers.forEach((signer, idx) => { let i; if (indices != undefined) { i = indices[idx]; if (i < 0) { throw new Error( `Invalid signing index = ${i}, not whole number.` ); } } else { i = idx; } let o; if (ondices != undefined) { o = ondices[idx]; if (o <= 0) { throw new Error( `Invalid other signing index = {o}, not None or not whole number.` ); } } else { o = i; } const only = o == undefined; sigers.push(signer.sign(ser, i, only, o) as Siger); }); return sigers; } else { const cigars = new Array<Cigar>(); signers.forEach((signer: Signer) => { cigars.push(signer.sign(ser) as Cigar); }); return cigars; } } } export function riKey(pre: string, ridx: number) { return pre + '.' + ridx.toString(16).padStart(32, '0'); } export interface KeyStore { getGbls(key: string): string | undefined; pinGbls(key: string, val: string): void; prmsElements(): Array<[string, PrePrm]>; getPrms(keys: string): PrePrm | undefined; pinPrms(keys: string, data: PrePrm): void; putPrms(keys: string, data: PrePrm): boolean; remPrms(keys: string): boolean; prisElements(decrypter: Decrypter): Array<[string, Signer]>; getPris(keys: string, decrypter: Decrypter): Signer | undefined; pinPris(keys: string, data: Signer, encrypter: Encrypter): void; putPris(pubKey: string, signer: Signer, encrypter: Encrypter): boolean; remPris(pubKey: string): void; getPths(pubKey: string): PubPath | undefined; putPths(pubKey: string, val: PubPath): boolean; pinPths(pubKey: string, val: PubPath): boolean; getPres(pre: string): Uint8Array | undefined; putPres(pre: string, val: Uint8Array): boolean; pinPres(pre: string, val: Uint8Array): boolean; getSits(keys: string): PreSit | undefined; putSits(pre: string, val: PreSit): boolean; pinSits(pre: string, val: PreSit): boolean; remSits(keys: string): boolean; getPubs(keys: string): PubSet | undefined; putPubs(keys: string, data: PubSet): boolean; } /* In memory test implementation of Keeper key store */ class Keeper implements KeyStore { private readonly _gbls: Map<string, string>; private readonly _pris: Map<string, Uint8Array>; private readonly _pths: Map<string, PubPath>; private readonly _pres: Map<string, Uint8Array>; private readonly _prms: Map<string, PrePrm>; private readonly _sits: Map<string, PreSit>; private readonly _pubs: Map<string, PubSet>; constructor() { this._gbls = new Map<string, string>(); this._pris = new Map<string, Uint8Array>(); this._pths = new Map<string, PubPath>(); this._pres = new Map<string, Uint8Array>(); this._prms = new Map<string, PrePrm>(); this._sits = new Map<string, PreSit>(); this._pubs = new Map<string, PubSet>(); } getGbls(key: string): string | undefined { return this._gbls.get(key); } pinGbls(key: string, val: string): void { this._gbls.set(key, val); } prmsElements(): Array<[string, PrePrm]> { const out = new Array<[string, PrePrm]>(); this._prms.forEach((value, key) => { out.push([key, value]); }); return out; } getPrms(keys: string): PrePrm | undefined { return this._prms.get(keys); } pinPrms(keys: string, data: PrePrm): void { this._prms.set(keys, data); } putPrms(keys: string, data: PrePrm): boolean { if (this._prms.has(keys)) { return false; } this._prms.set(keys, data); return true; } remPrms(keys: string): boolean { return this._prms.delete(keys); } prisElements(decrypter: Decrypter): Array<[string, Signer]> { const out = new Array<[string, Signer]>(); this._pris.forEach(function (val, pubKey) { const verfer = new Verfer({ qb64: pubKey }); const signer = decrypter.decrypt(val, null, verfer.transferable); out.push([pubKey, signer]); }); return out; } pinPris(pubKey: string, signer: Signer, encrypter: Encrypter): void { const cipher = encrypter.encrypt(null, signer); this._pris.set(pubKey, cipher.qb64b); } putPris(pubKey: string, signer: Signer, encrypter: Encrypter): boolean { if (this._pris.has(pubKey)) { return false; } const cipher = encrypter.encrypt(null, signer); this._pris.set(pubKey, cipher.qb64b); return true; } getPris(pubKey: string, decrypter: Decrypter): Signer | undefined { const val = this._pris.get(pubKey); if (val == undefined) { return undefined; } const verfer = new Verfer({ qb64: pubKey }); return decrypter.decrypt(val, null, verfer.transferable); } pinPths(pubKey: string, val: PubPath): boolean { this._pths.set(pubKey, val); return true; } putPths(pubKey: string, val: PubPath): boolean { if (this._pths.has(pubKey)) { return false; } this._pths.set(pubKey, val); return true; } getPths(pubKey: string): PubPath | undefined { return this._pths.get(pubKey); } remPris(pubKey: string): void { this._pris.delete(pubKey); } getPres(pre: string): Uint8Array | undefined { return this._pres.get(pre); } pinPres(pre: string, val: Uint8Array): boolean { this._pres.set(pre, val); return true; } putPres(pre: string, val: Uint8Array): boolean { if (this._pres.has(pre)) { return false; } this._pres.set(pre, val); return true; } getSits(keys: string): PreSit | undefined { return this._sits.get(keys); } putSits(pre: string, val: PreSit): boolean { if (this._sits.has(pre)) { return false; } this._sits.set(pre, val); return true; } pinSits(pre: string, val: PreSit): boolean { this._sits.set(pre, val); return true; } remSits(keys: string): boolean { return this._sits.delete(keys); } getPubs(keys: string): PubSet | undefined { return this._pubs.get(keys); } putPubs(keys: string, data: PubSet): boolean { if (this._pubs.has(keys)) { return false; } this._pubs.set(keys, data); return true; } }