Require keys in openpgp.sign and make all top-level functions fully async (#1318)

- `openpgp.sign` throws if no signing keys are given, instead of returning a
non-signed literal packet.
- Any top-level function error will cause Promise rejection, and can thus be
handled with `.catch()`.
This commit is contained in:
larabr 2021-06-15 17:21:18 +02:00 committed by GitHub
parent b4e53b3ff7
commit e785df4c8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 122 deletions

View File

@ -201,7 +201,7 @@ export async function createSignaturePacket(dataToSign, privateKey, signingKeyPa
throw new Error('Cannot sign with a gnu-dummy key.'); throw new Error('Cannot sign with a gnu-dummy key.');
} }
if (!signingKeyPacket.isDecrypted()) { if (!signingKeyPacket.isDecrypted()) {
throw new Error('Private key is not decrypted.'); throw new Error('Signing key is not decrypted.');
} }
const signaturePacket = new SignaturePacket(); const signaturePacket = new SignaturePacket();
Object.assign(signaturePacket, signatureProperties); Object.assign(signaturePacket, signatureProperties);

View File

@ -658,7 +658,7 @@ export class Message {
/** /**
* Create signature packets for the message * Create signature packets for the message
* @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign
* @param {Array<PrivateKey>} signingKeys - private keys with decrypted secret key data for signing * @param {Array<PrivateKey>} [signingKeys] - private keys with decrypted secret key data for signing
* @param {Signature} [signature] - Any existing detached signature to append * @param {Signature} [signature] - Any existing detached signature to append
* @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] * @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i]
* @param {Date} [date] - Override the creationtime of the signature * @param {Date} [date] - Override the creationtime of the signature
@ -684,7 +684,7 @@ export async function createSignaturePackets(literalDataPacket, signingKeys, sig
const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config);
return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config);
})).then(signatureList => { })).then(signatureList => {
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket)); packetlist.push(...signatureList);
}); });
if (signature) { if (signature) {

View File

@ -50,7 +50,7 @@ import util from './util';
* @async * @async
* @static * @static
*/ */
export function generateKey({ userIDs = [], passphrase = "", type = "ecc", rsaBits = 4096, curve = "curve25519", keyExpirationTime = 0, date = new Date(), subkeys = [{}], config }) { export async function generateKey({ userIDs = [], passphrase = "", type = "ecc", rsaBits = 4096, curve = "curve25519", keyExpirationTime = 0, date = new Date(), subkeys = [{}], config }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
userIDs = toArray(userIDs); userIDs = toArray(userIDs);
if (userIDs.length === 0) { if (userIDs.length === 0) {
@ -61,19 +61,20 @@ export function generateKey({ userIDs = [], passphrase = "", type = "ecc", rsaBi
} }
const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys };
return generate(options, config).then(async key => { try {
const key = await generate(options, config);
const revocationCertificate = await key.getRevocationCertificate(date, config); const revocationCertificate = await key.getRevocationCertificate(date, config);
key.revocationSignatures = []; key.revocationSignatures = [];
return { return {
key,
key: key,
privateKeyArmored: key.armor(config), privateKeyArmored: key.armor(config),
publicKeyArmored: key.toPublic().armor(config), publicKeyArmored: key.toPublic().armor(config),
revocationCertificate: revocationCertificate revocationCertificate: revocationCertificate
}; };
}).catch(onError.bind(null, 'Error generating keypair')); } catch (err) {
throw util.wrapError('Error generating keypair', err);
}
} }
/** /**
@ -90,7 +91,7 @@ export function generateKey({ userIDs = [], passphrase = "", type = "ecc", rsaBi
* @async * @async
* @static * @static
*/ */
export function reformatKey({ privateKey, userIDs = [], passphrase = "", keyExpirationTime = 0, date, config }) { export async function reformatKey({ privateKey, userIDs = [], passphrase = "", keyExpirationTime = 0, date, config }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
userIDs = toArray(userIDs); userIDs = toArray(userIDs);
if (userIDs.length === 0) { if (userIDs.length === 0) {
@ -98,19 +99,20 @@ export function reformatKey({ privateKey, userIDs = [], passphrase = "", keyExpi
} }
const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; const options = { privateKey, userIDs, passphrase, keyExpirationTime, date };
return reformat(options, config).then(async key => { try {
const revocationCertificate = await key.getRevocationCertificate(date, config); const reformattedKey = await reformat(options, config);
key.revocationSignatures = []; const revocationCertificate = await reformattedKey.getRevocationCertificate(date, config);
reformattedKey.revocationSignatures = [];
return { return {
key: reformattedKey,
key: key, privateKeyArmored: reformattedKey.armor(config),
privateKeyArmored: key.armor(config), publicKeyArmored: reformattedKey.toPublic().armor(config),
publicKeyArmored: key.toPublic().armor(config),
revocationCertificate: revocationCertificate revocationCertificate: revocationCertificate
}; };
}).catch(onError.bind(null, 'Error reformatting keypair')); } catch (err) {
throw util.wrapError('Error reformatting keypair', err);
}
} }
/** /**
@ -130,29 +132,30 @@ export function reformatKey({ privateKey, userIDs = [], passphrase = "", keyExpi
* @async * @async
* @static * @static
*/ */
export function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), config }) { export async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), config }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
return Promise.resolve().then(() => { try {
if (revocationCertificate) { const revokedKey = revocationCertificate ?
return key.applyRevocationCertificate(revocationCertificate, date, config); await key.applyRevocationCertificate(revocationCertificate, date, config) :
} else { await key.revoke(reasonForRevocation, date, config);
return key.revoke(reasonForRevocation, date, config);
} if (revokedKey.isPrivate()) {
}).then(async key => { const publicKey = revokedKey.toPublic();
if (key.isPrivate()) {
const publicKey = key.toPublic();
return { return {
privateKey: key, privateKey: revokedKey,
privateKeyArmored: key.armor(config), privateKeyArmored: revokedKey.armor(config),
publicKey: publicKey, publicKey: publicKey,
publicKeyArmored: publicKey.armor(config) publicKeyArmored: publicKey.armor(config)
}; };
} }
return { return {
publicKey: key, publicKey: revokedKey,
publicKeyArmored: key.armor(config) publicKeyArmored: revokedKey.armor(config)
}; };
}).catch(onError.bind(null, 'Error revoking key')); } catch (err) {
throw util.wrapError('Error revoking key', err);
}
} }
/** /**
@ -171,9 +174,9 @@ export async function decryptKey({ privateKey, passphrase, config }) {
throw new Error("Cannot decrypt a public key"); throw new Error("Cannot decrypt a public key");
} }
const clonedPrivateKey = privateKey.clone(true); const clonedPrivateKey = privateKey.clone(true);
const passphrases = util.isArray(passphrase) ? passphrase : [passphrase];
try { try {
const passphrases = util.isArray(passphrase) ? passphrase : [passphrase];
await Promise.all(clonedPrivateKey.getKeys().map(key => ( await Promise.all(clonedPrivateKey.getKeys().map(key => (
// try to decrypt each key with any of the given passphrases // try to decrypt each key with any of the given passphrases
util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase)))
@ -183,7 +186,7 @@ export async function decryptKey({ privateKey, passphrase, config }) {
return clonedPrivateKey; return clonedPrivateKey;
} catch (err) { } catch (err) {
clonedPrivateKey.clearPrivateParams(); clonedPrivateKey.clearPrivateParams();
return onError('Error decrypting private key', err); throw util.wrapError('Error decrypting private key', err);
} }
} }
@ -204,13 +207,13 @@ export async function encryptKey({ privateKey, passphrase, config }) {
} }
const clonedPrivateKey = privateKey.clone(true); const clonedPrivateKey = privateKey.clone(true);
try { const keys = clonedPrivateKey.getKeys();
const keys = clonedPrivateKey.getKeys(); const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase);
const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); if (passphrases.length !== keys.length) {
if (passphrases.length !== keys.length) { throw new Error("Invalid number of passphrases given for key encryption");
throw new Error("Invalid number of passphrases for key"); }
}
try {
await Promise.all(keys.map(async (key, i) => { await Promise.all(keys.map(async (key, i) => {
const { keyPacket } = key; const { keyPacket } = key;
await keyPacket.encrypt(passphrases[i], config); await keyPacket.encrypt(passphrases[i], config);
@ -219,7 +222,7 @@ export async function encryptKey({ privateKey, passphrase, config }) {
return clonedPrivateKey; return clonedPrivateKey;
} catch (err) { } catch (err) {
clonedPrivateKey.clearPrivateParams(); clonedPrivateKey.clearPrivateParams();
return onError('Error encrypting private key', err); throw util.wrapError('Error encrypting private key', err);
} }
} }
@ -253,7 +256,7 @@ export async function encryptKey({ privateKey, passphrase, config }) {
* @async * @async
* @static * @static
*/ */
export function encrypt({ message, encryptionKeys, signingKeys, passwords, sessionKey, armor = true, signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { export async function encrypt({ message, encryptionKeys, signingKeys, passwords, sessionKey, armor = true, signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
checkMessage(message); encryptionKeys = toArray(encryptionKeys); signingKeys = toArray(signingKeys); passwords = toArray(passwords); signingUserIDs = toArray(signingUserIDs); encryptionUserIDs = toArray(encryptionUserIDs); checkMessage(message); encryptionKeys = toArray(encryptionKeys); signingKeys = toArray(signingKeys); passwords = toArray(passwords); signingUserIDs = toArray(signingUserIDs); encryptionUserIDs = toArray(encryptionUserIDs);
if (rest.detached) { if (rest.detached) {
@ -262,11 +265,12 @@ export function encrypt({ message, encryptionKeys, signingKeys, passwords, sessi
if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead"); if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead");
if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead"); if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead");
return Promise.resolve().then(async function() { if (!signingKeys) {
const streaming = message.fromStream; signingKeys = [];
if (!signingKeys) { }
signingKeys = [];
} const streaming = message.fromStream;
try {
if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified
message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config);
} }
@ -277,7 +281,9 @@ export function encrypt({ message, encryptionKeys, signingKeys, passwords, sessi
message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config);
const data = armor ? message.armor(config) : message.write(); const data = armor ? message.armor(config) : message.write();
return convertStream(data, streaming, armor ? 'utf8' : 'binary'); return convertStream(data, streaming, armor ? 'utf8' : 'binary');
}).catch(onError.bind(null, 'Error encrypting message')); } catch (err) {
throw util.wrapError('Error encrypting message', err);
}
} }
/** /**
@ -311,13 +317,14 @@ export function encrypt({ message, encryptionKeys, signingKeys, passwords, sessi
* @async * @async
* @static * @static
*/ */
export function decrypt({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { export async function decrypt({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
checkMessage(message); verificationKeys = toArray(verificationKeys); decryptionKeys = toArray(decryptionKeys); passwords = toArray(passwords); sessionKeys = toArray(sessionKeys); checkMessage(message); verificationKeys = toArray(verificationKeys); decryptionKeys = toArray(decryptionKeys); passwords = toArray(passwords); sessionKeys = toArray(sessionKeys);
if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead"); if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead");
if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead"); if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead");
return message.decrypt(decryptionKeys, passwords, sessionKeys, date, config).then(async function(decrypted) { try {
const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config);
if (!verificationKeys) { if (!verificationKeys) {
verificationKeys = []; verificationKeys = [];
} }
@ -344,7 +351,9 @@ export function decrypt({ message, decryptionKeys, passwords, sessionKeys, verif
result.data = await convertStream(result.data, message.fromStream, format); result.data = await convertStream(result.data, message.fromStream, format);
if (!message.fromStream) await prepareSignatures(result.signatures); if (!message.fromStream) await prepareSignatures(result.signatures);
return result; return result;
}).catch(onError.bind(null, 'Error decrypting message')); } catch (err) {
throw util.wrapError('Error decrypting message', err);
}
} }
@ -370,7 +379,7 @@ export function decrypt({ message, decryptionKeys, passwords, sessionKeys, verif
* @async * @async
* @static * @static
*/ */
export function sign({ message, signingKeys, armor = true, detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { export async function sign({ message, signingKeys, armor = true, detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
checkCleartextOrMessage(message); checkCleartextOrMessage(message);
if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead"); if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead");
@ -378,8 +387,11 @@ export function sign({ message, signingKeys, armor = true, detached = false, sig
if (message instanceof CleartextMessage && detached) throw new Error("Can't detach-sign a cleartext message"); if (message instanceof CleartextMessage && detached) throw new Error("Can't detach-sign a cleartext message");
signingKeys = toArray(signingKeys); signingUserIDs = toArray(signingUserIDs); signingKeys = toArray(signingKeys); signingUserIDs = toArray(signingUserIDs);
if (!signingKeys || signingKeys.length === 0) {
throw new Error('No signing keys provided');
}
return Promise.resolve().then(async function() { try {
let signature; let signature;
if (detached) { if (detached) {
signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config);
@ -396,7 +408,9 @@ export function sign({ message, signingKeys, armor = true, detached = false, sig
}); });
} }
return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary');
}).catch(onError.bind(null, 'Error signing message')); } catch (err) {
throw util.wrapError('Error signing message', err);
}
} }
/** /**
@ -425,7 +439,7 @@ export function sign({ message, signingKeys, armor = true, detached = false, sig
* @async * @async
* @static * @static
*/ */
export function verify({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { export async function verify({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
checkCleartextOrMessage(message); checkCleartextOrMessage(message);
if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead"); if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead");
@ -434,7 +448,7 @@ export function verify({ message, verificationKeys, expectSigned = false, format
verificationKeys = toArray(verificationKeys); verificationKeys = toArray(verificationKeys);
return Promise.resolve().then(async function() { try {
const result = {}; const result = {};
if (signature) { if (signature) {
result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); result.signatures = await message.verifyDetached(signature, verificationKeys, date, config);
@ -457,7 +471,9 @@ export function verify({ message, verificationKeys, expectSigned = false, format
result.data = await convertStream(result.data, message.fromStream, format); result.data = await convertStream(result.data, message.fromStream, format);
if (!message.fromStream) await prepareSignatures(result.signatures); if (!message.fromStream) await prepareSignatures(result.signatures);
return result; return result;
}).catch(onError.bind(null, 'Error verifying signed message')); } catch (err) {
throw util.wrapError('Error verifying signed message', err);
}
} }
@ -478,16 +494,17 @@ export function verify({ message, verificationKeys, expectSigned = false, format
* @async * @async
* @static * @static
*/ */
export function generateSessionKey({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { export async function generateSessionKey({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
encryptionKeys = toArray(encryptionKeys); encryptionUserIDs = toArray(encryptionUserIDs); encryptionKeys = toArray(encryptionKeys); encryptionUserIDs = toArray(encryptionUserIDs);
if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead"); if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead");
return Promise.resolve().then(async function() { try {
const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config);
return Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); return sessionKeys;
} catch (err) {
}).catch(onError.bind(null, 'Error generating session key')); throw util.wrapError('Error generating session key', err);
}
} }
/** /**
@ -509,17 +526,17 @@ export function generateSessionKey({ encryptionKeys, date = new Date(), encrypti
* @async * @async
* @static * @static
*/ */
export function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, armor = true, wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { export async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, armor = true, wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
checkBinary(data); checkString(algorithm, 'algorithm'); encryptionKeys = toArray(encryptionKeys); passwords = toArray(passwords); encryptionUserIDs = toArray(encryptionUserIDs); checkBinary(data); checkString(algorithm, 'algorithm'); encryptionKeys = toArray(encryptionKeys); passwords = toArray(passwords); encryptionUserIDs = toArray(encryptionUserIDs);
if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead"); if (rest.publicKeys) throw new Error("The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead");
return Promise.resolve().then(async function() { try {
const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config);
return armor ? message.armor(config) : message.write(); return armor ? message.armor(config) : message.write();
} catch (err) {
}).catch(onError.bind(null, 'Error encrypting session key')); throw util.wrapError('Error encrypting session key', err);
}
} }
/** /**
@ -537,16 +554,17 @@ export function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKe
* @async * @async
* @static * @static
*/ */
export function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { export async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) {
config = { ...defaultConfig, ...config }; config = { ...defaultConfig, ...config };
checkMessage(message); decryptionKeys = toArray(decryptionKeys); passwords = toArray(passwords); checkMessage(message); decryptionKeys = toArray(decryptionKeys); passwords = toArray(passwords);
if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead"); if (rest.privateKeys) throw new Error("The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead");
return Promise.resolve().then(async function() { try {
const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config);
return message.decryptSessionKeys(decryptionKeys, passwords, date, config); return sessionKeys;
} catch (err) {
}).catch(onError.bind(null, 'Error decrypting session keys')); throw util.wrapError('Error decrypting session keys', err);
}
} }
@ -662,22 +680,3 @@ async function prepareSignatures(signatures) {
} }
})); }));
} }
/**
* Global error handler that logs the stack trace and rethrows a high lvl error message.
* @param {String} message - A human readable high level error Message
* @param {Error} error - The internal error that caused the failure
* @private
*/
function onError(message, error) {
// log the stack trace
util.printDebugError(error);
// update error message
try {
error.message = message + ': ' + error.message;
} catch (e) {}
throw error;
}

View File

@ -952,7 +952,7 @@ module.exports = () => describe('OpenPGP.js public api tests', function() {
}); });
it('should throw if missing userIDs', async function() { it('should throw if missing userIDs', async function() {
expect(() => openpgp.generateKey({})).to.throw(/UserIDs are required/); await expect(openpgp.generateKey({})).to.be.rejectedWith(/UserIDs are required/);
}); });
}); });
@ -1126,6 +1126,22 @@ module.exports = () => describe('OpenPGP.js public api tests', function() {
openpgp.config.minRSABits = minRSABitsVal; openpgp.config.minRSABits = minRSABitsVal;
}); });
it('Calling decrypt with encrypted key leads to exception', async function() {
const publicKey = await openpgp.readKey({ armoredKey: pub_key });
const privateKey = await openpgp.readKey({ armoredKey: priv_key });
const encOpt = {
message: await openpgp.createMessage({ text: plaintext }),
encryptionKeys: publicKey
};
const decOpt = {
decryptionKeys: privateKey
};
const encrypted = await openpgp.encrypt(encOpt);
decOpt.message = await openpgp.readMessage({ armoredMessage: encrypted });
await expect(openpgp.decrypt(decOpt)).to.be.rejectedWith('Error decrypting message: Decryption key is not decrypted.');
});
it('decrypt/verify should succeed with valid signature (expectSigned=true)', async function () { it('decrypt/verify should succeed with valid signature (expectSigned=true)', async function () {
const publicKey = await openpgp.readKey({ armoredKey: pub_key }); const publicKey = await openpgp.readKey({ armoredKey: pub_key });
const privateKey = await openpgp.decryptKey({ const privateKey = await openpgp.decryptKey({
@ -1517,6 +1533,12 @@ aOU=
}); });
expect(sig).to.match(/-----END PGP MESSAGE-----\n$/); expect(sig).to.match(/-----END PGP MESSAGE-----\n$/);
}); });
it('Calling sign with no signing key leads to exception', async function() {
await expect(openpgp.sign({
message: await openpgp.createMessage({ text: plaintext })
})).to.be.rejectedWith(/No signing keys provided/);
});
}); });
describe('encrypt, decrypt, sign, verify - integration tests', function() { describe('encrypt, decrypt, sign, verify - integration tests', function() {
@ -1588,32 +1610,6 @@ aOU=
} }
}); });
it('Decrypting key with wrong passphrase should be rejected', async function () {
await expect(openpgp.decryptKey({
privateKey: await openpgp.readKey({ armoredKey: priv_key }),
passphrase: 'wrong passphrase'
})).to.eventually.be.rejectedWith('Incorrect key passphrase');
});
it('Can decrypt key with correct passphrase', async function () {
expect(privateKey.isDecrypted()).to.be.false;
const decryptedKey = await openpgp.decryptKey({ privateKey, passphrase });
expect(decryptedKey.isDecrypted()).to.be.true;
});
it('Calling decrypt with not decrypted key leads to exception', async function() {
const encOpt = {
message: await openpgp.createMessage({ text: plaintext }),
encryptionKeys: publicKey
};
const decOpt = {
decryptionKeys: privateKey
};
const encrypted = await openpgp.encrypt(encOpt);
decOpt.message = await openpgp.readMessage({ armoredMessage: encrypted });
await expect(openpgp.decrypt(decOpt)).to.be.rejectedWith('Error decrypting message: Decryption key is not decrypted.');
});
tryTests('CFB mode (asm.js)', tests, { tryTests('CFB mode (asm.js)', tests, {
if: true, if: true,
beforeEach: function() { beforeEach: function() {