import { KeyStore } from 'cic-client-meta'; // TODO should we put this on the mutable key store object import * as openpgp from 'openpgp'; const keyring = new openpgp.Keyring(); interface MutableKeyStore extends KeyStore { loadKeyring(): void; importKeyPair(publicKey: any, privateKey: any): Promise; importPublicKey(publicKey: any): Promise; importPrivateKey(privateKey: any): Promise; getPublicKeys(): Array; getTrustedKeys(): Array; getTrustedActiveKeys(): Array; getEncryptKeys(): Array; getPrivateKeys(): Array; getPrivateKey(): any; isValidKey(key: any): Promise; isEncryptedPrivateKey(privateKey: any): Promise; getFingerprint(): string; getKeyId(key: any): string; getPrivateKeyId(): string; getKeysForId(keyId: string): Array; getPublicKeyForId(keyId: string): any; getPrivateKeyForId(keyId: string): any; getPublicKeyForSubkeyId(subkeyId: string): any; getPublicKeysForAddress(address: string): Array; removeKeysForId(keyId: string): Array; removePublicKeyForId(keyId: string): any; removePublicKey(publicKey: any): any; clearKeysInKeyring(): void; sign(plainText: string): Promise; } class MutablePgpKeyStore implements MutableKeyStore { async loadKeyring(): Promise { await keyring.load(); await keyring.store(); } async importKeyPair(publicKey: any, privateKey: any): Promise { await keyring.publicKeys.importKey(publicKey); await keyring.privateKeys.importKey(privateKey); } async importPublicKey(publicKey: any): Promise { await keyring.publicKeys.importKey(publicKey); } async importPrivateKey(privateKey: any): Promise { await keyring.privateKeys.importKey(privateKey); } getPublicKeys(): Array { return keyring.publicKeys.keys; } getTrustedKeys(): Array { return keyring.publicKeys.keys; } getTrustedActiveKeys(): Array { return keyring.publicKeys.keys; } getEncryptKeys(): Array { return []; } getPrivateKeys(): Array { return keyring.privateKeys.keys; } getPrivateKey(): any { return keyring.privateKeys && keyring.privateKeys.keys[0]; } async isValidKey(key): Promise { // There is supposed to be an openpgp.readKey() method but I can't find it? const testKey = await openpgp.key.readArmored(key); return !testKey.err; } async isEncryptedPrivateKey(privateKey: any): Promise { const imported = await openpgp.key.readArmored(privateKey); for (const key of imported.keys) { if (key.isDecrypted()) { return false; } } return true; } getFingerprint(): string { // TODO Handle multiple keys return ( keyring.privateKeys && keyring.privateKeys.keys[0] && keyring.privateKeys.keys[0].keyPacket && keyring.privateKeys.keys[0].keyPacket.fingerprint ); } getKeyId(key: any): string { return key.getKeyId().toHex(); } getPrivateKeyId(): string { // TODO is there a library that comes with angular for doing this? return ( keyring.privateKeys && keyring.privateKeys.keys[0] && keyring.privateKeys.keys[0].getKeyId().toHex() ); } getKeysForId(keyId: string): Array { return keyring.getKeysForId(keyId); } getPublicKeyForId(keyId): any { return keyring.publicKeys.getForId(keyId); } getPrivateKeyForId(keyId): any { return keyring.privateKeys.getForId(keyId); } getPublicKeyForSubkeyId(subkeyId): any { return keyring.publicKeys.getForId(subkeyId, true); } getPublicKeysForAddress(address): Array { return keyring.publicKeys.getForAddress(address); } removeKeysForId(keyId): Array { return keyring.removeKeysForId(keyId); } removePublicKeyForId(keyId): any { return keyring.publicKeys.removeForId(keyId); } removePublicKey(publicKey: any): any { const keyId = publicKey.getKeyId().toHex(); return keyring.publicKeys.removeForId(keyId); } clearKeysInKeyring(): void { keyring.clear(); } async sign(plainText): Promise { const privateKey = this.getPrivateKey(); if (!privateKey.isDecrypted()) { const password = window.prompt('password'); await privateKey.decrypt(password); } const opts = { message: openpgp.message.fromText(plainText), privateKeys: [privateKey], detached: true, }; const signatureObject = await openpgp.sign(opts); return signatureObject.signature; } } export { MutablePgpKeyStore, MutableKeyStore };