Write tests for new api: openpgp.encrypt/decrypt

This commit is contained in:
Tankred Hase 2016-02-08 23:28:54 +07:00
parent a44e1e5024
commit b1f6266cc8
4 changed files with 328 additions and 156 deletions

View File

@ -53,7 +53,7 @@ export function initWorker({ path='openpgp.worker.js', worker } = {}) {
if (worker || typeof window !== 'undefined' && window.Worker) {
asyncProxy = new AsyncProxy({ path, worker, config });
} else {
throw new Error('Initializing web worker failed!');
throw new Error('Initializing web worker failed');
}
}
@ -109,13 +109,13 @@ export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=fal
// js fallback already tried
if (config.debug) { console.error(err); }
if (!util.getWebCrypto()) {
throw new Error('Error generating keypair using js fallback!');
throw new Error('Error generating keypair using js fallback');
}
// fall back to js keygen in a worker
if (config.debug) { console.log('Error generating keypair using native WebCrypto... falling back back to js!'); }
if (config.debug) { console.log('Error generating keypair using native WebCrypto... falling back back to js'); }
return asyncProxy.generateKey(options);
}).catch(onError.bind(null, 'Error generating keypair!'));
}).catch(onError.bind(null, 'Error generating keypair'));
}
@ -139,8 +139,7 @@ export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=fal
* @static
*/
export function encrypt({ data, publicKeys, privateKeys, passwords, filename, packets }) {
publicKeys = toArray(publicKeys);
privateKeys = toArray(privateKeys);
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
if (asyncProxy) { // use web worker if available
return asyncProxy.encrypt({ data, publicKeys, privateKeys, passwords, filename, packets });
@ -160,7 +159,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, filename, pa
return getAsciiArmored(msg);
}
}, 'Error encrypting message!');
}, 'Error encrypting message');
}
/**
@ -168,7 +167,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, filename, pa
* Either a private key, a session key or a password must be specified.
* @param {Message} message the message object with the encrypted data
* @param {Key} privateKey (optional) private key with decrypted secret key data or session key
* @param {Key|Array<Key>} publickeys (optional) array of publickeys or single key, to verify signatures
* @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, to verify signatures
* @param {String} sessionKey (optional) session key as a binary string
* @param {String} password (optional) single password to decrypt the message
* @param {String} format (optional) return data format either as 'utf8' or 'binary'
@ -176,23 +175,23 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, filename, pa
* { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] }
* @static
*/
export function decrypt({ message, privateKey, publickeys, sessionKey, password, format='utf8' }) {
publickeys = toArray(publickeys);
export function decrypt({ message, privateKey, publicKeys, sessionKey, password, format='utf8' }) {
checkMessage(message); publicKeys = toArray(publicKeys);
if (asyncProxy) { // use web worker if available
return asyncProxy.decrypt({ message, privateKey, publickeys, sessionKey, password, format });
return asyncProxy.decrypt({ message, privateKey, publicKeys, sessionKey, password, format });
}
return execute(() => {
message = message.decrypt(privateKey, sessionKey, password);
const result = parseMessage(message, format);
if (publickeys && result.data) { // verify only if publickeys are specified
result.signatures = message.verify(publickeys);
if (publicKeys && result.data) { // verify only if publicKeys are specified
result.signatures = message.verify(publicKeys);
}
return result;
}, 'Error decrypting message!');
}, 'Error decrypting message');
}
@ -211,10 +210,8 @@ export function decrypt({ message, privateKey, publickeys, sessionKey, password,
* @static
*/
export function sign({ data, privateKeys }) {
checkString(data);
privateKeys = toArray(privateKeys);
if (!util.isString(data)) {
throw new Error('Only cleartext data of type String supported!');
}
if (asyncProxy) { // use web worker if available
return asyncProxy.sign({ data, privateKeys });
@ -228,7 +225,7 @@ export function sign({ data, privateKeys }) {
data: cleartextMessage.armor()
};
}, 'Error signing cleartext message!');
}, 'Error signing cleartext message');
}
/**
@ -240,10 +237,8 @@ export function sign({ data, privateKeys }) {
* @static
*/
export function verify({ message, publicKeys }) {
checkCleartextMessage(message);
publicKeys = toArray(publicKeys);
if (!(message instanceof cleartext.CleartextMessage)) {
throw new Error('Parameter [message] needs to be of type CleartextMessage.');
}
if (asyncProxy) { // use web worker if available
return asyncProxy.verify({ message, publicKeys });
@ -254,7 +249,7 @@ export function verify({ message, publicKeys }) {
data: message.getText(),
signatures: message.verify(publicKeys)
}), 'Error verifying cleartext signed message!');
}), 'Error verifying cleartext signed message');
}
@ -283,7 +278,7 @@ export function encryptSessionKey({ sessionKey, algo, publicKeys, passwords }) {
data: messageLib.encryptSessionKey(sessionKey, algo, publicKeys, passwords).packets.write()
}), 'Error encrypting session key!');
}), 'Error encrypting session key');
}
/**
@ -303,7 +298,7 @@ export function decryptSessionKey({ message, privateKey, sessionKey, password })
return asyncProxy.decryptSessionKey({ message, privateKey, sessionKey, password });
}
return execute(() => message.decryptSessionKey(privateKey, sessionKey, password), 'Error decrypting session key!');
return execute(() => message.decryptSessionKey(privateKey, sessionKey, password), 'Error decrypting session key');
}
@ -314,6 +309,30 @@ export function decryptSessionKey({ message, privateKey, sessionKey, password })
//////////////////////////
/**
* Input validation
*/
function checkString(data, name) {
if (!util.isString(data)) {
throw new Error('Parameter [' + (name || 'data') + '] must be of type String');
}
}
function checkData(data, name) {
if (!util.isUint8Array(data) && !util.isString(data)) {
throw new Error('Parameter [' + (name || 'data') + '] must be of type String or Uint8Array');
}
}
function checkMessage(message) {
if (!messageLib.Message.prototype.isPrototypeOf(message)) {
throw new Error('Parameter [message] needs to be of type Message');
}
}
function checkCleartextMessage(message) {
if (!cleartext.CleartextMessage.prototype.isPrototypeOf(message)) {
throw new Error('Parameter [message] needs to be of type CleartextMessage');
}
}
/**
* Format user ids for internal use.
*/
@ -324,7 +343,7 @@ function formatUserIds(options) {
options.userIds = toArray(options.userIds); // normalize to array
options.userIds = options.userIds.map(id => {
if (util.isString(id) && !util.isUserId(id)) {
throw new Error('Invalid user id format!');
throw new Error('Invalid user id format');
}
if (util.isUserId(id)) {
return id; // user id is already in correct format... no conversion necessary
@ -333,7 +352,7 @@ function formatUserIds(options) {
id.name = id.name || '';
id.email = id.email || '';
if (!util.isString(id.name) || (id.email && !util.isEmailAddress(id.email))) {
throw new Error('Invalid user id format!');
throw new Error('Invalid user id format');
}
return id.name + ' <' + id.email + '>';
});
@ -364,7 +383,7 @@ function createMessage(data, filename) {
} else if (util.isString(data)) {
msg = messageLib.fromText(data, filename);
} else {
throw new Error('Data must be of type String or Uint8Array!');
throw new Error('Data must be of type String or Uint8Array');
}
return msg;
}
@ -411,7 +430,7 @@ function parseMessage(message, format) {
filename: message.getFilename()
};
} else {
throw new Error('Invalid format!');
throw new Error('Invalid format');
}
}
@ -438,5 +457,5 @@ function onError(message, error) {
// log the stack trace
if (config.debug) { console.error(error.stack); }
// rethrow new high level error for api users
throw new Error(message);
throw new Error(message + ': ' + error.message);
}

