UNPKG

jinaga

Version:

Data management for web and mobile applications.

44 lines (40 loc) 1.59 kB
import { md, pki, util } from "node-forge"; import { canonicalizeFact } from "../fact/hash"; import { FactEnvelope, FactRecord } from "../storage"; import { Trace } from "../util/trace"; export interface KeyPair { publicPem: string; privatePem: string; } export function generateKeyPair(): KeyPair { const keypair = pki.rsa.generateKeyPair({ bits: 2048 }); const privatePem = pki.privateKeyToPem(keypair.privateKey); const publicPem = pki.publicKeyToPem(keypair.publicKey); return { privatePem, publicPem }; } export function signFacts(keyPair: KeyPair, facts: FactRecord[]): FactEnvelope[] { const privateKey = <pki.rsa.PrivateKey>pki.privateKeyFromPem(keyPair.privatePem); const envelopes: FactEnvelope[] = facts.map(fact => signFact(fact, keyPair.publicPem, privateKey)); return envelopes; } function signFact(fact: FactRecord, publicPem: string, privateKey: pki.rsa.PrivateKey): FactEnvelope { const canonicalString = canonicalizeFact(fact.fields, fact.predecessors); const encodedString = util.encodeUtf8(canonicalString); const digest = md.sha512.create().update(encodedString); const hash = util.encode64(digest.digest().getBytes()); if (fact.hash !== hash) { Trace.error(`Hash does not match. "${fact.hash}" !== "${hash}"\nFact: ${canonicalString}`); return { fact, signatures: [] }; } const signature = util.encode64(privateKey.sign(digest)); return { fact, signatures: [{ signature, publicKey: publicPem }] }; }