UNPKG

signify-ts

Version:

Signing at the edge for KERI, ACDC, and KERIA

134 lines (122 loc) 4 kB
import { EmptyMaterialError } from './kering'; export {}; import libsodium from 'libsodium-wrappers-sumo'; import { Matter } from './matter'; import { MtrDex } from './matter'; import { Verfer } from './verfer'; import { Cigar } from './cigar'; import { Siger } from './siger'; import { IdrDex } from './indexer'; import { Buffer } from 'buffer'; /** * @description Signer is Matter subclass with method to create signature of serialization * It will use .raw as signing (private) key seed * .code as cipher suite for signing and new property .verfer whose property * .raw is public key for signing. * If not provided .verfer is generated from private key seed using .code as cipher suite for creating key-pair. */ interface SignerArgs { raw?: Uint8Array | undefined; code?: string; qb64b?: Uint8Array | undefined; qb64?: string; qb2?: Uint8Array | undefined; transferable?: boolean; } export class Signer extends Matter { private readonly _sign: Function; private readonly _verfer: Verfer; constructor({ raw, code = MtrDex.Ed25519_Seed, qb64, qb64b, qb2, transferable = true, }: SignerArgs) { try { super({ raw, code, qb64, qb64b, qb2 }); } catch (e) { if (e instanceof EmptyMaterialError) { if (code == MtrDex.Ed25519_Seed) { const raw = libsodium.randombytes_buf( libsodium.crypto_sign_SEEDBYTES ); super({ raw, code, qb64, qb64b, qb2 }); } else { throw new Error(`Unsupported signer code = ${code}.`); } } else { throw e; } } let verfer; if (this.code == MtrDex.Ed25519_Seed) { this._sign = this._ed25519; const keypair = libsodium.crypto_sign_seed_keypair(this.raw); verfer = new Verfer({ raw: keypair.publicKey, code: transferable ? MtrDex.Ed25519 : MtrDex.Ed25519N, }); } else { throw new Error(`Unsupported signer code = ${this.code}.`); } this._verfer = verfer; } /** * @description Property verfer: Returns Verfer instance Assumes ._verfer is correctly assigned */ get verfer(): Verfer { return this._verfer; } sign( ser: Uint8Array, index: number | null = null, only: boolean = false, ondex: number | undefined = undefined ): Siger | Cigar { return this._sign(ser, this.raw, this.verfer, index, only, ondex); } _ed25519( ser: Uint8Array, seed: Uint8Array, verfer: Verfer, index: number | null, only: boolean = false, ondex: number | undefined ) { const sig = libsodium.crypto_sign_detached( ser, Buffer.concat([seed, verfer.raw]) ); if (index == null) { return new Cigar({ raw: sig, code: MtrDex.Ed25519_Sig }, verfer); } else { let code; if (only) { ondex = undefined; if (index <= 63) { code = IdrDex.Ed25519_Crt_Sig; } else { code = IdrDex.Ed25519_Big_Crt_Sig; } } else { if (ondex == undefined) { ondex = index; } if (ondex == index && index <= 63) // both same and small code = IdrDex.Ed25519_Sig; // use small both same // otherwise big or both not same so use big both else code = IdrDex.Ed25519_Big_Sig; // use use big both } return new Siger( { raw: sig, code: code, index: index, ondex: ondex }, verfer ); } } }