import bs58 from 'bs58'; import { asn1, md, pki, util } from 'node-forge'; import { ICrypto } from './crypto'; import { IKeyPair } from './key-pair'; export default class CryptoForge implements ICrypto { public generateRsaKeyPair(bits: number): Promise { return new Promise((resolve, reject) => { pki.rsa.generateKeyPair({bits, workers: 2}, (err, {privateKey, publicKey}) => { if (err) { reject(err); return; } resolve({ export: () => this.export(privateKey, publicKey), getPublicHash: () => this.getPublicHash(publicKey), getPublicKey: () => this.getPublicKey(publicKey), sign: (data: Buffer) => this.sign(privateKey, data), }); }); }); } public async sign(privateKeyObj: any, data: Buffer): Promise { const sha256 = md.sha256.create(); const buf = util.hexToBytes(data.toString('hex')); sha256.update(buf); const signature = privateKeyObj.sign(sha256); const hexed = util.bytesToHex(signature); return hexed; } public async importRsaKeyPair(serialized: any): Promise { const { privateKey, publicKey } = JSON.parse(bs58.decode(serialized).toString('utf-8')); const privateKeyObj = pki.privateKeyFromPem(privateKey); const publicKeyObj = pki.publicKeyFromPem(publicKey); return { export: () => this.export(privateKeyObj, publicKeyObj), getPublicHash: () => this.getPublicHash(publicKeyObj), getPublicKey: () => this.getPublicKey(publicKeyObj), sign: (data: Buffer) => this.sign(privateKeyObj, data), }; } private getPublicHash(publicKeyObj: any): string { const publicKeyHexString = this.getPublicKey(publicKeyObj); const sha256 = md.sha256.create(); const buf = util.hexToBytes(publicKeyHexString); sha256.update(buf); const digested = sha256.digest().bytes(); const pubHash = bs58.encode(Buffer.from(digested, 'binary')); return pubHash; } private getPublicKey(publicKeyObj: any): string { const pk = asn1.toDer(pki.publicKeyToAsn1(publicKeyObj)).toHex(); return pk; } private async export(privateKeyObj: any, publicKeyObj: any): Promise { const privateKey = pki.privateKeyToPem(privateKeyObj); const publicKey = pki.publicKeyToPem(publicKeyObj); const jsonString = JSON.stringify({privateKey, publicKey}); return bs58.encode(Buffer.from(jsonString, 'utf-8')); } }