cleanup, docs

This commit is contained in:
Sanjana Rajan 2018-02-12 10:51:54 +01:00
parent 417af8c6bc
commit 989ad5077e
8 changed files with 76 additions and 141 deletions

8
npm-shrinkwrap.json generated
View File

@ -1525,7 +1525,7 @@
"browserify-rsa": "4.0.1",
"create-hash": "1.1.3",
"create-hmac": "1.1.6",
"elliptic": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f",
"elliptic": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c",
"inherits": "2.0.3",
"parse-asn1": "5.1.0"
}
@ -1937,7 +1937,7 @@
"dev": true,
"requires": {
"bn.js": "4.11.8",
"elliptic": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f"
"elliptic": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c"
}
},
"create-hash": {
@ -2325,7 +2325,7 @@
"dev": true
},
"elliptic": {
"version": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f",
"version": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c",
"requires": {
"bn.js": "4.11.8",
"brorand": "1.1.0",
@ -5604,7 +5604,7 @@
"integrity": "sha1-1QfOzkAInFJI4J7GgmaiAwqcYyU=",
"requires": {
"asn1.js": "4.9.2",
"elliptic": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f",
"elliptic": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c",
"safe-buffer": "5.1.1"
},
"dependencies": {

View File

@ -208,22 +208,23 @@ Key.prototype.getKeyIds = function() {
};
/**
* Returns first key packet for given array of key IDs
* @param {Array<module:type/keyid>} keyIds
* Returns array containing first key packet for given key ID or all key packets in the case of a wildcard ID
* @param {type/keyid>} keyIds
* @return {(module:packet/public_subkey|module:packet/public_key|
* module:packet/secret_subkey|module:packet/secret_key|null)}
*/
Key.prototype.getKeyPacket = function(keyIds) {
Key.prototype.getKeyPackets = function(packetKeyId) {
var keys = this.getAllKeyPackets();
if (packetKeyId.isWildcard()) {
return keys;
}
for (var i = 0; i < keys.length; i++) {
var keyId = keys[i].getKeyId();
for (var j = 0; j < keyIds.length; j++) {
if (keyId.equals(keyIds[j])) {
return keys[i];
}
if (keyId.equals(packetKeyId)) {
return [keys[i]];
}
}
return null;
return [];
};
/**

View File

@ -92,16 +92,13 @@ Message.prototype.getSigningKeyIds = function() {
/**
* Decrypt the message. Either a private key, a session key, or a password must be specified.
* @param {Array<Key>} privateKeys (optional) private key with decrypted secret data
* @param {Array<String>} passwords (optional) password used to decrypt
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String }
* @param {Array<Key>} privateKeys (optional) private keys with decrypted secret data
* @param {Array<String>} passwords (optional) passwords used to decrypt
* @param {Array<Object>} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String }
* @return {Message} new message with decrypted content
*/
Message.prototype.decrypt = async function(privateKeys, passwords, sessionKey) {
let keyObjs = sessionKey || await this.decryptSessionKeys(privateKeys, passwords);
if (!util.isArray(keyObjs)) {
keyObjs = [keyObjs];
}
Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys) {
const keyObjs = sessionKeys || await this.decryptSessionKeys(privateKeys, passwords);
const symEncryptedPacketlist = this.packets.filterByTag(
enums.packet.symmetricallyEncrypted,
@ -141,9 +138,9 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKey) {
};
/**
* Decrypt an encrypted session key either with private keys or passwords.
* @param {Array<Key>} privateKeys (optional) private key with decrypted secret data
* @param {Array<String>} passwords (optional) password used to decrypt
* Decrypt encrypted session keys either with private keys or passwords.
* @param {Array<Key>} privateKeys (optional) private keys with decrypted secret data
* @param {Array<String>} passwords (optional) passwords used to decrypt
* @return {Array<{ data:Uint8Array, algorithm:String }>} array of object with potential sessionKey, algorithm pairs
*/
Message.prototype.decryptSessionKeys = function(privateKeys, passwords) {
@ -155,14 +152,12 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) {
throw new Error('No symmetrically encrypted session key packet found.');
}
await Promise.all(symESKeyPacketlist.map(async function(packet) {
for (var i = 0; i < passwords.length; i++) {
await Promise.all(passwords.map(async function(password) {
try {
// eslint-disable-next-line no-await-in-loop
await packet.decrypt(passwords[i]);
await packet.decrypt(password);
keyPackets.push(packet);
break;
} catch (err) {}
}
}));
}));
} else if (privateKeys) {
@ -171,30 +166,21 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) {
throw new Error('No public key encrypted session key packet found.');
}
await Promise.all(pkESKeyPacketlist.map(async function(packet) {
for (var i = 0; i < privateKeys.length; i++){
var privateKeyPackets;
if (packet.publicKeyId.isWildcard()) {
// wildcard key ID - try all key packets
privateKeyPackets = privateKeys[i].getAllKeyPackets();
} else {
privateKeyPackets = [privateKeys[i].getKeyPacket([packet.publicKeyId])];
var privateKeyPackets = privateKeys.reduce(function(acc, privateKey) {
return acc.concat(privateKey.getKeyPackets(packet.publicKeyId));
}, []);
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
if (!privateKeyPacket) {
return;
}
for (var j = 0; j < privateKeyPackets.length; j++) {
var privateKeyPacket = privateKeyPackets[j];
if (!privateKeyPacket) {
continue;
}
if (!privateKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
try {
// eslint-disable-next-line no-await-in-loop
await packet.decrypt(privateKeyPacket);
keyPackets.push(packet);
break;
} catch (err) {}
if (!privateKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
}
try {
await packet.decrypt(privateKeyPacket);
keyPackets.push(packet);
} catch (err) {}
}));
}));
} else {
throw new Error('No key or password specified.');
@ -259,9 +245,10 @@ Message.prototype.getText = function() {
* @param {Array<Key>} keys (optional) public key(s) for message encryption
* @param {Array<String>} passwords (optional) password(s) for message encryption
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String }
* @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs
* @return {Message} new message with encrypted content
*/
Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard) {
Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard=false) {
let symAlgo, msg, symEncryptedPacket;
return Promise.resolve().then(async () => {
if (sessionKey) {
@ -314,9 +301,10 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard) {
* @param {String} symAlgo session key algorithm
* @param {Array<Key>} publicKeys (optional) public key(s) for message encryption
* @param {Array<String>} passwords (optional) for message encryption
* @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs
* @return {Message} new message with encrypted content
*/
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard) {
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard=false) {
var results, packetlist = new packet.List();
return Promise.resolve().then(async () => {
@ -328,11 +316,7 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, us
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
}
var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey();
if (!useWildcard) {
pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId();
} else {
pkESKeyPacket.publicKeyId = type_keyid.wildcard();
}
pkESKeyPacket.publicKeyId = useWildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId();
pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm;
pkESKeyPacket.sessionKey = sessionKey;
pkESKeyPacket.sessionKeyAlgorithm = symAlgo;

View File

@ -196,6 +196,7 @@ export function decryptKey({ privateKey, passphrase }) {
* @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object)
* @param {Signature} signature (optional) a detached signature to add to the encrypted message
* @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object
* @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs
* @return {Promise<Object>} encrypted (and optionally signed message) in the form:
* {data: ASCII armored message if 'armor' is true,
* message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true}
@ -217,11 +218,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey,
if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified
if (detached) {
var detachedSignature = await message.signDetached(privateKeys, signature);
if (armor) {
result.signature = detachedSignature.armor();
} else {
result.signature = detachedSignature;
}
result.signature = armor ? detachedSignature.armor() : detachedSignature;
} else {
message = await message.sign(privateKeys, signature);
}
@ -245,25 +242,25 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey,
/**
* Decrypts a message with the user's private key, a session key or a password. 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|Array<Key>} privateKeys (optional) private key with decrypted secret key data or session key
* @param {String|Array<String>} passwords (optional) single password to decrypt the message
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String }
* @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, to verify signatures
* @param {String} format (optional) return data format either as 'utf8' or 'binary'
* @param {Signature} signature (optional) detached signature for verification
* @param {Message} message the message object with the encrypted data
* @param {Key|Array<Key>} privateKeys (optional) private keys with decrypted secret key data or session key
* @param {String|Array<String>} passwords (optional) passwords to decrypt the message
* @param {Object|Array<Object>} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String }
* @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, to verify signatures
* @param {String} format (optional) return data format either as 'utf8' or 'binary'
* @param {Signature} signature (optional) detached signature for verification
* @return {Promise<Object>} decrypted and verified message in the form:
* { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] }
* @static
*/
export function decrypt({ message, privateKeys, passwords, sessionKey, publicKeys, format='utf8', signature=null }) {
checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format='utf8', signature=null }) {
checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); sessionKeys = toArray(sessionKeys);
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKey, publicKeys, format, signature });
return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKeys, publicKeys, format, signature });
}
return message.decrypt(privateKeys, passwords, sessionKey).then(async function(message) {
return message.decrypt(privateKeys, passwords, sessionKeys).then(async function(message) {
const result = parseMessage(message, format);
@ -271,13 +268,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKey, publicKey
publicKeys = [];
}
if (signature) {
//detached signature
result.signatures = await message.verifyDetached(signature, publicKeys);
} else {
result.signatures = await message.verify(publicKeys);
}
result.signatures = signature ? await message.verifyDetached(signature, publicKeys) : await message.verify(publicKeys);
return result;
}).catch(onError.bind(null, 'Error decrypting message'));
@ -312,21 +303,11 @@ export function sign({ data, privateKeys, armor=true, detached=false}) {
var result = {};
return Promise.resolve().then(async function() {
var message;
if (util.isString(data)) {
message = new CleartextMessage(data);
} else {
message = messageLib.fromBinary(data);
}
var message = util.isString(data) ? new CleartextMessage(data) : messageLib.fromBinary(data);
if (detached) {
var signature = await message.signDetached(privateKeys);
if (armor) {
result.signature = signature.armor();
} else {
result.signature = signature;
}
result.signature = armor ? signature.armor() : signature;
} else {
message = await message.sign(privateKeys);
if (armor) {
@ -360,18 +341,8 @@ export function verify({ message, publicKeys, signature=null }) {
return Promise.resolve().then(async function() {
var result = {};
if (CleartextMessage.prototype.isPrototypeOf(message)) {
result.data = message.getText();
} else {
result.data = message.getLiteralData();
}
if (signature) {
//detached signature
result.signatures = await message.verifyDetached(signature, publicKeys);
} else {
result.signatures = await message.verify(publicKeys);
}
result.data = CleartextMessage.prototype.isPrototypeOf(message) ? message.getText() : message.getLiteralData();
result.signatures = signature ? await message.verifyDetached(signature, publicKeys) : await message.verify(publicKeys);
return result;
}).catch(onError.bind(null, 'Error verifying cleartext signed message'));
@ -392,6 +363,7 @@ export function verify({ message, publicKeys, signature=null }) {
* @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256'
* @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, used to encrypt the key
* @param {String|Array<String>} passwords (optional) passwords for the message
* @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs
* @return {Promise<Message>} the encrypted session key packets contained in a message object
* @static
*/
@ -410,7 +382,7 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords, useW
}
/**
* Decrypt a symmetric session key with a private key or password. Either a private key or
* Decrypt symmetric session keys with a private key or password. Either a private key or
* a password must be specified.
* @param {Message} message a message object containing the encrypted session key packets
* @param {Key|Array<Key} privateKeys (optional) private keys with decrypted secret key data

View File

@ -71,6 +71,7 @@ export default function PublicKeyEncryptedSessionKey() {
* @return {module:packet/public_key_encrypted_session_key} Object representation
*/
PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
this.version = bytes[0];
this.publicKeyId.read(bytes.subarray(1,bytes.length));
this.publicKeyAlgorithm = enums.read(enums.publicKey, bytes[9]);

View File

@ -62,7 +62,7 @@ Keyid.prototype.isNull = function() {
};
Keyid.prototype.isWildcard = function() {
return this.toHex() === '0000000000000000';
return /^0+$/.test(this.toHex());
};
Keyid.mapToHex = function (keyId) {
@ -83,6 +83,6 @@ Keyid.fromId = function (hex) {
Keyid.wildcard = function () {
var keyid = new Keyid();
keyid.read(util.str2Uint8Array(util.hex2bin('0000000000000000')));
keyid.read(new Uint8Array(8));
return keyid;
};

View File

@ -578,7 +578,7 @@ describe('OpenPGP.js public api tests', function() {
}).then(function(decryptedSessionKeys) {
return openpgp.decrypt({
sessionKey: decryptedSessionKeys[0],
sessionKeys: decryptedSessionKeys[0],
message: openpgp.message.readArmored(msgAsciiArmored)
});
@ -601,30 +601,7 @@ describe('OpenPGP.js public api tests', function() {
}).then(function(decryptedSessionKeys) {
return openpgp.decrypt({
sessionKey: decryptedSessionKeys[0],
message: openpgp.message.readArmored(msgAsciiArmored)
});
}).then(function(decrypted) {
expect(decrypted.data).to.equal(plaintext);
});
});
it('roundtrip workflow: encrypt, decryptSessionKeys, decrypt with multiple passwords', function() {
var msgAsciiArmored;
return openpgp.encrypt({
data: plaintext,
passwords: password2
}).then(function(encrypted) {
msgAsciiArmored = encrypted.data;
return openpgp.decryptSessionKeys({
message: openpgp.message.readArmored(msgAsciiArmored),
passwords: [password1, password2, password3]
});
}).then(function(decryptedSessionKeys) {
return openpgp.decrypt({
sessionKey: decryptedSessionKeys[0],
sessionKeys: decryptedSessionKeys[0],
message: openpgp.message.readArmored(msgAsciiArmored)
});
@ -647,7 +624,7 @@ describe('OpenPGP.js public api tests', function() {
}).then(function(decryptedSessionKeys) {
return openpgp.decrypt({
sessionKey: decryptedSessionKeys[0],
sessionKeys: decryptedSessionKeys,
message: openpgp.message.readArmored(msgAsciiArmored)
});
@ -727,7 +704,7 @@ describe('OpenPGP.js public api tests', function() {
});
});
it('should encrypt then decrypt wuth multiple private keys', function() {
it('should encrypt then decrypt with multiple private keys', function() {
var privKeyDE = openpgp.key.readArmored(priv_key_de).keys[0];
privKeyDE.decrypt(passphrase);
@ -802,7 +779,7 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function(encrypted) {
expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/);
var decOpt = {
sessionKey: encrypted.sessionKey,
sessionKeys: encrypted.sessionKey,
message: openpgp.message.readArmored(encrypted.data)
};
return openpgp.decrypt(decOpt);
@ -824,7 +801,7 @@ describe('OpenPGP.js public api tests', function() {
publicKeys: publicKey.keys
};
var decOpt = {
sessionKey: sessionKey
sessionKeys: sessionKey
};
return openpgp.encrypt(encOpt).then(function(encrypted) {
expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/);
@ -842,7 +819,7 @@ describe('OpenPGP.js public api tests', function() {
};
var encOpt = {
data: plaintext,
sessionKey: sessionKey,
sessionKeys: sessionKey,
publicKeys: publicKey.keys
};
var decOpt = {

View File

@ -539,8 +539,8 @@ describe("Signature", function() {
var keyids = sMsg.getSigningKeyIds();
expect(pubKey2.getKeyPacket(keyids)).to.exist;
expect(pubKey3.getKeyPacket(keyids)).to.exist;
expect(pubKey2.getKeyPackets(keyids[1])).to.not.be.empty;
expect(pubKey3.getKeyPackets(keyids[0])).to.not.be.empty;
expect(sMsg.getText()).to.equal(plaintext);
@ -586,8 +586,8 @@ describe("Signature", function() {
var keyids = csMsg.getSigningKeyIds();
expect(pubKey2.getKeyPacket(keyids)).to.exist;
expect(pubKey3.getKeyPacket(keyids)).to.exist;
expect(pubKey2.getKeyPackets(keyids[0])).to.not.be.empty;
expect(pubKey3.getKeyPackets(keyids[1])).to.not.be.empty;
return openpgp.verify({ publicKeys:[pubKey2, pubKey3], message:csMsg }).then(function(cleartextSig) {
expect(cleartextSig).to.exist;