some cleanup

This commit is contained in:
Bart Butler 2018-03-06 10:04:33 -08:00
parent 2bb5db2cf4
commit 1cd9018346
12 changed files with 286 additions and 262 deletions

View File

@ -153,7 +153,7 @@ Key.prototype.packetlist2structure = function(packetlist) {
/**
* Transforms structured key data to packetlist
* @return {module:packet/packetlist} The packets that form a key
* @returns {module:packet/packetlist} The packets that form a key
*/
Key.prototype.toPacketlist = function() {
const packetlist = new packet.List();
@ -210,7 +210,7 @@ Key.prototype.getKeyIds = function() {
/**
* Returns array containing first key packet for given key ID or all key packets in the case of a wildcard ID
* @param {type/keyid} keyId
* @return {(module:packet/public_subkey|module:packet/public_key|
* @returns {(module:packet/public_subkey|module:packet/public_key|
* module:packet/secret_subkey|module:packet/secret_key|null)}
*/
Key.prototype.getKeyPackets = function(packetKeyId) {
@ -229,7 +229,7 @@ Key.prototype.getKeyPackets = function(packetKeyId) {
/**
* Returns userids
* @return {Array<string>} array of userids
* @returns {Array<string>} array of userids
*/
Key.prototype.getUserIds = function() {
const userids = [];
@ -243,7 +243,7 @@ Key.prototype.getUserIds = function() {
/**
* Returns true if this is a public key
* @return {Boolean}
* @returns {Boolean}
*/
Key.prototype.isPublic = function() {
return this.primaryKey.tag === enums.packet.publicKey;
@ -251,7 +251,7 @@ Key.prototype.isPublic = function() {
/**
* Returns true if this is a private key
* @return {Boolean}
* @returns {Boolean}
*/
Key.prototype.isPrivate = function() {
return this.primaryKey.tag === enums.packet.secretKey;
@ -259,7 +259,7 @@ Key.prototype.isPrivate = function() {
/**
* Returns key as public key (shallow copy)
* @return {module:key~Key} new public Key
* @returns {module:key~Key} new public Key
*/
Key.prototype.toPublic = function() {
const packetlist = new packet.List();
@ -290,7 +290,7 @@ Key.prototype.toPublic = function() {
/**
* Returns ASCII armored text of key
* @return {String} ASCII armor
* @returns {String} ASCII armor
*/
Key.prototype.armor = function() {
const type = this.isPublic() ? enums.armor.public_key : enums.armor.private_key;
@ -301,7 +301,7 @@ Key.prototype.armor = function() {
* Returns first key packet or key packet by given keyId that is available for signing or signature verification
* @param {module:type/keyid} keyId, optional
* @param {Date} date use the given date for verification instead of the current time
* @return {(module:packet/secret_subkey|module:packet/secret_key|null)} key packet or null if no signing key has been found
* @returns {(module:packet/secret_subkey|module:packet/secret_key|null)} key packet or null if no signing key has been found
*/
Key.prototype.getSigningKeyPacket = function (keyId=null, date=new Date()) {
const primaryUser = this.getPrimaryUser(date);
@ -379,6 +379,7 @@ Key.prototype.getEncryptionKeyPacket = function(keyId, date=new Date()) {
/**
* Encrypts all secret key and subkey packets
* @param {String} passphrase
* @returns {Promise<Boolean>}
*/
Key.prototype.encrypt = async function(passphrase) {
if (!this.isPrivate()) {
@ -397,7 +398,7 @@ Key.prototype.encrypt = async function(passphrase) {
/**
* Decrypts all secret key and subkey packets
* @param {String} passphrase
* @return {Promise<Boolean>} true if all key and subkey packets decrypted successfully
* @returns {Promise<Boolean>} true if all key and subkey packets decrypted successfully
*/
Key.prototype.decrypt = async function(passphrase) {
if (!this.isPrivate()) {
@ -413,7 +414,7 @@ Key.prototype.decrypt = async function(passphrase) {
* Decrypts specific key packets by key ID
* @param {Array<module:type/keyid>} keyIds
* @param {String} passphrase
* @return {Boolean} true if all key packets decrypted successfully
* @returns {Boolean} true if all key packets decrypted successfully
*/
Key.prototype.decryptKeyPacket = function(keyIds, passphrase) {
if (this.isPrivate()) {
@ -439,7 +440,7 @@ Key.prototype.decryptKeyPacket = function(keyIds, passphrase) {
* Verify primary key. Checks for revocation signatures, expiration time
* and valid self signature
* @param {Date} date (optional) use the given date for verification instead of the current time
* @return {module:enums.keyStatus} The status of the primary key
* @returns {Promise{module:enums.keyStatus}} The status of the primary key
*/
Key.prototype.verifyPrimaryKey = async function(date=new Date()) {
// TODO clarify OpenPGP's behavior given an expired revocation signature
@ -481,7 +482,7 @@ Key.prototype.verifyPrimaryKey = async function(date=new Date()) {
/**
* Returns the expiration time of the primary key or null if key does not expire
* @return {Date|null}
* @returns {Date|null}
*/
Key.prototype.getExpirationTime = function() {
if (this.primaryKey.version === 3) {
@ -516,7 +517,7 @@ function getExpirationTime(keyPacket, selfCertificate, defaultValue=null) {
*
* NOTE: call verifyPrimaryUser before calling this function.
* @param {Date} date use the given date for verification instead of the current time
* @return {{user: Array<module:packet/User>, selfCertificate: Array<module:packet/signature>}|null} The primary user and the self signature
* @returns {{user: Array<module:packet/User>, selfCertificate: Array<module:packet/signature>}|null} The primary user and the self signature
*/
Key.prototype.getPrimaryUser = function(date=new Date()) {
let primaryUsers = [];
@ -649,7 +650,7 @@ Key.prototype.revoke = function() {
/**
* Signs primary user of key
* @param {Array<module:key~Key>} privateKey decrypted private keys for signing
* @return {module:key~Key} new public key with new certificate signature
* @returns {Promise<module:key~Key>} new public key with new certificate signature
*/
Key.prototype.signPrimaryUser = async function(privateKeys) {
await this.verifyPrimaryUser();
@ -666,7 +667,7 @@ Key.prototype.signPrimaryUser = async function(privateKeys) {
/**
* Signs all users of key
* @param {Array<module:key~Key>} privateKeys decrypted private keys for signing
* @return {module:key~Key} new public key with new certificate signature
* @returns {Promise<module:key~Key>} new public key with new certificate signature
*/
Key.prototype.signAllUsers = async function(privateKeys) {
const that = this;
@ -682,7 +683,7 @@ Key.prototype.signAllUsers = async function(privateKeys) {
* - if no arguments are given, verifies the self certificates;
* - otherwise, verifies all certificates signed with given keys.
* @param {Array<module:key~Key>} keys array of keys to verify certificate signatures
* @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
* @returns {Promise<Array<({keyid: module:type/keyid, valid: Boolean})>>} list of signer's keyid and validity of signature
*/
Key.prototype.verifyPrimaryUser = async function(keys) {
const { primaryKey } = this;
@ -732,7 +733,7 @@ Key.prototype.verifyPrimaryUser = async function(keys) {
* - if no arguments are given, verifies the self certificates;
* - otherwise, verifies all certificates signed with given keys.
* @param {Array<module:key~Key>} keys array of keys to verify certificate signatures
* @return {Array<({userid: String, keyid: module:type/keyid, valid: Boolean})>} list of userid, signer's keyid and validity of signature
* @returns {Promise<Array<({userid: String, keyid: module:type/keyid, valid: Boolean})>>} list of userid, signer's keyid and validity of signature
*/
Key.prototype.verifyAllUsers = async function(keys) {
const results = [];
@ -768,7 +769,7 @@ function User(userPacket) {
/**
* Transforms structured user data to packetlist
* @return {module:packet/packetlist}
* @returns {module:packet/packetlist}
*/
User.prototype.toPacketlist = function() {
const packetlist = new packet.List();
@ -785,7 +786,7 @@ User.prototype.toPacketlist = function() {
* @param {module:packet/signature} certificate The certificate to verify
* @param {module:packet/public_subkey|module:packet/public_key|
* module:packet/secret_subkey|module:packet/secret_key} key, optional The key to verify the signature
* @return {Boolean} True if the certificate is revoked
* @returns {Promise<Boolean>} True if the certificate is revoked
*/
User.prototype.isRevoked = async function(primaryKey, certificate, key) {
certificate.revoked = null;
@ -807,7 +808,7 @@ User.prototype.isRevoked = async function(primaryKey, certificate, key) {
* Signs user
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {Array<module:key~Key>} privateKeys decrypted private keys for signing
* @return {module:key~Key} new user with new certificate signatures
* @returns {Promise<module:key~Key>} new user with new certificate signatures
*/
User.prototype.sign = async function(primaryKey, privateKeys) {
const dataToSign = { userid: this.userId || this.userAttribute, key: primaryKey };
@ -848,7 +849,7 @@ User.prototype.sign = async function(primaryKey, privateKeys) {
* @param {module:packet/signature} certificate A certificate of this user
* @param {Array<module:key~Key>} keys array of keys to verify certificate signatures
* @param {Date} date use the given date for verification instead of the current time
* @return {module:enums.keyStatus} status of the certificate
* @returns {Promise<module:enums.keyStatus>} status of the certificate
*/
User.prototype.verifyCertificate = async function(primaryKey, certificate, keys, date=new Date()) {
const that = this;
@ -876,7 +877,7 @@ User.prototype.verifyCertificate = async function(primaryKey, certificate, keys,
* Verifies all user certificates
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {Array<module:key~Key>} keys array of keys to verify certificate signatures
* @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
* @returns {Promise<Array<({keyid: module:type/keyid, valid: Boolean})>>} list of signer's keyid and validity of signature
*/
User.prototype.verifyAllCertifications = async function(primaryKey, keys) {
const that = this;
@ -894,7 +895,7 @@ User.prototype.verifyAllCertifications = async function(primaryKey, keys) {
* Verify User. Checks for existence of self signatures, revocation signatures
* and validity of self signature
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @return {module:enums.keyStatus} status of user
* @returns {Promise<module:enums.keyStatus>} status of user
*/
User.prototype.verify = async function(primaryKey) {
if (!this.selfCertifications) {
@ -922,7 +923,7 @@ User.prototype.verify = async function(primaryKey) {
/**
* Update user with new components from specified user
* @param {module:key~User} user source user to merge
* @param {module:packet/signature} primaryKey primary key used for validation
* @param {Promise<module:packet/signature>} primaryKey primary key used for validation
*/
User.prototype.update = async function(user, primaryKey) {
const dataToVerify = { userid: this.userId || this.userAttribute, key: primaryKey };
@ -951,7 +952,7 @@ function SubKey(subKeyPacket) {
/**
* Transforms structured subkey data to packetlist
* @return {module:packet/packetlist}
* @returns {module:packet/packetlist}
*/
SubKey.prototype.toPacketlist = function() {
const packetlist = new packet.List();
@ -967,7 +968,7 @@ SubKey.prototype.toPacketlist = function() {
* Returns true if the subkey can be used for encryption
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {Date} date use the given date for verification instead of the current time
* @return {Boolean}
* @returns {Promise<Boolean>}
*/
SubKey.prototype.isValidEncryptionKey = async function(primaryKey, date=new Date()) {
if (await this.verify(primaryKey, date) !== enums.keyStatus.valid) {
@ -985,7 +986,7 @@ SubKey.prototype.isValidEncryptionKey = async function(primaryKey, date=new Date
* Returns true if the subkey can be used for signing of data
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {Date} date use the given date for verification instead of the current time
* @return {Boolean}
* @returns {Promise<Boolean>}
*/
SubKey.prototype.isValidSigningKey = async function(primaryKey, date=new Date()) {
if (await this.verify(primaryKey, date) !== enums.keyStatus.valid) {
@ -1004,7 +1005,7 @@ SubKey.prototype.isValidSigningKey = async function(primaryKey, date=new Date())
* and valid binding signature
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {Date} date use the given date for verification instead of the current time
* @return {module:enums.keyStatus} The status of the subkey
* @returns {Promise<module:enums.keyStatus>} The status of the subkey
*/
SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
const that = this;
@ -1051,7 +1052,7 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
/**
* Returns the expiration time of the subkey or null if key does not expire
* @return {Date|null}
* @returns {Date|null}
*/
SubKey.prototype.getExpirationTime = function() {
let highest;
@ -1070,7 +1071,7 @@ SubKey.prototype.getExpirationTime = function() {
/**
* Update subkey with new components from specified subkey
* @param {module:key~SubKey} subKey source subkey to merge
* @param {module:packet/signature} primaryKey primary key used for validation
* @param {Promise<module:packet/signature>} primaryKey primary key used for validation
*/
SubKey.prototype.update = async function(subKey, primaryKey) {
if (await subKey.verify(primaryKey) === enums.keyStatus.invalid) {
@ -1112,7 +1113,7 @@ SubKey.prototype.update = async function(subKey, primaryKey) {
/**
* Reads an unarmored OpenPGP key list and returns one or multiple key objects
* @param {Uint8Array} data to be parsed
* @return {{keys: Array<module:key~Key>, err: (Array<Error>|null)}} result object with key and error arrays
* @returns {{keys: Array<module:key~Key>, err: (Array<Error>|null)}} result object with key and error arrays
* @static
*/
export function read(data) {
@ -1145,7 +1146,7 @@ export function read(data) {
/**
* Reads an OpenPGP armored text and returns one or multiple key objects
* @param {String} armoredText text to be parsed
* @return {{keys: Array<module:key~Key>, err: (Array<Error>|null)}} result object with key and error arrays
* @returns {{keys: Array<module:key~Key>, err: (Array<Error>|null)}} result object with key and error arrays
* @static
*/
export function readArmored(armoredText) {
@ -1173,7 +1174,7 @@ export function readArmored(armoredText) {
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key
* @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked
* @param {Number} [options.keyExpirationTime=0] The number of seconds after the key creation time that the key expires
* @return {module:key~Key}
* @returns {module:key~Key}
* @static
*/
export function generate(options) {
@ -1248,7 +1249,7 @@ export function generate(options) {
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key
* @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked
* @param {Number} [options.keyExpirationTime=0] The number of seconds after the key creation time that the key expires
* @return {module:key~Key}
* @returns {Promise<module:key~Key>}
* @static
*/
export async function reformat(options) {
@ -1382,7 +1383,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
/**
* Returns the preferred signature hash algorithm of a key
* @param {object} key
* @return {String}
* @returns {String}
*/
export function getPreferredHashAlgo(key) {
let hash_algo = config.prefer_hash_algorithm;
@ -1416,7 +1417,7 @@ export function getPreferredHashAlgo(key) {
/**
* Returns the preferred symmetric algorithm for a set of keys
* @param {Array<module:key~Key>} keys Set of keys
* @return {enums.symmetric} Preferred symmetric algorithm
* @returns {enums.symmetric} Preferred symmetric algorithm
*/
export function getPreferredSymAlgo(keys) {
const prioMap = {};

View File

@ -55,7 +55,7 @@ export function Message(packetlist) {
/**
* Returns the key IDs of the keys to which the session key is encrypted
* @return {Array<module:type/keyid>} array of keyid objects
* @returns {Array<module:type/keyid>} array of keyid objects
*/
Message.prototype.getEncryptionKeyIds = function() {
const keyIds = [];
@ -68,7 +68,7 @@ Message.prototype.getEncryptionKeyIds = function() {
/**
* Returns the key IDs of the keys that signed the message
* @return {Array<module:type/keyid>} array of keyid objects
* @returns {Array<module:type/keyid>} array of keyid objects
*/
Message.prototype.getSigningKeyIds = function() {
const keyIds = [];
@ -93,7 +93,7 @@ Message.prototype.getSigningKeyIds = function() {
* @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
* @returns {Promise<Message>} new message with decrypted content
*/
Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys) {
const keyObjs = sessionKeys || await this.decryptSessionKeys(privateKeys, passwords);
@ -105,7 +105,7 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys)
);
if (symEncryptedPacketlist.length === 0) {
return;
return this;
}
const symEncryptedPacket = symEncryptedPacketlist[0];
@ -138,74 +138,73 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys)
* 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
* @returns {Promise{Array<{ data:Uint8Array, algorithm:String }>}} array of object with potential sessionKey, algorithm pairs
*/
Message.prototype.decryptSessionKeys = function(privateKeys, passwords) {
Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
let keyPackets = [];
return Promise.resolve().then(async () => {
if (passwords) {
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
if (!symESKeyPacketlist) {
throw new Error('No symmetrically encrypted session key packet found.');
}
await Promise.all(symESKeyPacketlist.map(async function(packet) {
await Promise.all(passwords.map(async function(password) {
try {
await packet.decrypt(password);
keyPackets.push(packet);
} catch (err) {}
}));
}));
} else if (privateKeys) {
const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey);
if (!pkESKeyPacketlist) {
throw new Error('No public key encrypted session key packet found.');
}
await Promise.all(pkESKeyPacketlist.map(async function(packet) {
const privateKeyPackets = privateKeys.reduce(function(acc, privateKey) {
return acc.concat(privateKey.getKeyPackets(packet.publicKeyId));
}, []);
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
if (!privateKeyPacket) {
return;
}
if (!privateKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
try {
await packet.decrypt(privateKeyPacket);
keyPackets.push(packet);
} catch (err) {}
}));
if (passwords) {
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
if (!symESKeyPacketlist) {
throw new Error('No symmetrically encrypted session key packet found.');
}
await Promise.all(symESKeyPacketlist.map(async function(packet) {
await Promise.all(passwords.map(async function(password) {
try {
await packet.decrypt(password);
keyPackets.push(packet);
} catch (err) {}
}));
} else {
throw new Error('No key or password specified.');
}
}).then(() => {
if (keyPackets.length) {
// Return only unique session keys
if (keyPackets.length > 1) {
const seen = {};
keyPackets = keyPackets.filter(function(item) {
const k = item.sessionKeyAlgorithm + util.Uint8Array_to_str(item.sessionKey);
if (seen.hasOwnProperty(k)) {
return false;
}
seen[k] = true;
return true;
});
}
}));
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
} else if (privateKeys) {
const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey);
if (!pkESKeyPacketlist) {
throw new Error('No public key encrypted session key packet found.');
}
throw new Error('Session key decryption failed.');
});
await Promise.all(pkESKeyPacketlist.map(async function(packet) {
const privateKeyPackets = privateKeys.reduce(function(acc, privateKey) {
return acc.concat(privateKey.getKeyPackets(packet.publicKeyId));
}, []);
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
if (!privateKeyPacket) {
return;
}
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.');
}
if (keyPackets.length) {
// Return only unique session keys
if (keyPackets.length > 1) {
const seen = {};
keyPackets = keyPackets.filter(function(item) {
const k = item.sessionKeyAlgorithm + util.Uint8Array_to_str(item.sessionKey);
if (seen.hasOwnProperty(k)) {
return false;
}
seen[k] = true;
return true;
});
}
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
}
throw new Error('Session key decryption failed.');
};
/**
* Get literal data that is the body of the message
* @return {(Uint8Array|null)} literal body of the message as Uint8Array
* @returns {(Uint8Array|null)} literal body of the message as Uint8Array
*/
Message.prototype.getLiteralData = function() {
const literal = this.packets.findPacket(enums.packet.literal);
@ -214,7 +213,7 @@ Message.prototype.getLiteralData = function() {
/**
* Get filename from literal data packet
* @return {(String|null)} filename of literal data packet as string
* @returns {(String|null)} filename of literal data packet as string
*/
Message.prototype.getFilename = function() {
const literal = this.packets.findPacket(enums.packet.literal);
@ -223,7 +222,7 @@ Message.prototype.getFilename = function() {
/**
* Get literal data as text
* @return {(String|null)} literal body of the message interpreted as text
* @returns {(String|null)} literal body of the message interpreted as text
*/
Message.prototype.getText = function() {
const literal = this.packets.findPacket(enums.packet.literal);
@ -240,54 +239,52 @@ Message.prototype.getText = function() {
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String }
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
* @param {Date} date (optional) override the creation date of the literal package
* @return {Message} new message with encrypted content
* @returns {Promise<Message>} new message with encrypted content
*/
Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard=false, date=new Date()) {
Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard=false, date=new Date()) {
let symAlgo;
let msg;
let symEncryptedPacket;
return Promise.resolve().then(async () => {
if (sessionKey) {
if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) {
throw new Error('Invalid session key for encryption.');
}
symAlgo = sessionKey.algorithm;
sessionKey = sessionKey.data;
} else if (keys && keys.length) {
symAlgo = enums.read(enums.symmetric, getPreferredSymAlgo(keys));
} else if (passwords && passwords.length) {
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
} else {
throw new Error('No keys, passwords, or session key provided.');
if (sessionKey) {
if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) {
throw new Error('Invalid session key for encryption.');
}
symAlgo = sessionKey.algorithm;
sessionKey = sessionKey.data;
} else if (keys && keys.length) {
symAlgo = enums.read(enums.symmetric, getPreferredSymAlgo(keys));
} else if (passwords && passwords.length) {
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
} else {
throw new Error('No keys, passwords, or session key provided.');
}
if (!sessionKey) {
sessionKey = await crypto.generateSessionKey(symAlgo);
if (!sessionKey) {
sessionKey = await crypto.generateSessionKey(symAlgo);
}
const msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard, date);
if (config.aead_protect) {
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
} else if (config.integrity_protect) {
symEncryptedPacket = new packet.SymEncryptedIntegrityProtected();
} else {
symEncryptedPacket = new packet.SymmetricallyEncrypted();
}
symEncryptedPacket.packets = this.packets;
await symEncryptedPacket.encrypt(symAlgo, sessionKey);
msg.packets.push(symEncryptedPacket);
symEncryptedPacket.packets = new packet.List(); // remove packets after encryption
return {
message: msg,
sessionKey: {
data: sessionKey,
algorithm: symAlgo
}
msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard, date);
if (config.aead_protect) {
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
} else if (config.integrity_protect) {
symEncryptedPacket = new packet.SymEncryptedIntegrityProtected();
} else {
symEncryptedPacket = new packet.SymmetricallyEncrypted();
}
symEncryptedPacket.packets = this.packets;
return symEncryptedPacket.encrypt(symAlgo, sessionKey);
}).then(() => {
msg.packets.push(symEncryptedPacket);
symEncryptedPacket.packets = new packet.List(); // remove packets after encryption
return {
message: msg,
sessionKey: {
data: sessionKey,
algorithm: symAlgo
}
};
});
};
};
/**
@ -298,64 +295,64 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard=false
* @param {Array<String>} passwords (optional) for message encryption
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
* @param {Date} date (optional) override the creation date signature
* @return {Message} new message with encrypted content
* @returns {Promise<Message>} new message with encrypted content
*/
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false, date=new Date()) {
export async function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false, date=new Date()) {
const packetlist = new packet.List();
return Promise.resolve().then(async () => {
if (publicKeys) {
const results = await Promise.all(publicKeys.map(async function(key) {
await key.verifyPrimaryUser();
const encryptionKeyPacket = key.getEncryptionKeyPacket(undefined, date);
if (!encryptionKeyPacket) {
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
if (publicKeys) {
const results = await Promise.all(publicKeys.map(async function(key) {
await key.verifyPrimaryUser();
const encryptionKeyPacket = key.getEncryptionKeyPacket(undefined, date);
if (!encryptionKeyPacket) {
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
}
const pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey();
pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId();
pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm;
pkESKeyPacket.sessionKey = sessionKey;
pkESKeyPacket.sessionKeyAlgorithm = symAlgo;
await pkESKeyPacket.encrypt(encryptionKeyPacket);
delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption
return pkESKeyPacket;
}));
packetlist.concat(results);
}
if (passwords) {
const testDecrypt = async function(keyPacket, password) {
try {
await keyPacket.decrypt(password);
return 1;
} catch (e) {
return 0;
}
};
const sum = (accumulator, currentValue) => accumulator + currentValue;
const encryptPassword = async function(sessionKey, symAlgo, password) {
const symEncryptedSessionKeyPacket = new packet.SymEncryptedSessionKey();
symEncryptedSessionKeyPacket.sessionKey = sessionKey;
symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo;
await symEncryptedSessionKeyPacket.encrypt(password);
if (config.password_collision_check) {
const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd)));
if (results.reduce(sum) !== 1) {
return encryptPassword(sessionKey, symAlgo, password);
}
const pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey();
pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId();
pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm;
pkESKeyPacket.sessionKey = sessionKey;
pkESKeyPacket.sessionKeyAlgorithm = symAlgo;
await pkESKeyPacket.encrypt(encryptionKeyPacket);
delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption
return pkESKeyPacket;
}));
packetlist.concat(results);
}
}
if (passwords) {
const testDecrypt = async function(keyPacket, password) {
try {
await keyPacket.decrypt(password);
return 1;
} catch (e) {
return 0;
}
};
delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption
return symEncryptedSessionKeyPacket;
};
const sum = (accumulator, currentValue) => accumulator + currentValue;
const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, pwd)));
packetlist.concat(results);
}
const encryptPassword = async function(sessionKey, symAlgo, password) {
const symEncryptedSessionKeyPacket = new packet.SymEncryptedSessionKey();
symEncryptedSessionKeyPacket.sessionKey = sessionKey;
symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo;
await symEncryptedSessionKeyPacket.encrypt(password);
if (config.password_collision_check) {
const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd)));
if (results.reduce(sum) !== 1) {
return encryptPassword(sessionKey, symAlgo, password);
}
}
delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption
return symEncryptedSessionKeyPacket;
};
const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, pwd)));
packetlist.concat(results);
}
}).then(() => new Message(packetlist));
return new Message(packetlist);
}
/**
@ -363,7 +360,7 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wi
* @param {Array<module:key~Key>} privateKeys private keys with decrypted secret key data for signing
* @param {Signature} signature (optional) any existing detached signature to add to the message
* @param {Date} date} (optional) override the creation time of the signature
* @return {module:message~Message} new message with signed content
* @returns {Promise<Message>} new message with signed content
*/
Message.prototype.sign = async function(privateKeys=[], signature=null, date=new Date()) {
const packetlist = new packet.List();
@ -427,7 +424,7 @@ Message.prototype.sign = async function(privateKeys=[], signature=null, date=new
/**
* Compresses the message (the literal and -if signed- signature data packets of the message)
* @param {module:enums.compression} compression compression algorithm to be used
* @return {module:message~Message} new message with compressed content
* @returns {module:message~Message} new message with compressed content
*/
Message.prototype.compress = function(compression) {
if (compression === enums.compression.uncompressed) {
@ -446,10 +443,10 @@ Message.prototype.compress = function(compression) {
/**
* Create a detached signature for the message (the literal data packet of the message)
* @param {Array<module:key~Key>} privateKeys private keys with decrypted secret key data for signing
* @param {Signature} signature (optional) any existing detached signature
* @param {Date} date (optional) override the creation time of the signature
* @return {module:signature~Signature} new detached signature of message content
* @param {Array<module:key~Key>} privateKeys private keys with decrypted secret key data for signing
* @param {Signature} signature (optional) any existing detached signature
* @param {Date} date (optional) override the creation time of the signature
* @returns {Promise<module:signature~Signature>} new detached signature of message content
*/
Message.prototype.signDetached = async function(privateKeys=[], signature=null, date=new Date()) {
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
@ -461,11 +458,11 @@ Message.prototype.signDetached = async function(privateKeys=[], signature=null,
/**
* Create signature packets for the message
* @param {module:packet/literal} literalDataPacket the literal data packet to sign
* @param {Array<module:key~Key>} privateKeys private keys with decrypted secret key data for signing
* @param {Signature} signature (optional) any existing detached signature to append
* @param {Date} date (optional) override the creationtime of the signature
* @return {module:packet/packetlist} list of signature packets
* @param {module:packet/literal} literalDataPacket the literal data packet to sign
* @param {Array<module:key~Key>} privateKeys private keys with decrypted secret key data for signing
* @param {Signature} signature (optional) any existing detached signature to append
* @param {Date} date (optional) override the creationtime of the signature
* @returns {Promise<module:packet/packetlist>} list of signature packets
*/
export async function createSignaturePackets(literalDataPacket, privateKeys, signature=null, date=new Date()) {
const packetlist = new packet.List();
@ -507,7 +504,7 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig
* Verify message signatures
* @param {Array<module:key~Key>} keys array of keys to verify signatures
* @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time
* @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
* @returns {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
*/
Message.prototype.verify = function(keys, date=new Date()) {
const msg = this.unwrapCompressed();
@ -524,7 +521,7 @@ Message.prototype.verify = function(keys, date=new Date()) {
* @param {Array<module:key~Key>} keys array of keys to verify signatures
* @param {Signature} signature
* @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time
* @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
* @returns {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
*/
Message.prototype.verifyDetached = function(signature, keys, date=new Date()) {
const msg = this.unwrapCompressed();
@ -542,7 +539,7 @@ Message.prototype.verifyDetached = function(signature, keys, date=new Date()) {
* @param {Array<module:packet/literal>} literalDataList array of literal data packets
* @param {Array<module:key~Key>} keys array of keys to verify signatures
* @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time
* @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
* @returns {Promise{Array<({keyid: module:type/keyid, valid: Boolean})>}} list of signer's keyid and validity of signature
*/
export async function createVerificationObjects(signatureList, literalDataList, keys, date=new Date()) {
return Promise.all(signatureList.map(async function(signature) {
@ -572,7 +569,7 @@ export async function createVerificationObjects(signatureList, literalDataList,
/**
* Unwrap compressed message
* @return {module:message~Message} message Content of compressed message
* @returns {module:message~Message} message Content of compressed message
*/
Message.prototype.unwrapCompressed = function() {
const compressed = this.packets.filterByTag(enums.packet.compressed);
@ -592,7 +589,7 @@ Message.prototype.appendSignature = function(detachedSignature) {
/**
* Returns ASCII armored text of message
* @return {String} ASCII armor
* @returns {String} ASCII armor
*/
Message.prototype.armor = function() {
return armor.encode(enums.armor.message, this.packets.write());
@ -601,7 +598,7 @@ Message.prototype.armor = function() {
/**
* reads an OpenPGP armored message and returns a message object
* @param {String} armoredText text to be parsed
* @return {module:message~Message} new message object
* @returns {module:message~Message} new message object
* @static
*/
export function readArmored(armoredText) {
@ -614,7 +611,7 @@ export function readArmored(armoredText) {
/**
* reads an OpenPGP message as byte array and returns a message object
* @param {Uint8Array} input binary message
* @return {Message} new message object
* @returns {Message} new message object
* @static
*/
export function read(input) {
@ -628,7 +625,7 @@ export function read(input) {
* @param {String} text
* @param {String} filename (optional)
* @param {Date} date (optional)
* @return {module:message~Message} new message object
* @returns {module:message~Message} new message object
* @static
*/
export function fromText(text, filename, date=new Date()) {
@ -648,7 +645,7 @@ export function fromText(text, filename, date=new Date()) {
* @param {Uint8Array} bytes
* @param {String} filename (optional)
* @param {Date} date (optional)
* @return {module:message~Message} new message object
* @returns {module:message~Message} new message object
* @static
*/
export function fromBinary(bytes, filename, date=new Date()) {

View File

@ -68,7 +68,7 @@ export function initWorker({ path='openpgp.worker.js', n = 1, workers = [] } = {
/**
* Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker()
* @return {module:worker/async_proxy~AsyncProxy|null} the async proxy or null if not initialized
* @returns {module:worker/async_proxy~AsyncProxy|null} the async proxy or null if not initialized
*/
export function getWorker() {
return asyncProxy;
@ -97,7 +97,7 @@ export function destroyWorker() {
* @param {String} curve (optional) elliptic curve for ECC keys: curve25519, p256, p384, p521, or secp256k1
* @param {Boolean} unlocked (optional) If the returned secret part of the generated key is unlocked
* @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
* @return {Promise<Object>} The generated key object in the form:
* @returns {Promise<Object>} The generated key object in the form:
* { key:Key, privateKeyArmored:String, publicKeyArmored:String }
* @static
*/
@ -134,7 +134,7 @@ export function generateKey({
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
* @param {Boolean} unlocked (optional) If the returned secret part of the generated key is unlocked
* @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
* @return {Promise<Object>} The generated key object in the form:
* @returns {Promise<Object>} The generated key object in the form:
* { key:Key, privateKeyArmored:String, publicKeyArmored:String }
* @static
*/
@ -164,7 +164,7 @@ export function reformatKey({
* Unlock a private key with your passphrase.
* @param {Key} privateKey the private key that is to be decrypted
* @param {String} passphrase the user's passphrase chosen during key generation
* @return {Key} the unlocked private key
* @returns {Promise<Object>} the unlocked key object in the form: { key:Key }
*/
export function decryptKey({ privateKey, passphrase }) {
if (asyncProxy) { // use web worker if available
@ -184,7 +184,7 @@ export function decryptKey({ privateKey, passphrase }) {
* Lock a private key with your passphrase.
* @param {Key} privateKey the private key that is to be decrypted
* @param {String} passphrase the user's passphrase chosen during key generation
* @return {Key} the locked private key
* @returns {Promise<Object>} the locked key object in the form: { key:Key }
*/
export function encryptKey({ privateKey, passphrase }) {
if (asyncProxy) { // use web worker if available
@ -224,7 +224,7 @@ export function encryptKey({ privateKey, passphrase }) {
* @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
* @param {Date} date (optional) override the creation date of the message and the message signature
* @return {Promise<Object>} encrypted (and optionally signed message) in the form:
* @returns {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}
* @static
@ -276,7 +276,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey,
* @param {String} format (optional) return data format either as 'utf8' or 'binary'
* @param {Signature} signature (optional) detached signature for verification
* @param {Date} date (optional) use the given date for verification instead of the current time
* @return {Promise<Object>} decrypted and verified message in the form:
* @returns {Promise<Object>} decrypted and verified message in the form:
* { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] }
* @static
*/
@ -315,7 +315,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
* @param {Boolean} armor (optional) if the return value should be ascii armored or the message object
* @param {Boolean} detached (optional) if the return value should contain a detached signature
* @param {Date} date (optional) override the creation date signature
* @return {Promise<Object>} signed cleartext in the form:
* @returns {Promise<Object>} signed cleartext 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}
* @static
@ -357,7 +357,7 @@ export function sign({
* @param {CleartextMessage} message cleartext message object with signatures
* @param {Signature} signature (optional) detached signature for verification
* @param {Date} date (optional) use the given date for verification instead of the current time
* @return {Promise<Object>} cleartext with status of verified signatures in the form of:
* @returns {Promise<Object>} cleartext with status of verified signatures in the form of:
* { data:String, signatures: [{ keyid:String, valid:Boolean }] }
* @static
*/
@ -393,7 +393,7 @@ export function verify({ message, publicKeys, signature=null, date=new Date() })
* @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} wildcard (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
* @returns {Promise<Message>} the encrypted session key packets contained in a message object
* @static
*/
export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wildcard=false }) {
@ -416,7 +416,7 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wild
* @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:
* @returns {Promise<Object|undefined>} Array of decrypted session key, algorithm pairs in form:
* { data:Uint8Array, algorithm:String }
* or 'undefined' if no key packets found
* @static
@ -505,7 +505,7 @@ function formatUserIds(userIds) {
/**
* Normalize parameter to an array if it is not undefined.
* @param {Object} param the parameter to be normalized
* @return {Array<Object>|undefined} the resulting array or undefined
* @returns {Array<Object>|undefined} the resulting array or undefined
*/
function toArray(param) {
if (param && !util.isArray(param)) {
@ -519,7 +519,7 @@ function toArray(param) {
* @param {String|Uint8Array} data the payload for the message
* @param {String} filename the literal data packet's filename
* @param {Date} date the creation date of the package
* @return {Message} a message object
* @returns {Message} a message object
*/
function createMessage(data, filename, date=new Date()) {
let msg;
@ -537,7 +537,7 @@ function createMessage(data, filename, date=new Date()) {
* Parse the message given a certain format.
* @param {Message} message the message object to be parse
* @param {String} format the output format e.g. 'utf8' or 'binary'
* @return {Object} the parse data in the respective format
* @returns {Object} the parse data in the respective format
*/
function parseMessage(message, format) {
if (format === 'binary') {
@ -572,7 +572,7 @@ function onError(message, error) {
/**
* Check for AES-GCM support and configuration by the user. Only browsers that
* implement the current WebCrypto specification support native AES-GCM.
* @return {Boolean} If authenticated encryption should be used
* @returns {Boolean} If authenticated encryption should be used
*/
function nativeAEAD() {
return util.getWebCrypto() && config.aead_protect;

View File

@ -91,7 +91,7 @@ Packetlist.prototype.push = function (packet) {
/**
* Remove a packet from the list and return it.
* @return {Object} The packet that was removed
* @returns {Object} The packet that was removed
*/
Packetlist.prototype.pop = function() {
if (this.length === 0) {
@ -164,6 +164,8 @@ Packetlist.prototype.map = function (callback) {
/**
* Executes the callback function once for each element
* until it finds one where callback returns a truthy value
* @param {Function} callback
* @returns {Promise<Boolean>}
*/
Packetlist.prototype.some = async function (callback) {
for (let i = 0; i < this.length; i++) {
@ -178,7 +180,7 @@ Packetlist.prototype.some = async function (callback) {
/**
* Traverses packet tree and returns first matching packet
* @param {module:enums.packet} type The packet type
* @return {module:packet/packet|null}
* @returns {module:packet/packet|null}
*/
Packetlist.prototype.findPacket = function (type) {
const packetlist = this.filterByTag(type);

View File

@ -67,7 +67,7 @@ export default function PublicKeyEncryptedSessionKey() {
* @param {Integer} position Position to start reading from the input string
* @param {Integer} len Length of the packet or the remaining length of
* input at position
* @return {module:packet/public_key_encrypted_session_key} Object representation
* @returns {module:packet/public_key_encrypted_session_key} Object representation
*/
PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
this.version = bytes[0];
@ -88,7 +88,7 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
/**
* Create a string representation of a tag 1 packet
*
* @return {Uint8Array} The Uint8Array representation
* @returns {Uint8Array} The Uint8Array representation
*/
PublicKeyEncryptedSessionKey.prototype.write = function () {
const arr = [new Uint8Array([this.version]), this.publicKeyId.write(), new Uint8Array([enums.write(enums.publicKey, this.publicKeyAlgorithm)])];
@ -100,6 +100,11 @@ PublicKeyEncryptedSessionKey.prototype.write = function () {
return util.concatUint8Array(arr);
};
/**
* Encrypt session key packet
* @param {module:packet/public_key} key Public key
* @returns {Promise<Boolean>}
*/
PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) {
let data = String.fromCharCode(enums.write(enums.symmetric, this.sessionKeyAlgorithm));
@ -117,6 +122,7 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) {
this.encrypted = await crypto.publicKeyEncrypt(
algo, key.params, toEncrypt, key.fingerprint);
return true;
};
/**
@ -125,7 +131,7 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) {
*
* @param {module:packet/secret_key} key
* Private key with secret params unlocked
* @return {String} The unencrypted session key
* @returns {Promise<Boolean>}
*/
PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
@ -150,6 +156,7 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
this.sessionKey = key;
this.sessionKeyAlgorithm = enums.read(enums.symmetric, decoded.charCodeAt(0));
}
return true;
};
/**

View File

@ -151,7 +151,7 @@ SecretKey.prototype.read = function (bytes) {
};
/** Creates an OpenPGP key packet for the given key.
* @return {String} A string of bytes containing the secret key OpenPGP packet
* @returns {String} A string of bytes containing the secret key OpenPGP packet
*/
SecretKey.prototype.write = function () {
const arr = [this.writePublicKey()];
@ -172,11 +172,12 @@ SecretKey.prototype.write = function () {
* and the passphrase is empty or undefined, the key will be set as not encrypted.
* This can be used to remove passphrase protection after calling decrypt().
* @param {String} passphrase
* @returns {Promise<Boolean>}
*/
SecretKey.prototype.encrypt = async function (passphrase) {
if (this.isDecrypted && !passphrase) {
this.encrypted = null;
return;
return false;
} else if (!passphrase) {
throw new Error('The key must be decrypted before removing passphrase protection.');
}
@ -195,6 +196,7 @@ SecretKey.prototype.encrypt = async function (passphrase) {
arr.push(crypto.cfb.normalEncrypt(symmetric, key, cleartext, iv));
this.encrypted = util.concatUint8Array(arr);
return true;
};
function produceEncryptionKey(s2k, passphrase, algorithm) {
@ -209,10 +211,8 @@ function produceEncryptionKey(s2k, passphrase, algorithm) {
* @link module:packet/secret_key.isDecrypted should be
* false otherwise a call to this function is not needed
*
* @param {String} str_passphrase The passphrase for this private key
* as string
* @return {Boolean} True if the passphrase was correct or param already
* decrypted; false if not
* @param {String} passphrase The passphrase for this private key as string
* @returns {Promise<Boolean>}
*/
SecretKey.prototype.decrypt = async function (passphrase) {
if (this.isDecrypted) {
@ -267,6 +267,8 @@ SecretKey.prototype.decrypt = async function (passphrase) {
this.params = this.params.concat(privParams);
this.isDecrypted = true;
this.encrypted = null;
return true;
};
SecretKey.prototype.generate = function (bits, curve) {

View File

@ -211,6 +211,7 @@ Signature.prototype.write = function () {
* Signs provided data. This needs to be done prior to serialization.
* @param {module:packet/secret_key} key private key used to sign the message.
* @param {Object} data Contains packets to be signed.
* @returns {Promise<Boolean>}
*/
Signature.prototype.sign = async function (key, data) {
const signatureType = enums.write(enums.signature, this.signatureType);
@ -247,6 +248,7 @@ Signature.prototype.sign = async function (key, data) {
this.signature = await crypto.signature.sign(
publicKeyAlgorithm, hashAlgorithm, key.params, toHash
);
return true;
};
/**
@ -615,7 +617,7 @@ Signature.prototype.calculateTrailer = function () {
* @param {String|Object} data data which on the signature applies
* @param {module:packet/public_subkey|module:packet/public_key|
* module:packet/secret_subkey|module:packet/secret_key} key the public key to verify the signature
* @return {boolean} True if message is verified, else false.
* @return {Promise<Boolean>} True if message is verified, else false.
*/
Signature.prototype.verify = async function (key, data) {
const signatureType = enums.write(enums.signature, this.signatureType);

View File

@ -64,19 +64,21 @@ SymEncryptedAEADProtected.prototype.write = function () {
* Decrypt the encrypted payload.
* @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128'
* @param {Uint8Array} key The session key used to encrypt the payload
* @return {Promise<undefined>} Nothing is returned
* @return {Promise<Boolean>}
*/
SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key) {
this.packets.read(await crypto.gcm.decrypt(sessionKeyAlgorithm, this.encrypted, key, this.iv));
return true;
};
/**
* Encrypt the packet list payload.
* @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128'
* @param {Uint8Array} key The session key used to encrypt the payload
* @return {Promise<undefined>} Nothing is returned
* @return {Promise<Boolean>}
*/
SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) {
this.iv = await crypto.random.getRandomBytes(IV_LEN); // generate new random IV
this.encrypted = await crypto.gcm.encrypt(sessionKeyAlgorithm, this.packets.write(), key, this.iv);
return true;
};

View File

@ -79,7 +79,7 @@ SymEncryptedIntegrityProtected.prototype.write = function () {
* Encrypt the payload in the packet.
* @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128'
* @param {Uint8Array} key The key of cipher blocksize length to be used
* @return {Promise}
* @return {Promise<Boolean>}
*/
SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) {
const bytes = this.packets.write();
@ -98,13 +98,14 @@ SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlg
this.encrypted = crypto.cfb.encrypt(prefixrandom, sessionKeyAlgorithm, tohash, key, false);
this.encrypted = this.encrypted.subarray(0, prefix.length + tohash.length);
}
return true;
};
/**
* Decrypts the encrypted data contained in the packet.
* @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128'
* @param {Uint8Array} key The key of cipher blocksize length to be used
* @return {Promise}
* @return {Promise<Boolean>}
*/
SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key) {
let decrypted;

View File

@ -102,10 +102,9 @@ SymEncryptedSessionKey.prototype.write = function() {
};
/**
* Decrypts the session key (only for public key encrypted session key
* packets (tag 1)
*
* @return {Uint8Array} The unencrypted session key
* Decrypts the session key
* @param {String} passphrase The passphrase in string form
* @return {Promise<Boolean}
*/
SymEncryptedSessionKey.prototype.decrypt = async function(passphrase) {
const algo = this.sessionKeyEncryptionAlgorithm !== null ?
@ -123,8 +122,14 @@ SymEncryptedSessionKey.prototype.decrypt = async function(passphrase) {
this.sessionKeyAlgorithm = enums.read(enums.symmetric, decrypted[0]);
this.sessionKey = decrypted.subarray(1, decrypted.length);
}
return true;
};
/**
* Encrypts the session key
* @param {String} passphrase The passphrase in string form
* @return {Promise<Boolean}
*/
SymEncryptedSessionKey.prototype.encrypt = async function(passphrase) {
const algo = this.sessionKeyEncryptionAlgorithm !== null ?
this.sessionKeyEncryptionAlgorithm :
@ -146,6 +151,7 @@ SymEncryptedSessionKey.prototype.encrypt = async function(passphrase) {
const private_key = util.concatUint8Array([algo_enum, this.sessionKey]);
this.encrypted = crypto.cfb.normalEncrypt(algo, key, private_key, null);
return true;
};
/**

View File

@ -54,13 +54,11 @@ SymmetricallyEncrypted.prototype.write = function () {
};
/**
* Symmetrically decrypt the packet data
*
* Decrypt the symmetrically-encrypted packet data
* @param {module:enums.symmetric} sessionKeyAlgorithm
* Symmetric key algorithm to use // See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880 9.2}
* @param {String} key
* Key as string with the corresponding length to the
* algorithm
* @param {Uint8Array} key The key of cipher blocksize length to be used
* @returns {Promise<Boolean>}
*/
SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm, key) {
const decrypted = crypto.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted, true);
@ -73,13 +71,20 @@ SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm,
}
this.packets.read(decrypted);
return Promise.resolve();
return true;
};
/**
* Encrypt the symmetrically-encrypted packet data
* @param {module:enums.symmetric} sessionKeyAlgorithm
* Symmetric key algorithm to use // See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880 9.2}
* @param {Uint8Array} key The key of cipher blocksize length to be used
* @returns {Promise<Boolean>}
*/
SymmetricallyEncrypted.prototype.encrypt = async function (algo, key) {
const data = this.packets.write();
this.encrypted = crypto.cfb.encrypt(await crypto.getPrefixRandom(algo), algo, data, key, true);
return Promise.resolve();
return true;
};

View File

@ -22,7 +22,7 @@ import packet from '../packet';
/**
* Message handling
*/
function handleMessage(id) {
function handleMessage(workerId) {
return function(event) {
const msg = event.data;
switch (msg.event) {
@ -38,10 +38,10 @@ function handleMessage(id) {
this.tasks[msg.id].resolve(msg.data);
}
delete this.tasks[msg.id];
this.workers[id].requests--;
this.workers[workerId].requests--;
break;
case 'request-seed':
this.seedRandom(id, msg.amount);
this.seedRandom(workerId, msg.amount);
break;
default:
throw new Error('Unknown Worker Event.');
@ -53,10 +53,9 @@ function handleMessage(id) {
* Initializes a new proxy and loads the web worker
* @constructor
* @param {String} path The path to the worker or 'openpgp.worker.js' by default
* @param {Number} n number of workers to initialize
* @param {Number} n number of workers to initialize if path given
* @param {Object} config config The worker configuration
* @param {Array<Object>} worker alternative to path parameter: web worker initialized with 'openpgp.worker.js'
* @return {Promise}
*/
export default function AsyncProxy({ path='openpgp.worker.js', n = 1, workers = [], config } = {}) {
@ -100,9 +99,9 @@ AsyncProxy.prototype.getID = function() {
* Send message to worker with random data
* @param {Integer} size Number of bytes to send
*/
AsyncProxy.prototype.seedRandom = async function(id, size) {
AsyncProxy.prototype.seedRandom = async function(workerId, size) {
const buf = await crypto.random.getRandomBytes(size);
this.workers[id].postMessage({ event:'seed-random', buf }, util.getTransferables(buf));
this.workers[workerId].postMessage({ event:'seed-random', buf }, util.getTransferables(buf));
};
/**