View File

@ -145,20 +145,37 @@ AsyncProxy.prototype.generateKey = function(options) {
});
};
AsyncProxy.prototype.encrypt = function({ data, publicKeys, privateKeys, passwords, filename, packets }) {
AsyncProxy.prototype.encrypt = function(options) {
return this.execute(() => {
if(publicKeys) {
publicKeys = publicKeys.length ? publicKeys : [publicKeys];
publicKeys = publicKeys.map(key => key.toPacketlist());
if(options.publicKeys) {
options.publicKeys = options.publicKeys.map(key => key.toPacketlist());
}
if(privateKeys) {
privateKeys = privateKeys.length ? privateKeys : [privateKeys];
privateKeys = privateKeys.map(key => key.toPacketlist());
if(options.privateKeys) {
options.privateKeys = options.privateKeys.map(key => key.toPacketlist());
}
this.worker.postMessage({
event:'encrypt',
options: { data, publicKeys, privateKeys, passwords, filename, packets }
});
this.worker.postMessage({ event:'encrypt', options });
});
};
AsyncProxy.prototype.decrypt = function(options) {
return new Promise((resolve, reject) => {
if(options.publicKeys) {
options.publicKeys = options.publicKeys.map(key => key.toPacketlist());
}
if(options.privateKey) {
options.privateKey = options.privateKey.toPacketlist();
}
this.worker.postMessage({ event:'decrypt', options });
this.tasks.push({ resolve: data => {
if (data.signatures) {
data.signatures = data.signatures.map(sig => {
sig.keyid = type_keyid.fromClone(sig.keyid);
return sig;
});
}
resolve(data);
}, reject });
});
};
@ -172,36 +189,6 @@ AsyncProxy.prototype.encryptSessionKey = function({ sessionKey, algo, keys, pass
});
};
AsyncProxy.prototype.signAndEncryptMessage = function(publicKeys, privateKey, text) {
var self = this;
return self.execute(function() {
if (!publicKeys.length) {
publicKeys = [publicKeys];
}
publicKeys = publicKeys.map(function(key) {
return key.toPacketlist();
});
privateKey = privateKey.toPacketlist();
self.worker.postMessage({
event: 'sign-and-encrypt-message',
publicKeys: publicKeys,
privateKey: privateKey,
text: text
});
});
};
AsyncProxy.prototype.decryptMessage = function({ message, privateKey, format }) {
return this.execute(() => {
if(!(String.prototype.isPrototypeOf(privateKey) || typeof privateKey === 'string' || Uint8Array.prototype.isPrototypeOf(privateKey))) {
privateKey = privateKey.toPacketlist();
}
this.worker.postMessage({ event:'decrypt-message', message, privateKey, format });
});
};
AsyncProxy.prototype.decryptSessionKey = function(privateKey, message) {
var self = this;
@ -218,36 +205,6 @@ AsyncProxy.prototype.decryptSessionKey = function(privateKey, message) {
});
};
AsyncProxy.prototype.decryptAndVerifyMessage = function(privateKey, publicKeys, message) {
var self = this;
var promise = new Promise(function(resolve, reject) {
privateKey = privateKey.toPacketlist();
if (!publicKeys.length) {
publicKeys = [publicKeys];
}
publicKeys = publicKeys.map(function(key) {
return key.toPacketlist();
});
self.worker.postMessage({
event: 'decrypt-and-verify-message',
privateKey: privateKey,
publicKeys: publicKeys,
message: message
});
self.tasks.push({ resolve:function(data) {
data.signatures = data.signatures.map(function(sig) {
sig.keyid = type_keyid.fromClone(sig.keyid);
return sig;
});
resolve(data);
}, reject:reject });
});
return promise;
};
AsyncProxy.prototype.signClearMessage = function(privateKeys, text) {
var self = this;

View File

@ -52,6 +52,7 @@ self.onmessage = function (event) {
var data = null,
err = null,
msg = event.data,
opt = msg.options || {},
correct = false;
switch (msg.event) {
@ -68,14 +69,41 @@ self.onmessage = function (event) {
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
break;
case 'encrypt-message':
if(msg.keys) {
msg.keys = msg.keys.map(packetlistCloneToKey);
case 'generate-key':
window.openpgp.generateKey(opt).then(data => {
data.key = data.key.toPacketlist();
response({ event:'method-return', data });
}).catch(e => {
response({ event:'method-return', err:e.message });
});
break;
case 'encrypt':
if(opt.publicKeys) {
opt.publicKeys = opt.publicKeys.map(packetlistCloneToKey);
}
window.openpgp.encryptMessage(msg.keys, msg.data, msg.passwords, msg.params).then(function(data) {
response({event: 'method-return', data: data});
}).catch(function(e) {
response({event: 'method-return', err: e.message});
if(opt.privateKeys) {
opt.privateKeys = opt.privateKeys.map(packetlistCloneToKey);
}
window.openpgp.encrypt(opt).then(data => {
response({ event:'method-return', data });
}).catch(e => {
response({ event:'method-return', err:e.message });
});
break;
case 'decrypt':
if(opt.publicKeys) {
opt.publicKeys = opt.publicKeys.map(packetlistCloneToKey);
}
if(opt.privateKey) {
opt.privateKey = packetlistCloneToKey(opt.privateKey);
}
opt.message = packetlistCloneToMessage(opt.message.packets);
window.openpgp.decrypt(opt).then(data => {
response({ event:'method-return', data });
}).catch(e => {
response({ event:'method-return', err:e.message });
});
break;
@ -90,31 +118,6 @@ self.onmessage = function (event) {
});
break;
case 'sign-and-encrypt-message':
if (!msg.publicKeys.length) {
msg.publicKeys = [msg.publicKeys];
}
msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey);
msg.privateKey = packetlistCloneToKey(msg.privateKey);
window.openpgp.signAndEncryptMessage(msg.publicKeys, msg.privateKey, msg.text).then(function(data) {
response({event: 'method-return', data: data});
}).catch(function(e) {
response({event: 'method-return', err: e.message});
});
break;
case 'decrypt-message':
if(!(String.prototype.isPrototypeOf(msg.privateKey) || typeof msg.privateKey === 'string' || Uint8Array.prototype.isPrototypeOf(msg.privateKey))) {
msg.privateKey = packetlistCloneToKey(msg.privateKey);
}
msg.message = packetlistCloneToMessage(msg.message.packets);
window.openpgp.decryptMessage(msg.privateKey, msg.message, msg.params).then(function(data) {
response({event: 'method-return', data: data});
}).catch(function(e) {
response({event: 'method-return', err: e.message});
});
break;
case 'decrypt-session-key':
if(!(String.prototype.isPrototypeOf(msg.privateKey) || typeof msg.privateKey === 'string')) {
msg.privateKey = packetlistCloneToKey(msg.privateKey);
@ -127,20 +130,6 @@ self.onmessage = function (event) {
});
break;
case 'decrypt-and-verify-message':
msg.privateKey = packetlistCloneToKey(msg.privateKey);
if (!msg.publicKeys.length) {
msg.publicKeys = [msg.publicKeys];
}
msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey);
msg.message = packetlistCloneToMessage(msg.message.packets);
window.openpgp.decryptAndVerifyMessage(msg.privateKey, msg.publicKeys, msg.message).then(function(data) {
response({event: 'method-return', data: data});
}).catch(function(e) {
response({event: 'method-return', err: e.message});
});
break;
case 'sign-clear-message':
msg.privateKeys = msg.privateKeys.map(packetlistCloneToKey);
window.openpgp.signClearMessage(msg.privateKeys, msg.text).then(function(data) {
@ -164,15 +153,6 @@ self.onmessage = function (event) {
});
break;
case 'generate-key':
window.openpgp.generateKey(msg.options).then(function(data) {
data.key = data.key.toPacketlist();
response({event: 'method-return', data: data});
}).catch(function(e) {
response({event: 'method-return', err: e.message});
});
break;
case 'decrypt-key':
try {
msg.privateKey = packetlistCloneToKey(msg.privateKey);

View File

@ -8,7 +8,7 @@ var sinon = require('sinon'),
describe('OpenPGP.js public api tests', function() {
describe('initWorker, getWorker, destroyWorker', function() {
describe('initWorker, getWorker, destroyWorker - unit tests', function() {
afterEach(function() {
openpgp.destroyWorker(); // cleanup worker in case of failure
});
@ -264,4 +264,220 @@ describe('OpenPGP.js public api tests', function() {
});
});
describe('encrypt, decrypt - integration tests', function() {
var pub_key =
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
'',
'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+',
'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5',
'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0',
'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS',
'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6',
'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki',
'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf',
'9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa',
'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag',
'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr',
'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb',
'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA',
'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP',
'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2',
'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X',
'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD',
'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY',
'hz3tYjKhoFTKEIq3y3Pp',
'=h/aX',
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
var priv_key =
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
'',
'lQH+BFJhL04BBADclrUEDDsm0PSZbQ6pml9FpzTyXiyCyDN+rMOsy9J300Oc10kt',
'/nyBej9vZSRcaW5VpNNj0iA+c1/w2FPf84zNsTzvDmuMaNHFUzky4/vkYuZra//3',
'+Ri7CF8RawSYQ/4IRbC9zqdBlzniyfQOW7Dp/LYe8eibnDSrmkQem0G0jwARAQAB',
'/gMDAu7L//czBpE40p1ZqO8K3k7UejemjsQqc7kOqnlDYd1Z6/3NEA/UM30Siipr',
'KjdIFY5+hp0hcs6EiiNq0PDfm/W2j+7HfrZ5kpeQVxDek4irezYZrl7JS2xezaLv',
'k0Fv/6fxasnFtjOM6Qbstu67s5Gpl9y06ZxbP3VpT62+Xeibn/swWrfiJjuGEEhM',
'bgnsMpHtzAz/L8y6KSzViG/05hBaqrvk3/GeEA6nE+o0+0a6r0LYLTemmq6FbaA1',
'PHo+x7k7oFcBFUUeSzgx78GckuPwqr2mNfeF+IuSRnrlpZl3kcbHASPAOfEkyMXS',
'sWGE7grCAjbyQyM3OEXTSyqnehvGS/1RdB6kDDxGwgE/QFbwNyEh6K4eaaAThW2j',
'IEEI0WEnRkPi9fXyxhFsCLSI1XhqTaq7iDNqJTxE+AX2b9ZuZXAxI3Tc/7++vEyL',
'3p18N/MB2kt1Wb1azmXWL2EKlT1BZ5yDaJuBQ8BhphM3tCRUZXN0IE1jVGVzdGlu',
'Z3RvbiA8dGVzdEBleGFtcGxlLmNvbT6IuQQTAQIAIwUCUmEvTgIbLwcLCQgHAwIB',
'BhUIAgkKCwQWAgMBAh4BAheAAAoJEEpjYTpNbkCUMAwD+gIK08qpEZSVas9qW+Ok',
'32wzNkwxe6PQgZwcyBqMQYZUcKagC8+89pMQQ5sKUGvpIgat42Tf1KLGPcvG4cDA',
'JZ6w2PYz9YHQqPh9LA+PAnV8m25TcGmKcKgvFUqQ3U53X/Y9sBP8HooRqfwwHcv9',
'pMgQmojmNbI4VHydRqIBePawnQH+BFJhL04BBADpH8+0EVolpPiOrXTKoBKTiyrB',
'UyxzodyJ8zmVJ3HMTEU/vidpQwzISwoc/ndDFMXQauq6xqBCD9m2BPQI3UdQzXnb',
'LsAI52nWCIqOkzM5NAKWoKhyXK9Y4UH4v9LAYQgl/stIISvCgG4mJ8lzzEBWvRdf',
'Qm2Ghb64/3V5NDdemwARAQAB/gMDAu7L//czBpE40iPcpLzL7GwBbWFhSWgSLy53',
'Md99Kxw3cApWCok2E8R9/4VS0490xKZIa5y2I/K8thVhqk96Z8Kbt7MRMC1WLHgC',
'qJvkeQCI6PrFM0PUIPLHAQtDJYKtaLXxYuexcAdKzZj3FHdtLNWCooK6n3vJlL1c',
'WjZcHJ1PH7USlj1jup4XfxsbziuysRUSyXkjn92GZLm+64vCIiwhqAYoizF2NHHG',
'hRTN4gQzxrxgkeVchl+ag7DkQUDANIIVI+A63JeLJgWJiH1fbYlwESByHW+zBFNt',
'qStjfIOhjrfNIc3RvsggbDdWQLcbxmLZj4sB0ydPSgRKoaUdRHJY0S4vp9ouKOtl',
'2au/P1BP3bhD0fDXl91oeheYth+MSmsJFDg/vZJzCJhFaQ9dp+2EnjN5auNCNbaI',
'beFJRHFf9cha8p3hh+AK54NRCT++B2MXYf+TPwqX88jYMBv8kk8vYUgo8128r1zQ',
'EzjviQE9BBgBAgAJBQJSYS9OAhsuAKgJEEpjYTpNbkCUnSAEGQECAAYFAlJhL04A',
'CgkQ4IT3RGwgLJe6ogQA2aaJEIBIXtgrs+8WSJ4k3DN4rRXcXaUZf667pjdD9nF2',
'3BzjFH6Z78JIGaxRHJdM7b05aE8YuzM8f3NIlT0F0OLq/TI2muYU9f/U2DQBuf+w',
'KTB62+PELVgi9MsXC1Qv/u/o1LZtmmxTFFOD35xKsxZZI2OJj2pQpqObW27M8Nlc',
'BQQAw2YA3fFc38qPK+PY4rZyTRdbvjyyX+1zeqIo8wn7QCQwXs+OGaH2fGoT35AI',
'SXuqKcWqoEuO7OBSEFThCXBfUYMC01OrqKEswPm/V3zZkLu01q12UMwZach28QwK',
'/YZly4ioND2tdazj17u2rU2dwtiHPe1iMqGgVMoQirfLc+k=',
'=lw5e',
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
var passphrase = 'hello world';
var plaintext = 'short message\nnext line\n한국어/조선말';
var password1 = 'I am a password';
var password2 = 'I am another password';
var privateKey, publicKey;
before(function() {
openpgp.initWorker({ path:'../dist/openpgp.worker.js' });
});
beforeEach(function() {
publicKey = openpgp.key.readArmored(pub_key);
expect(publicKey.keys).to.have.length(1);
expect(publicKey.err).to.not.exist;
privateKey = openpgp.key.readArmored(priv_key);
expect(privateKey.keys).to.have.length(1);
expect(privateKey.err).to.not.exist;
});
after(function() {
openpgp.destroyWorker(); // cleanup worker in case of failure
});
it('Decrypting key with wrong passphrase returns false', function () {
expect(privateKey.keys[0].decrypt('wrong passphrase')).to.be.false;
});
it('Decrypting key with correct passphrase returns true', function () {
expect(privateKey.keys[0].decrypt(passphrase)).to.be.true;
});
function testHelper(encOpt, decOpt, dontUnlock) {
if (!dontUnlock) {
expect(privateKey.keys[0].decrypt(passphrase)).to.be.true;
}
return openpgp.encrypt(encOpt).then(function(encrypted) {
expect(encrypted.data).to.exist;
var msg = openpgp.message.readArmored(encrypted.data);
expect(msg).to.exist;
decOpt.message = msg;
return openpgp.decrypt(decOpt);
});
}
it('Calling decrypt with not decrypted key leads to exception', function (done) {
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
};
var decOpt = {
privateKey: privateKey.keys[0]
};
testHelper(encOpt, decOpt, true).catch(function(error) {
expect(error.message).to.match(/not decrypted/);
done();
});
});
it('should encrypt then decrypt with pgp key pair', function(done) {
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
};
var decOpt = {
privateKey: privateKey.keys[0]
};
testHelper(encOpt, decOpt).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures).to.not.exist;
done();
});
});
it('should encrypt/sign and decrypt/verify with pgp key pair', function(done) {
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
privateKeys: privateKey.keys
};
var decOpt = {
privateKey: privateKey.keys[0],
publicKeys: publicKey.keys
};
testHelper(encOpt, decOpt).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true;
done();
});
});
it('should fail to verify with wrong public pgp key', function(done) {
var wrong_pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n' +
'Version: OpenPGP.js v0.9.0\r\n' +
'Comment: Hoodiecrow - https://hoodiecrow.com\r\n' +
'\r\n' +
'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\r\n' +
'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\r\n' +
'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\r\n' +
'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\r\n' +
'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' +
'=6XMW\r\n' +
'-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n';
var encOpt = {
data: plaintext,
publicKeys: publicKey.keys,
privateKeys: privateKey.keys
};
var decOpt = {
privateKey: privateKey.keys[0],
publicKeys: openpgp.key.readArmored(wrong_pubkey).keys
};
testHelper(encOpt, decOpt).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null;
done();
});
});
it('should encrypt and decrypt with one password', function(done) {
var encOpt = {
data: plaintext,
passwords: password1
};
var decOpt = {
password: password1
};
testHelper(encOpt, decOpt).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
it('should encrypt and decrypt with two password2', function(done) {
var encOpt = {
data: plaintext,
passwords: [password1, password2]
};
var decOpt = {
password: password2
};
testHelper(encOpt, decOpt).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
done();
});
});
});
});