import {MutableKeyStore} from '@app/_helpers/pgp-key-store'; const openpgp = require('openpgp'); interface Signable { digest(): string; } type Signature = { engine: string algo: string data: string digest: string; }; interface Signer { onsign(signature: Signature): void; onverify(flag: boolean): void; fingerprint(): string; prepare(material: Signable): boolean; verify(digest: string, signature: Signature): void; sign(digest: string): void; } class PGPSigner implements Signer { engine = 'pgp'; algo = 'sha256'; dgst: string; signature: Signature; keyStore: MutableKeyStore; onsign: (signature: Signature) => void; onverify: (flag: boolean) => void; constructor(keyStore: MutableKeyStore) { this.keyStore = keyStore; this.onsign = (signature: Signature) => {}; this.onverify = (flag: boolean) => {}; } public fingerprint(): string { return this.keyStore.getFingerprint(); } public prepare(material: Signable): boolean { this.dgst = material.digest(); return true; } public verify(digest: string, signature: Signature): void { openpgp.signature.readArmored(signature.data).then((sig) => { const opts = { message: openpgp.cleartext.fromText(digest), publicKeys: this.keyStore.getTrustedKeys(), signature: sig, }; openpgp.verify(opts).then((v) => { let i = 0; for (i = 0; i < v.signatures.length; i++) { const s = v.signatures[i]; if (s.valid) { this.onverify(s); return; } } console.error('checked ' + i + ' signature(s) but none valid'); this.onverify(false); }); }).catch((e) => { console.error(e); this.onverify(false); }); } public sign(digest: string): void { const m = openpgp.cleartext.fromText(digest); const pk = this.keyStore.getPrivateKey(); const opts = { message: m, privateKeys: [pk], detached: true, }; openpgp.sign(opts).then((s) => { this.signature = { engine: this.engine, algo: this.algo, data: s.signature, // TODO: fix for browser later digest, }; this.onsign(this.signature); }).catch((e) => { console.error(e); this.onsign(undefined); }); } } export { Signable, Signature, Signer, PGPSigner };