Write tests for new api: openpgp.encrypt/decrypt
This commit is contained in:
parent
a44e1e5024
commit
b1f6266cc8
|
@ -53,7 +53,7 @@ export function initWorker({ path='openpgp.worker.js', worker } = {}) {
|
||||||
if (worker || typeof window !== 'undefined' && window.Worker) {
|
if (worker || typeof window !== 'undefined' && window.Worker) {
|
||||||
asyncProxy = new AsyncProxy({ path, worker, config });
|
asyncProxy = new AsyncProxy({ path, worker, config });
|
||||||
} else {
|
} 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
|
// js fallback already tried
|
||||||
if (config.debug) { console.error(err); }
|
if (config.debug) { console.error(err); }
|
||||||
if (!util.getWebCrypto()) {
|
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
|
// 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);
|
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
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encrypt({ data, publicKeys, privateKeys, passwords, filename, packets }) {
|
export function encrypt({ data, publicKeys, privateKeys, passwords, filename, packets }) {
|
||||||
publicKeys = toArray(publicKeys);
|
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
|
||||||
privateKeys = toArray(privateKeys);
|
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.encrypt({ data, publicKeys, privateKeys, passwords, filename, packets });
|
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);
|
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.
|
* Either a private key, a session key or a password must be specified.
|
||||||
* @param {Message} message the message object with the encrypted data
|
* @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} 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} sessionKey (optional) session key as a binary string
|
||||||
* @param {String} password (optional) single password to decrypt the message
|
* @param {String} password (optional) single password to decrypt the message
|
||||||
* @param {String} format (optional) return data format either as 'utf8' or 'binary'
|
* @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 }] }
|
* { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] }
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function decrypt({ message, privateKey, publickeys, sessionKey, password, format='utf8' }) {
|
export function decrypt({ message, privateKey, publicKeys, sessionKey, password, format='utf8' }) {
|
||||||
publickeys = toArray(publickeys);
|
checkMessage(message); publicKeys = toArray(publicKeys);
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
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(() => {
|
return execute(() => {
|
||||||
|
|
||||||
message = message.decrypt(privateKey, sessionKey, password);
|
message = message.decrypt(privateKey, sessionKey, password);
|
||||||
const result = parseMessage(message, format);
|
const result = parseMessage(message, format);
|
||||||
if (publickeys && result.data) { // verify only if publickeys are specified
|
if (publicKeys && result.data) { // verify only if publicKeys are specified
|
||||||
result.signatures = message.verify(publickeys);
|
result.signatures = message.verify(publicKeys);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}, 'Error decrypting message!');
|
}, 'Error decrypting message');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,10 +210,8 @@ export function decrypt({ message, privateKey, publickeys, sessionKey, password,
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function sign({ data, privateKeys }) {
|
export function sign({ data, privateKeys }) {
|
||||||
|
checkString(data);
|
||||||
privateKeys = toArray(privateKeys);
|
privateKeys = toArray(privateKeys);
|
||||||
if (!util.isString(data)) {
|
|
||||||
throw new Error('Only cleartext data of type String supported!');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.sign({ data, privateKeys });
|
return asyncProxy.sign({ data, privateKeys });
|
||||||
|
@ -228,7 +225,7 @@ export function sign({ data, privateKeys }) {
|
||||||
data: cleartextMessage.armor()
|
data: cleartextMessage.armor()
|
||||||
};
|
};
|
||||||
|
|
||||||
}, 'Error signing cleartext message!');
|
}, 'Error signing cleartext message');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -240,10 +237,8 @@ export function sign({ data, privateKeys }) {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function verify({ message, publicKeys }) {
|
export function verify({ message, publicKeys }) {
|
||||||
|
checkCleartextMessage(message);
|
||||||
publicKeys = toArray(publicKeys);
|
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
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.verify({ message, publicKeys });
|
return asyncProxy.verify({ message, publicKeys });
|
||||||
|
@ -254,7 +249,7 @@ export function verify({ message, publicKeys }) {
|
||||||
data: message.getText(),
|
data: message.getText(),
|
||||||
signatures: message.verify(publicKeys)
|
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()
|
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 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.
|
* Format user ids for internal use.
|
||||||
*/
|
*/
|
||||||
|
@ -324,7 +343,7 @@ function formatUserIds(options) {
|
||||||
options.userIds = toArray(options.userIds); // normalize to array
|
options.userIds = toArray(options.userIds); // normalize to array
|
||||||
options.userIds = options.userIds.map(id => {
|
options.userIds = options.userIds.map(id => {
|
||||||
if (util.isString(id) && !util.isUserId(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)) {
|
if (util.isUserId(id)) {
|
||||||
return id; // user id is already in correct format... no conversion necessary
|
return id; // user id is already in correct format... no conversion necessary
|
||||||
|
@ -333,7 +352,7 @@ function formatUserIds(options) {
|
||||||
id.name = id.name || '';
|
id.name = id.name || '';
|
||||||
id.email = id.email || '';
|
id.email = id.email || '';
|
||||||
if (!util.isString(id.name) || (id.email && !util.isEmailAddress(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 + '>';
|
return id.name + ' <' + id.email + '>';
|
||||||
});
|
});
|
||||||
|
@ -364,7 +383,7 @@ function createMessage(data, filename) {
|
||||||
} else if (util.isString(data)) {
|
} else if (util.isString(data)) {
|
||||||
msg = messageLib.fromText(data, filename);
|
msg = messageLib.fromText(data, filename);
|
||||||
} else {
|
} 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;
|
return msg;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +430,7 @@ function parseMessage(message, format) {
|
||||||
filename: message.getFilename()
|
filename: message.getFilename()
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid format!');
|
throw new Error('Invalid format');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,5 +457,5 @@ function onError(message, error) {
|
||||||
// log the stack trace
|
// log the stack trace
|
||||||
if (config.debug) { console.error(error.stack); }
|
if (config.debug) { console.error(error.stack); }
|
||||||
// rethrow new high level error for api users
|
// rethrow new high level error for api users
|
||||||
throw new Error(message);
|
throw new Error(message + ': ' + error.message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(() => {
|
return this.execute(() => {
|
||||||
if(publicKeys) {
|
if(options.publicKeys) {
|
||||||
publicKeys = publicKeys.length ? publicKeys : [publicKeys];
|
options.publicKeys = options.publicKeys.map(key => key.toPacketlist());
|
||||||
publicKeys = publicKeys.map(key => key.toPacketlist());
|
|
||||||
}
|
}
|
||||||
if(privateKeys) {
|
if(options.privateKeys) {
|
||||||
privateKeys = privateKeys.length ? privateKeys : [privateKeys];
|
options.privateKeys = options.privateKeys.map(key => key.toPacketlist());
|
||||||
privateKeys = privateKeys.map(key => key.toPacketlist());
|
|
||||||
}
|
}
|
||||||
this.worker.postMessage({
|
this.worker.postMessage({ event:'encrypt', options });
|
||||||
event:'encrypt',
|
|
||||||
options: { data, publicKeys, privateKeys, passwords, filename, packets }
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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) {
|
AsyncProxy.prototype.decryptSessionKey = function(privateKey, message) {
|
||||||
var self = this;
|
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) {
|
AsyncProxy.prototype.signClearMessage = function(privateKeys, text) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ self.onmessage = function (event) {
|
||||||
var data = null,
|
var data = null,
|
||||||
err = null,
|
err = null,
|
||||||
msg = event.data,
|
msg = event.data,
|
||||||
|
opt = msg.options || {},
|
||||||
correct = false;
|
correct = false;
|
||||||
|
|
||||||
switch (msg.event) {
|
switch (msg.event) {
|
||||||
|
@ -68,14 +69,41 @@ self.onmessage = function (event) {
|
||||||
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
|
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'encrypt-message':
|
case 'generate-key':
|
||||||
if(msg.keys) {
|
window.openpgp.generateKey(opt).then(data => {
|
||||||
msg.keys = msg.keys.map(packetlistCloneToKey);
|
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) {
|
if(opt.privateKeys) {
|
||||||
response({event: 'method-return', data: data});
|
opt.privateKeys = opt.privateKeys.map(packetlistCloneToKey);
|
||||||
}).catch(function(e) {
|
}
|
||||||
response({event: 'method-return', err: e.message});
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -90,31 +118,6 @@ self.onmessage = function (event) {
|
||||||
});
|
});
|
||||||
break;
|
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':
|
case 'decrypt-session-key':
|
||||||
if(!(String.prototype.isPrototypeOf(msg.privateKey) || typeof msg.privateKey === 'string')) {
|
if(!(String.prototype.isPrototypeOf(msg.privateKey) || typeof msg.privateKey === 'string')) {
|
||||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||||
|
@ -127,20 +130,6 @@ self.onmessage = function (event) {
|
||||||
});
|
});
|
||||||
break;
|
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':
|
case 'sign-clear-message':
|
||||||
msg.privateKeys = msg.privateKeys.map(packetlistCloneToKey);
|
msg.privateKeys = msg.privateKeys.map(packetlistCloneToKey);
|
||||||
window.openpgp.signClearMessage(msg.privateKeys, msg.text).then(function(data) {
|
window.openpgp.signClearMessage(msg.privateKeys, msg.text).then(function(data) {
|
||||||
|
@ -164,15 +153,6 @@ self.onmessage = function (event) {
|
||||||
});
|
});
|
||||||
break;
|
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':
|
case 'decrypt-key':
|
||||||
try {
|
try {
|
||||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||||
|
|
|
@ -8,7 +8,7 @@ var sinon = require('sinon'),
|
||||||
|
|
||||||
describe('OpenPGP.js public api tests', function() {
|
describe('OpenPGP.js public api tests', function() {
|
||||||
|
|
||||||
describe('initWorker, getWorker, destroyWorker', function() {
|
describe('initWorker, getWorker, destroyWorker - unit tests', function() {
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
openpgp.destroyWorker(); // cleanup worker in case of failure
|
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)',
|
||||||
|
'',
|
||||||
|
'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',
|
||||||
|
'=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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user