wildcard implementation

This commit is contained in:
Sanjana Rajan 2018-02-09 10:49:15 +01:00
parent d5022a3a4a
commit 7365ffc9b7
4 changed files with 63 additions and 31 deletions

View File

@ -35,6 +35,7 @@ import armor from './encoding/armor';
import enums from './enums';
import util from './util';
import packet from './packet';
import type_keyid from './type/keyid';
import { Signature } from './signature';
import { getPreferredHashAlgo, getPreferredSymAlgo } from './key';
@ -154,10 +155,14 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) {
throw new Error('No symmetrically encrypted session key packet found.');
}
await Promise.all(symESKeyPacketlist.map(async function(packet) {
try {
await packet.decrypt(password);
keyPackets.push(packet);
} catch (err) {}
for (var i = 0; i < passwords.length; i++) {
try {
// eslint-disable-next-line no-await-in-loop
await packet.decrypt(passwords[i]);
keyPackets.push(packet);
break;
} catch (err) {}
}
}));
} else if (privateKeys) {
@ -165,16 +170,30 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) {
if (!pkESKeyPacketlist) {
throw new Error('No public key encrypted session key packet found.');
}
var privateKeyPacket = privateKey.getKeyPacket(this.getEncryptionKeyIds());
if (!privateKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
await Promise.all(pkESKeyPacketlist.map(async function(packet) {
if (packet.publicKeyId.equals(privateKeyPacket.getKeyId())) {
try {
await packet.decrypt(privateKeyPacket);
keyPackets.push(packet);
} catch (err) {}
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])];
}
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) {}
}
}
}));
} else {
@ -242,7 +261,7 @@ Message.prototype.getText = function() {
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String }
* @return {Message} new message with encrypted content
*/
Message.prototype.encrypt = function(keys, passwords, sessionKey) {
Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard) {
let symAlgo, msg, symEncryptedPacket;
return Promise.resolve().then(async () => {
if (sessionKey) {
@ -263,7 +282,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey) {
sessionKey = crypto.generateSessionKey(symAlgo);
}
msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords);
msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, useWildcard);
if (config.aead_protect) {
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
@ -297,7 +316,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey) {
* @param {Array<String>} passwords (optional) for message encryption
* @return {Message} new message with encrypted content
*/
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords) {
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard) {
var results, packetlist = new packet.List();
return Promise.resolve().then(async () => {
@ -309,7 +328,11 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords) {
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
}
var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey();
pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId();
if (!useWildcard) {
pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId();
} else {
pkESKeyPacket.publicKeyId = type_keyid.wildcard();
}
pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm;
pkESKeyPacket.sessionKey = sessionKey;
pkESKeyPacket.sessionKeyAlgorithm = symAlgo;

View File

@ -201,11 +201,11 @@ export function decryptKey({ privateKey, passphrase }) {
* message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true}
* @static
*/
export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, armor=true, detached=false, signature=null, returnSessionKey=false}) {
export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, armor=true, detached=false, signature=null, returnSessionKey=false, useWildcard=false}) {
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey });
return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey, useWildcard });
}
var result = {};
return Promise.resolve().then(async function() {
@ -226,7 +226,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey,
message = await message.sign(privateKeys, signature);
}
}
return message.encrypt(publicKeys, passwords, sessionKey);
return message.encrypt(publicKeys, passwords, sessionKey, useWildcard);
}).then(encrypted => {
if (armor) {
@ -395,16 +395,16 @@ export function verify({ message, publicKeys, signature=null }) {
* @return {Promise<Message>} the encrypted session key packets contained in a message object
* @static
*/
export function encryptSessionKey({ data, algorithm, publicKeys, passwords }) {
export function encryptSessionKey({ data, algorithm, publicKeys, passwords, useWildcard=false }) {
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords);
if (asyncProxy) { // use web worker if available
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords });
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords, useWildcard });
}
return Promise.resolve().then(async function() {
return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords) };
return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords, useWildcard) };
}).catch(onError.bind(null, 'Error encrypting session key'));
}
@ -412,24 +412,24 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords }) {
/**
* Decrypt a symmetric session key 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} privateKey (optional) private key with decrypted secret key data
* @param {String} password (optional) a single password to decrypt the session key
* @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
* @param {String|Array<String>} passwords (optional) passwords to decrypt the session key
* @return {Promise<Object|undefined>} Array of decrypted session key, algorithm pairs in form:
* { data:Uint8Array, algorithm:String }
* or 'undefined' if no key packets found
* @static
*/
export function decryptSessionKeys({ message, privateKey, password }) {
checkMessage(message);
export function decryptSessionKeys({ message, privateKeys, passwords }) {
checkMessage(message); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
if (asyncProxy) { // use web worker if available
return asyncProxy.delegate('decryptSessionKeys', { message, privateKey, password });
return asyncProxy.delegate('decryptSessionKeys', { message, privateKeys, passwords });
}
return Promise.resolve().then(async function() {
return message.decryptSessionKeys(privateKey, password);
return message.decryptSessionKeys(privateKeys, passwords);
}).catch(onError.bind(null, 'Error decrypting session keys'));
}

View File

@ -71,7 +71,6 @@ 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

@ -61,6 +61,10 @@ Keyid.prototype.isNull = function() {
return this.bytes === '';
};
Keyid.prototype.isWildcard = function() {
return this.toHex() === '0000000000000000';
};
Keyid.mapToHex = function (keyId) {
return keyId.toHex();
};
@ -76,3 +80,9 @@ Keyid.fromId = function (hex) {
keyid.read(util.str2Uint8Array(util.hex2bin(hex)));
return keyid;
};
Keyid.wildcard = function () {
var keyid = new Keyid();
keyid.read(util.str2Uint8Array(util.hex2bin('0000000000000000')));
return keyid;
};