Add documentation to pgp module.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Application imports
|
||||
import { MutablePgpKeyStore } from '@app/_pgp/pgp-key-store';
|
||||
|
||||
describe('PgpKeyStore', () => {
|
||||
|
||||
@@ -1,88 +1,290 @@
|
||||
// Third party imports
|
||||
import { KeyStore } from 'cic-client-meta';
|
||||
// TODO should we put this on the mutable key store object
|
||||
import * as openpgp from 'openpgp';
|
||||
|
||||
/** An openpgp Keyring instance. */
|
||||
const keyring = new openpgp.Keyring();
|
||||
|
||||
/**
|
||||
* @extends
|
||||
* Mutable Key store interface.
|
||||
*
|
||||
* @extends KeyStore
|
||||
*/
|
||||
interface MutableKeyStore extends KeyStore {
|
||||
/**
|
||||
* Instantiate the keyring in the keystore.
|
||||
* @async
|
||||
*/
|
||||
loadKeyring(): void;
|
||||
/**
|
||||
* Add a key pair to keyring.
|
||||
* @async
|
||||
* @param publicKey - The public key to be added to the keyring.
|
||||
* @param privateKey - The private key to be added to the keyring.
|
||||
* @throws Error
|
||||
*/
|
||||
importKeyPair(publicKey: any, privateKey: any): Promise<void>;
|
||||
importPublicKey(publicKey: any): void;
|
||||
/**
|
||||
* Add public key to keyring.
|
||||
* @async
|
||||
* @param publicKey - The public key to be added to the keyring.
|
||||
* @throws Error
|
||||
*/
|
||||
importPublicKey(publicKey: any): Promise<void>;
|
||||
/**
|
||||
* Add private key to keyring.
|
||||
* @async
|
||||
* @param privateKey - The private key to be added to the keyring.
|
||||
* @throws Error
|
||||
*/
|
||||
importPrivateKey(privateKey: any): Promise<void>;
|
||||
/**
|
||||
* Get all the public keys.
|
||||
* @returns An array of public keys.
|
||||
*/
|
||||
getPublicKeys(): Array<any>;
|
||||
/**
|
||||
* Get all the trusted keys.
|
||||
* @returns An array of trusted keys.
|
||||
*/
|
||||
getTrustedKeys(): Array<any>;
|
||||
/**
|
||||
* Get all the trusted active keys.
|
||||
* @returns An array of trusted active keys.
|
||||
*/
|
||||
getTrustedActiveKeys(): Array<any>;
|
||||
/**
|
||||
* Get all the encryption keys.
|
||||
* @returns An array of encryption keys.
|
||||
* @remarks
|
||||
* Current implementation doesn't include encryption keys.
|
||||
* This is included to appease the implemented Keystore interface.
|
||||
*/
|
||||
getEncryptKeys(): Array<any>;
|
||||
/**
|
||||
* Get all private keys.
|
||||
* @returns An array of all private keys.
|
||||
*/
|
||||
getPrivateKeys(): Array<any>;
|
||||
/**
|
||||
* Get the first private key.
|
||||
* @returns The first private key.
|
||||
*/
|
||||
getPrivateKey(): any;
|
||||
/**
|
||||
* Test if the input is a valid key.
|
||||
* @async
|
||||
* @param key - The input to be validated.
|
||||
* @returns true - If the input is a valid key.
|
||||
*/
|
||||
isValidKey(key: any): Promise<boolean>;
|
||||
/**
|
||||
* Verify that a private key is encrypted.
|
||||
* @async
|
||||
* @param privateKey - The private key to verify.
|
||||
* @returns true - If private key is encrypted.
|
||||
*/
|
||||
isEncryptedPrivateKey(privateKey: any): Promise<boolean>;
|
||||
/**
|
||||
* Get the first private key's fingerprint.
|
||||
* @returns The first private key's fingerprint.
|
||||
*/
|
||||
getFingerprint(): string;
|
||||
/**
|
||||
* Get a key's keyId.
|
||||
* @param key - The key to fetch the keyId from.
|
||||
* @returns The key's keyId.
|
||||
*/
|
||||
getKeyId(key: any): string;
|
||||
/**
|
||||
* Get the first private key's keyID.
|
||||
* @returns The first private key's keyId.
|
||||
*/
|
||||
getPrivateKeyId(): string;
|
||||
/**
|
||||
* Get keys from the keyring using their keyId.
|
||||
* @param keyId - The keyId of the keys to be fetched from the keyring.
|
||||
* @returns An array of the keys with that keyId.
|
||||
*/
|
||||
getKeysForId(keyId: string): Array<any>;
|
||||
/**
|
||||
* Get a public key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the public key to be fetched from the keyring.
|
||||
* @returns The public key with that keyId.
|
||||
*/
|
||||
getPublicKeyForId(keyId: string): any;
|
||||
/**
|
||||
* Get a private key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the private key to be fetched from the keyring.
|
||||
* @returns The private key with that keyId.
|
||||
*/
|
||||
getPrivateKeyForId(keyId: string): any;
|
||||
/**
|
||||
* Get a public key from the keyring using it's subkeyId.
|
||||
* @param subkeyId - The subkeyId of the public key to be fetched from the keyring.
|
||||
* @returns The public key with that subkeyId.
|
||||
*/
|
||||
getPublicKeyForSubkeyId(subkeyId: string): any;
|
||||
/**
|
||||
* Get public keys from the keyring using their address.
|
||||
* @param address - The address of the public keys to be fetched from the keyring.
|
||||
* @returns An array of the public keys with that address.
|
||||
*/
|
||||
getPublicKeysForAddress(address: string): Array<any>;
|
||||
/**
|
||||
* Remove a public key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the keys to be removed from the keyring.
|
||||
* @returns An array of the removed keys.
|
||||
*/
|
||||
removeKeysForId(keyId: string): Array<any>;
|
||||
/**
|
||||
* Remove a public key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the public key to be removed from the keyring.
|
||||
* @returns The removed public key.
|
||||
*/
|
||||
removePublicKeyForId(keyId: string): any;
|
||||
/**
|
||||
* Remove a public key from the keyring.
|
||||
* @param publicKey - The public key to be removed from the keyring.
|
||||
* @returns The removed public key.
|
||||
*/
|
||||
removePublicKey(publicKey: any): any;
|
||||
/** Remove all keys from the keyring. */
|
||||
clearKeysInKeyring(): void;
|
||||
/**
|
||||
* Sign message using private key.
|
||||
* @async
|
||||
* @param plainText - The message to be signed.
|
||||
* @returns The generated signature.
|
||||
*/
|
||||
sign(plainText: string): Promise<any>;
|
||||
}
|
||||
|
||||
/** Provides a keyring for pgp keys. */
|
||||
class MutablePgpKeyStore implements MutableKeyStore {
|
||||
/**
|
||||
* Instantiate the keyring in the keystore.
|
||||
* @async
|
||||
*/
|
||||
async loadKeyring(): Promise<void> {
|
||||
await keyring.load();
|
||||
await keyring.store();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key pair to keyring.
|
||||
* @async
|
||||
* @param publicKey - The public key to be added to the keyring.
|
||||
* @param privateKey - The private key to be added to the keyring.
|
||||
* @throws Error
|
||||
*/
|
||||
async importKeyPair(publicKey: any, privateKey: any): Promise<void> {
|
||||
await keyring.publicKeys.importKey(publicKey);
|
||||
await keyring.privateKeys.importKey(privateKey);
|
||||
try {
|
||||
await keyring.publicKeys.importKey(publicKey);
|
||||
await keyring.privateKeys.importKey(privateKey);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
importPublicKey(publicKey: any): void {
|
||||
keyring.publicKeys.importKey(publicKey);
|
||||
/**
|
||||
* Add public key to keyring.
|
||||
* @async
|
||||
* @param publicKey - The public key to be added to the keyring.
|
||||
* @throws Error
|
||||
*/
|
||||
async importPublicKey(publicKey: any): Promise<void> {
|
||||
try {
|
||||
await keyring.publicKeys.importKey(publicKey);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add private key to keyring.
|
||||
* @async
|
||||
* @param privateKey - The private key to be added to the keyring.
|
||||
* @throws Error
|
||||
*/
|
||||
async importPrivateKey(privateKey: any): Promise<void> {
|
||||
await keyring.privateKeys.importKey(privateKey);
|
||||
try {
|
||||
await keyring.privateKeys.importKey(privateKey);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the public keys.
|
||||
* @returns An array of public keys.
|
||||
*/
|
||||
getPublicKeys(): Array<any> {
|
||||
return keyring.publicKeys.keys;
|
||||
return keyring.publicKeys && keyring.publicKeys.keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the trusted keys.
|
||||
* @returns An array of trusted keys.
|
||||
*/
|
||||
getTrustedKeys(): Array<any> {
|
||||
return keyring.publicKeys.keys;
|
||||
return keyring.publicKeys && keyring.publicKeys.keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the trusted active keys.
|
||||
* @returns An array of trusted active keys.
|
||||
*/
|
||||
getTrustedActiveKeys(): Array<any> {
|
||||
return keyring.publicKeys.keys;
|
||||
return keyring.publicKeys && keyring.publicKeys.keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the encryption keys.
|
||||
* @returns An array of encryption keys.
|
||||
* @remarks
|
||||
* Current implementation doesn't include encryption keys.
|
||||
* This is included to appease the implemented Keystore interface.
|
||||
*/
|
||||
getEncryptKeys(): Array<any> {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all private keys.
|
||||
* @returns An array of all private keys.
|
||||
*/
|
||||
getPrivateKeys(): Array<any> {
|
||||
return keyring.privateKeys.keys;
|
||||
return keyring.privateKeys && keyring.privateKeys.keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first private key.
|
||||
* @returns The first private key.
|
||||
*/
|
||||
getPrivateKey(): any {
|
||||
return keyring.privateKeys && keyring.privateKeys.keys[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the input is a valid key.
|
||||
* @async
|
||||
* @param key - The input to be validated.
|
||||
* @returns true - If the input is a valid key.
|
||||
*/
|
||||
async isValidKey(key): Promise<boolean> {
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a private key is encrypted.
|
||||
* @async
|
||||
* @param privateKey - The private key to verify.
|
||||
* @returns true - If private key is encrypted.
|
||||
*/
|
||||
async isEncryptedPrivateKey(privateKey: any): Promise<boolean> {
|
||||
const imported = await openpgp.key.readArmored(privateKey);
|
||||
for (const key of imported.keys) {
|
||||
@@ -93,6 +295,10 @@ class MutablePgpKeyStore implements MutableKeyStore {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first private key's fingerprint.
|
||||
* @returns The first private key's fingerprint.
|
||||
*/
|
||||
getFingerprint(): string {
|
||||
// TODO Handle multiple keys
|
||||
return (
|
||||
@@ -103,10 +309,19 @@ class MutablePgpKeyStore implements MutableKeyStore {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a key's keyId.
|
||||
* @param key - The key to fetch the keyId from.
|
||||
* @returns The key's keyId.
|
||||
*/
|
||||
getKeyId(key: any): string {
|
||||
return key.getKeyId().toHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first private key's keyID.
|
||||
* @returns The first private key's keyId.
|
||||
*/
|
||||
getPrivateKeyId(): string {
|
||||
// TODO is there a library that comes with angular for doing this?
|
||||
return (
|
||||
@@ -116,43 +331,90 @@ class MutablePgpKeyStore implements MutableKeyStore {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keys from the keyring using their keyId.
|
||||
* @param keyId - The keyId of the keys to be fetched from the keyring.
|
||||
* @returns An array of the keys with that keyId.
|
||||
*/
|
||||
getKeysForId(keyId: string): Array<any> {
|
||||
return keyring.getKeysForId(keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a public key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the public key to be fetched from the keyring.
|
||||
* @returns The public key with that keyId.
|
||||
*/
|
||||
getPublicKeyForId(keyId): any {
|
||||
return keyring.publicKeys.getForId(keyId);
|
||||
return keyring.publicKeys && keyring.publicKeys.getForId(keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a private key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the private key to be fetched from the keyring.
|
||||
* @returns The private key with that keyId.
|
||||
*/
|
||||
getPrivateKeyForId(keyId): any {
|
||||
return keyring.privateKeys.getForId(keyId);
|
||||
return keyring.privateKeys && keyring.privateKeys.getForId(keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a public key from the keyring using it's subkeyId.
|
||||
* @param subkeyId - The subkeyId of the public key to be fetched from the keyring.
|
||||
* @returns The public key with that subkeyId.
|
||||
*/
|
||||
getPublicKeyForSubkeyId(subkeyId): any {
|
||||
return keyring.publicKeys.getForId(subkeyId, true);
|
||||
return keyring.publicKeys && keyring.publicKeys.getForId(subkeyId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public keys from the keyring using their address.
|
||||
* @param address - The address of the public keys to be fetched from the keyring.
|
||||
* @returns An array of the public keys with that address.
|
||||
*/
|
||||
getPublicKeysForAddress(address): Array<any> {
|
||||
return keyring.publicKeys.getForAddress(address);
|
||||
return keyring.publicKeys && keyring.publicKeys.getForAddress(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a public key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the keys to be removed from the keyring.
|
||||
* @returns An array of the removed keys.
|
||||
*/
|
||||
removeKeysForId(keyId): Array<any> {
|
||||
return keyring.removeKeysForId(keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a public key from the keyring using it's keyId.
|
||||
* @param keyId - The keyId of the public key to be removed from the keyring.
|
||||
* @returns The removed public key.
|
||||
*/
|
||||
removePublicKeyForId(keyId): any {
|
||||
return keyring.publicKeys.removeForId(keyId);
|
||||
return keyring.publicKeys && keyring.publicKeys.removeForId(keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a public key from the keyring.
|
||||
* @param publicKey - The public key to be removed from the keyring.
|
||||
* @returns The removed public key.
|
||||
*/
|
||||
removePublicKey(publicKey: any): any {
|
||||
const keyId = publicKey.getKeyId().toHex();
|
||||
return keyring.publicKeys.removeForId(keyId);
|
||||
return keyring.publicKeys && keyring.publicKeys.removeForId(keyId);
|
||||
}
|
||||
|
||||
/** Remove all keys from the keyring. */
|
||||
clearKeysInKeyring(): void {
|
||||
keyring.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign message using private key.
|
||||
* @async
|
||||
* @param plainText - The message to be signed.
|
||||
* @returns The generated signature.
|
||||
*/
|
||||
async sign(plainText): Promise<any> {
|
||||
const privateKey = this.getPrivateKey();
|
||||
if (!privateKey.isDecrypted()) {
|
||||
@@ -169,4 +431,5 @@ class MutablePgpKeyStore implements MutableKeyStore {
|
||||
}
|
||||
}
|
||||
|
||||
/** @exports */
|
||||
export { MutablePgpKeyStore, MutableKeyStore };
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { PGPSigner } from '@app/_pgp/pgp-signer';
|
||||
// Application imports
|
||||
import { MutableKeyStore, MutablePgpKeyStore } from '@app/_pgp/pgp-key-store';
|
||||
import { PGPSigner } from '@app/_pgp/pgp-signer';
|
||||
|
||||
const keystore: MutableKeyStore = new MutablePgpKeyStore();
|
||||
|
||||
describe('PgpSigner', () => {
|
||||
|
||||
@@ -1,53 +1,111 @@
|
||||
// Third party imports
|
||||
import * as openpgp from 'openpgp';
|
||||
|
||||
// Application imports
|
||||
import { MutableKeyStore } from '@app/_pgp/pgp-key-store';
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
|
||||
const openpgp = require('openpgp');
|
||||
|
||||
/** Signable object interface */
|
||||
interface Signable {
|
||||
/** The message to be signed. */
|
||||
digest(): string;
|
||||
}
|
||||
|
||||
/** Signature object interface */
|
||||
interface Signature {
|
||||
/** Encryption engine used. */
|
||||
engine: string;
|
||||
/** Encryption algorithm used */
|
||||
algo: string;
|
||||
/** Data to be signed. */
|
||||
data: string;
|
||||
/** Message digest */
|
||||
digest: string;
|
||||
}
|
||||
|
||||
/** Signer interface */
|
||||
interface Signer {
|
||||
/** Event triggered on successful signing of message. */
|
||||
onsign(signature: Signature): void;
|
||||
/** Event triggered on successful verification of a signature. */
|
||||
onverify(flag: boolean): void;
|
||||
/**
|
||||
* Get the private key fingerprint.
|
||||
* @returns A private key fingerprint.
|
||||
*/
|
||||
fingerprint(): string;
|
||||
/**
|
||||
* Load the message digest.
|
||||
* @param material - A signable object.
|
||||
* @returns true - If digest has been loaded successfully.
|
||||
*/
|
||||
prepare(material: Signable): boolean;
|
||||
/**
|
||||
* Verify that signature is valid.
|
||||
* @param digest - The message that was signed.
|
||||
* @param signature - The generated signature.
|
||||
*/
|
||||
verify(digest: string, signature: Signature): void;
|
||||
/**
|
||||
* Signs a message using a private key.
|
||||
* @async
|
||||
* @param digest - The message to be signed.
|
||||
*/
|
||||
sign(digest: string): Promise<void>;
|
||||
}
|
||||
|
||||
/** Provides functionality for signing and verifying signed messages. */
|
||||
class PGPSigner implements Signer {
|
||||
/** Encryption engine used. */
|
||||
engine = 'pgp';
|
||||
/** Encryption algorithm used */
|
||||
algo = 'sha256';
|
||||
/** Message digest */
|
||||
dgst: string;
|
||||
/** Generated signature */
|
||||
signature: Signature;
|
||||
/** A keystore holding pgp keys. */
|
||||
keyStore: MutableKeyStore;
|
||||
/** Event triggered on successful signing of message. */
|
||||
onsign: (signature: Signature) => void;
|
||||
/** Event triggered on successful verification of a signature. */
|
||||
onverify: (flag: boolean) => void;
|
||||
/** A service that provides logging capabilities. */
|
||||
loggingService: LoggingService;
|
||||
|
||||
/**
|
||||
* Initializing the Signer.
|
||||
* @param keyStore - A keystore holding pgp keys.
|
||||
*/
|
||||
constructor(keyStore: MutableKeyStore) {
|
||||
this.keyStore = keyStore;
|
||||
this.onsign = (signature: Signature) => {};
|
||||
this.onverify = (flag: boolean) => {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the private key fingerprint.
|
||||
* @returns A private key fingerprint.
|
||||
*/
|
||||
public fingerprint(): string {
|
||||
return this.keyStore.getFingerprint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the message digest.
|
||||
* @param material - A signable object.
|
||||
* @returns true - If digest has been loaded successfully.
|
||||
*/
|
||||
public prepare(material: Signable): boolean {
|
||||
this.dgst = material.digest();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that signature is valid.
|
||||
* @param digest - The message that was signed.
|
||||
* @param signature - The generated signature.
|
||||
*/
|
||||
public verify(digest: string, signature: Signature): void {
|
||||
openpgp.signature
|
||||
.readArmored(signature.data)
|
||||
@@ -80,6 +138,11 @@ class PGPSigner implements Signer {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a message using a private key.
|
||||
* @async
|
||||
* @param digest - The message to be signed.
|
||||
*/
|
||||
public async sign(digest: string): Promise<void> {
|
||||
const m = openpgp.cleartext.fromText(digest);
|
||||
const pk = this.keyStore.getPrivateKey();
|
||||
@@ -111,4 +174,5 @@ class PGPSigner implements Signer {
|
||||
}
|
||||
}
|
||||
|
||||
/** @exports */
|
||||
export { Signable, Signature, Signer, PGPSigner };
|
||||
|
||||
Reference in New Issue
Block a user