Add options to select encryption/signing key IDs (#1238)
This commit is contained in:
parent
b6edfe646b
commit
9ae0aae7a2
|
@ -66,29 +66,31 @@ export class CleartextMessage {
|
||||||
* Sign the cleartext message
|
* Sign the cleartext message
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature
|
* @param {Signature} signature (optional) any existing detached signature
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
* @param {Date} date (optional) The creation time of the signature that should be created
|
* @param {Date} date (optional) The creation time of the signature that should be created
|
||||||
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<module:cleartext.CleartextMessage>} new cleartext message with signed content
|
* @returns {Promise<module:cleartext.CleartextMessage>} new cleartext message with signed content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async sign(privateKeys, signature = null, date = new Date(), userIds = []) {
|
async sign(privateKeys, signature = null, signingKeyIds = [], date = new Date(), userIds = []) {
|
||||||
return new CleartextMessage(this.text, await this.signDetached(privateKeys, signature, date, userIds));
|
return new CleartextMessage(this.text, await this.signDetached(privateKeys, signature, signingKeyIds, date, userIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign the cleartext message
|
* Sign the cleartext message
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature
|
* @param {Signature} signature (optional) any existing detached signature
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
* @param {Date} date (optional) The creation time of the signature that should be created
|
* @param {Date} date (optional) The creation time of the signature that should be created
|
||||||
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async signDetached(privateKeys, signature = null, date = new Date(), userIds = []) {
|
async signDetached(privateKeys, signature = null, signingKeyIds = [], date = new Date(), userIds = []) {
|
||||||
const literalDataPacket = new LiteralDataPacket();
|
const literalDataPacket = new LiteralDataPacket();
|
||||||
literalDataPacket.setText(this.text);
|
literalDataPacket.setText(this.text);
|
||||||
|
|
||||||
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds, true));
|
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIds, date, userIds, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -308,13 +308,14 @@ export class Message {
|
||||||
* @param {Array<String>} passwords (optional) password(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, [aeadAlgorithm:String] }
|
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] }
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
* @param {Array<module:type/keyid>} encryptionKeyIds (optional) array of key IDs to use for encryption. Each encryptionKeyIds[i] corresponds to publicKeys[i]
|
||||||
* @param {Date} date (optional) override the creation date of the literal package
|
* @param {Date} date (optional) override the creation date of the literal package
|
||||||
* @param {Array<Object>} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
* @param {Array<Object>} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
||||||
* @param {Boolean} streaming (optional) whether to process data as a stream
|
* @param {Boolean} streaming (optional) whether to process data as a stream
|
||||||
* @returns {Promise<Message>} new message with encrypted content
|
* @returns {Promise<Message>} new message with encrypted content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async encrypt(keys, passwords, sessionKey, wildcard = false, date = new Date(), userIds = [], streaming) {
|
async encrypt(keys, passwords, sessionKey, wildcard = false, encryptionKeyIds = [], date = new Date(), userIds = [], streaming) {
|
||||||
if (sessionKey) {
|
if (sessionKey) {
|
||||||
if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) {
|
if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) {
|
||||||
throw new Error('Invalid session key for encryption.');
|
throw new Error('Invalid session key for encryption.');
|
||||||
|
@ -329,7 +330,7 @@ export class Message {
|
||||||
|
|
||||||
const { data: sessionKeyData, algorithm, aeadAlgorithm } = sessionKey;
|
const { data: sessionKeyData, algorithm, aeadAlgorithm } = sessionKey;
|
||||||
|
|
||||||
const msg = await Message.encryptSessionKey(sessionKeyData, algorithm, aeadAlgorithm, keys, passwords, wildcard, date, userIds);
|
const msg = await Message.encryptSessionKey(sessionKeyData, algorithm, aeadAlgorithm, keys, passwords, wildcard, encryptionKeyIds, date, userIds);
|
||||||
|
|
||||||
let symEncryptedPacket;
|
let symEncryptedPacket;
|
||||||
if (aeadAlgorithm) {
|
if (aeadAlgorithm) {
|
||||||
|
@ -357,17 +358,18 @@ export class Message {
|
||||||
* @param {Array<Key>} publicKeys (optional) public key(s) for message encryption
|
* @param {Array<Key>} publicKeys (optional) public key(s) for message encryption
|
||||||
* @param {Array<String>} passwords (optional) for message encryption
|
* @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 {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
* @param {Array<module:type/keyid>} encryptionKeyIds (optional) array of key IDs to use for encryption. Each encryptionKeyIds[i] corresponds to publicKeys[i]
|
||||||
* @param {Date} date (optional) override the date
|
* @param {Date} date (optional) override the date
|
||||||
* @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
* @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
||||||
* @returns {Promise<Message>} new message with encrypted content
|
* @returns {Promise<Message>} new message with encrypted content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
static async encryptSessionKey(sessionKey, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard = false, date = new Date(), userIds = []) {
|
static async encryptSessionKey(sessionKey, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard = false, encryptionKeyIds = [], date = new Date(), userIds = []) {
|
||||||
const packetlist = new PacketList();
|
const packetlist = new PacketList();
|
||||||
|
|
||||||
if (publicKeys) {
|
if (publicKeys) {
|
||||||
const results = await Promise.all(publicKeys.map(async function(publicKey) {
|
const results = await Promise.all(publicKeys.map(async function(publicKey, i) {
|
||||||
const encryptionKey = await publicKey.getEncryptionKey(undefined, date, userIds);
|
const encryptionKey = await publicKey.getEncryptionKey(encryptionKeyIds[i], date, userIds);
|
||||||
const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket();
|
const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket();
|
||||||
pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKey.getKeyId();
|
pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKey.getKeyId();
|
||||||
pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm;
|
pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm;
|
||||||
|
@ -422,13 +424,14 @@ export class Message {
|
||||||
* Sign the message (the literal data packet of the message)
|
* Sign 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 {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 {Signature} signature (optional) any existing detached signature to add to the message
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
* @param {Date} date (optional) override the creation time of the signature
|
* @param {Date} date (optional) override the creation time of the signature
|
||||||
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @param {Boolean} streaming (optional) whether to process data as a stream
|
* @param {Boolean} streaming (optional) whether to process data as a stream
|
||||||
* @returns {Promise<Message>} new message with signed content
|
* @returns {Promise<Message>} new message with signed content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async sign(privateKeys = [], signature = null, date = new Date(), userIds = [], streaming = false) {
|
async sign(privateKeys = [], signature = null, signingKeyIds = [], date = new Date(), userIds = [], streaming = false) {
|
||||||
const packetlist = new PacketList();
|
const packetlist = new PacketList();
|
||||||
|
|
||||||
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
|
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
|
||||||
|
@ -462,7 +465,8 @@ export class Message {
|
||||||
if (privateKey.isPublic()) {
|
if (privateKey.isPublic()) {
|
||||||
throw new Error('Need private key for signing');
|
throw new Error('Need private key for signing');
|
||||||
}
|
}
|
||||||
const signingKey = await privateKey.getSigningKey(undefined, date, userIds);
|
const signingKeyId = signingKeyIds[privateKeys.length - 1 - i];
|
||||||
|
const signingKey = await privateKey.getSigningKey(signingKeyId, date, userIds);
|
||||||
const onePassSig = new OnePassSignaturePacket();
|
const onePassSig = new OnePassSignaturePacket();
|
||||||
onePassSig.signatureType = signatureType;
|
onePassSig.signatureType = signatureType;
|
||||||
onePassSig.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKey.keyPacket, date, userIds);
|
onePassSig.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKey.keyPacket, date, userIds);
|
||||||
|
@ -477,7 +481,7 @@ export class Message {
|
||||||
});
|
});
|
||||||
|
|
||||||
packetlist.push(literalDataPacket);
|
packetlist.push(literalDataPacket);
|
||||||
packetlist.concat(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds, false, streaming));
|
packetlist.concat(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIds, date, userIds, false, streaming));
|
||||||
|
|
||||||
return new Message(packetlist);
|
return new Message(packetlist);
|
||||||
}
|
}
|
||||||
|
@ -506,18 +510,19 @@ export class Message {
|
||||||
* Create a detached signature for the message (the literal data packet of the message)
|
* 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 {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature
|
* @param {Signature} signature (optional) any existing detached signature
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
* @param {Date} date (optional) override the creation time of the signature
|
* @param {Date} date (optional) override the creation time of the signature
|
||||||
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @param {Boolean} streaming (optional) whether to process data as a stream
|
* @param {Boolean} streaming (optional) whether to process data as a stream
|
||||||
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async signDetached(privateKeys = [], signature = null, date = new Date(), userIds = [], streaming = false) {
|
async signDetached(privateKeys = [], signature = null, signingKeyIds = [], date = new Date(), userIds = [], streaming = false) {
|
||||||
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
|
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
|
||||||
if (!literalDataPacket) {
|
if (!literalDataPacket) {
|
||||||
throw new Error('No literal data packet to sign.');
|
throw new Error('No literal data packet to sign.');
|
||||||
}
|
}
|
||||||
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds, true, streaming));
|
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIds, date, userIds, true, streaming));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -689,6 +694,7 @@ export class Message {
|
||||||
* @param {LiteralDataPacket} literalDataPacket the literal data packet to sign
|
* @param {LiteralDataPacket} literalDataPacket the literal data packet to sign
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @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 {Signature} signature (optional) any existing detached signature to append
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
* @param {Date} date (optional) override the creationtime of the signature
|
* @param {Date} date (optional) override the creationtime of the signature
|
||||||
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @param {Boolean} detached (optional) whether to create detached signature packets
|
* @param {Boolean} detached (optional) whether to create detached signature packets
|
||||||
|
@ -696,7 +702,7 @@ export class Message {
|
||||||
* @returns {Promise<module:PacketList>} list of signature packets
|
* @returns {Promise<module:PacketList>} list of signature packets
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function createSignaturePackets(literalDataPacket, privateKeys, signature = null, date = new Date(), userIds = [], detached = false, streaming = false) {
|
export async function createSignaturePackets(literalDataPacket, privateKeys, signature = null, signingKeyIds = [], date = new Date(), userIds = [], detached = false, streaming = false) {
|
||||||
const packetlist = new PacketList();
|
const packetlist = new PacketList();
|
||||||
|
|
||||||
// If data packet was created from Uint8Array, use binary, otherwise use text
|
// If data packet was created from Uint8Array, use binary, otherwise use text
|
||||||
|
@ -708,7 +714,7 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig
|
||||||
if (privateKey.isPublic()) {
|
if (privateKey.isPublic()) {
|
||||||
throw new Error('Need private key for signing');
|
throw new Error('Need private key for signing');
|
||||||
}
|
}
|
||||||
const signingKey = await privateKey.getSigningKey(undefined, date, userId);
|
const signingKey = await privateKey.getSigningKey(signingKeyIds[i], date, userId);
|
||||||
return createSignaturePacket(literalDataPacket, privateKey, signingKey.keyPacket, { signatureType }, date, userId, detached, streaming);
|
return createSignaturePacket(literalDataPacket, privateKey, signingKey.keyPacket, { signatureType }, date, userId, detached, streaming);
|
||||||
})).then(signatureList => {
|
})).then(signatureList => {
|
||||||
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
|
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
|
||||||
|
|
|
@ -250,6 +250,8 @@ export async function encryptKey({ privateKey, passphrase }) {
|
||||||
* @param {'web'|'ponyfill'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
|
* @param {'web'|'ponyfill'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
|
||||||
* @param {Signature} signature (optional) a detached signature to add to the encrypted message
|
* @param {Signature} signature (optional) a detached signature to add to the encrypted message
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
|
* @param {Array<module:type/keyid>} encryptionKeyIds (optional) array of key IDs to use for encryption. Each encryptionKeyIds[i] corresponds to publicKeys[i]
|
||||||
* @param {Date} date (optional) override the creation date of the message signature
|
* @param {Date} date (optional) override the creation date of the message signature
|
||||||
* @param {Array<Object>} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array<Object>} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @param {Array<Object>} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
* @param {Array<Object>} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
||||||
|
@ -257,7 +259,7 @@ export async function encryptKey({ privateKey, passphrase }) {
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression = config.compression, armor = true, streaming = message && message.fromStream, detached = false, signature = null, wildcard = false, date = new Date(), fromUserIds = [], toUserIds = [] }) {
|
export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression = config.compression, armor = true, streaming = message && message.fromStream, detached = false, signature = null, wildcard = false, signingKeyIds = [], encryptionKeyIds = [], date = new Date(), fromUserIds = [], toUserIds = [] }) {
|
||||||
checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); fromUserIds = toArray(fromUserIds); toUserIds = toArray(toUserIds);
|
checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); fromUserIds = toArray(fromUserIds); toUserIds = toArray(toUserIds);
|
||||||
if (detached) {
|
if (detached) {
|
||||||
throw new Error("detached option has been removed from openpgp.encrypt. Separately call openpgp.sign instead. Don't forget to remove privateKeys option as well.");
|
throw new Error("detached option has been removed from openpgp.encrypt. Separately call openpgp.sign instead. Don't forget to remove privateKeys option as well.");
|
||||||
|
@ -268,10 +270,10 @@ export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKe
|
||||||
privateKeys = [];
|
privateKeys = [];
|
||||||
}
|
}
|
||||||
if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified
|
if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified
|
||||||
message = await message.sign(privateKeys, signature, date, fromUserIds, message.fromStream);
|
message = await message.sign(privateKeys, signature, signingKeyIds, date, fromUserIds, message.fromStream);
|
||||||
}
|
}
|
||||||
message = message.compress(compression);
|
message = message.compress(compression);
|
||||||
message = await message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserIds, streaming);
|
message = await message.encrypt(publicKeys, passwords, sessionKey, wildcard, encryptionKeyIds, date, toUserIds, streaming);
|
||||||
const data = armor ? message.armor() : message.write();
|
const data = armor ? message.armor() : message.write();
|
||||||
return convertStream(data, streaming, armor ? 'utf8' : 'binary');
|
return convertStream(data, streaming, armor ? 'utf8' : 'binary');
|
||||||
}).catch(onError.bind(null, 'Error encrypting message'));
|
}).catch(onError.bind(null, 'Error encrypting message'));
|
||||||
|
@ -340,13 +342,14 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
|
||||||
* @param {Boolean} armor (optional) whether the return values should be ascii armored (true, the default) or binary (false)
|
* @param {Boolean} armor (optional) whether the return values should be ascii armored (true, the default) or binary (false)
|
||||||
* @param {'web'|'ponyfill'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
|
* @param {'web'|'ponyfill'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
|
||||||
* @param {Boolean} detached (optional) if the return value should contain a detached signature
|
* @param {Boolean} detached (optional) if the return value should contain a detached signature
|
||||||
|
* @param {Array<module:type/keyid>} signingKeyIds (optional) array of key IDs to use for signing. Each signingKeyIds[i] corresponds to privateKeys[i]
|
||||||
* @param {Date} date (optional) override the creation date of the signature
|
* @param {Date} date (optional) override the creation date of the signature
|
||||||
* @param {Array<Object>} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
* @param {Array<Object>} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<String|ReadableStream<String>|NodeStream<String>|Uint8Array|ReadableStream<Uint8Array>|NodeStream<Uint8Array>>} (String if `armor` was true, the default; Uint8Array if `armor` was false)
|
* @returns {Promise<String|ReadableStream<String>|NodeStream<String>|Uint8Array|ReadableStream<Uint8Array>|NodeStream<Uint8Array>>} (String if `armor` was true, the default; Uint8Array if `armor` was false)
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function sign({ message, privateKeys, armor = true, streaming = message && message.fromStream, detached = false, date = new Date(), fromUserIds = [] }) {
|
export function sign({ message, privateKeys, armor = true, streaming = message && message.fromStream, detached = false, signingKeyIds = [], date = new Date(), fromUserIds = [] }) {
|
||||||
checkCleartextOrMessage(message);
|
checkCleartextOrMessage(message);
|
||||||
if (message instanceof CleartextMessage && !armor) throw new Error("Can't sign non-armored cleartext message");
|
if (message instanceof CleartextMessage && !armor) throw new Error("Can't sign non-armored cleartext message");
|
||||||
if (message instanceof CleartextMessage && detached) throw new Error("Can't sign detached cleartext message");
|
if (message instanceof CleartextMessage && detached) throw new Error("Can't sign detached cleartext message");
|
||||||
|
@ -355,9 +358,9 @@ export function sign({ message, privateKeys, armor = true, streaming = message &
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
let signature;
|
let signature;
|
||||||
if (detached) {
|
if (detached) {
|
||||||
signature = await message.signDetached(privateKeys, undefined, date, fromUserIds, message.fromStream);
|
signature = await message.signDetached(privateKeys, undefined, signingKeyIds, date, fromUserIds, message.fromStream);
|
||||||
} else {
|
} else {
|
||||||
signature = await message.sign(privateKeys, undefined, date, fromUserIds, message.fromStream);
|
signature = await message.sign(privateKeys, undefined, signingKeyIds, date, fromUserIds, message.fromStream);
|
||||||
}
|
}
|
||||||
signature = armor ? signature.armor() : signature.write();
|
signature = armor ? signature.armor() : signature.write();
|
||||||
if (detached) {
|
if (detached) {
|
||||||
|
@ -448,18 +451,19 @@ export function generateSessionKey({ publicKeys, date = new Date(), toUserIds =
|
||||||
* @param {String|Array<String>} passwords (optional) passwords for the message
|
* @param {String|Array<String>} passwords (optional) passwords for the message
|
||||||
* @param {Boolean} armor (optional) whether the return values should be ascii armored (true, the default) or binary (false)
|
* @param {Boolean} armor (optional) whether the return values should be ascii armored (true, the default) or binary (false)
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
* @param {Array<module:type/keyid>} encryptionKeyIds (optional) array of key IDs to use for encryption. Each encryptionKeyIds[i] corresponds to publicKeys[i]
|
||||||
* @param {Date} date (optional) override the date
|
* @param {Date} date (optional) override the date
|
||||||
* @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
* @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
||||||
* @returns {Promise<String|Uint8Array>} (String if `armor` was true, the default; Uint8Array if `armor` was false)
|
* @returns {Promise<String|Uint8Array>} (String if `armor` was true, the default; Uint8Array if `armor` was false)
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, armor = true, wildcard = false, date = new Date(), toUserIds = [] }) {
|
export function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, armor = true, wildcard = false, encryptionKeyIds = [], date = new Date(), toUserIds = [] }) {
|
||||||
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); toUserIds = toArray(toUserIds);
|
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); toUserIds = toArray(toUserIds);
|
||||||
|
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
|
|
||||||
const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds);
|
const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, encryptionKeyIds, date, toUserIds);
|
||||||
return armor ? message.armor() : message.write();
|
return armor ? message.armor() : message.write();
|
||||||
|
|
||||||
}).catch(onError.bind(null, 'Error encrypting session key'));
|
}).catch(onError.bind(null, 'Error encrypting session key'));
|
||||||
|
|
|
@ -5,6 +5,7 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp
|
||||||
const crypto = require('../../src/crypto');
|
const crypto = require('../../src/crypto');
|
||||||
const random = require('../../src/crypto/random');
|
const random = require('../../src/crypto/random');
|
||||||
const util = require('../../src/util');
|
const util = require('../../src/util');
|
||||||
|
const keyIdType = require('../../src/type/keyid');
|
||||||
|
|
||||||
const spy = require('sinon/lib/sinon/spy');
|
const spy = require('sinon/lib/sinon/spy');
|
||||||
const input = require('./testInputs.js');
|
const input = require('./testInputs.js');
|
||||||
|
@ -544,6 +545,120 @@ mNG2ibD6lftLOtDsVSDY8a6a
|
||||||
-----END PGP PRIVATE KEY BLOCK-----
|
-----END PGP PRIVATE KEY BLOCK-----
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const multipleEncryptionAndSigningSubkeys = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
|
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
|
||||||
|
=PUAJ
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
function withCompression(tests) {
|
function withCompression(tests) {
|
||||||
const compressionTypes = Object.keys(openpgp.enums.compression).map(k => openpgp.enums.compression[k]);
|
const compressionTypes = Object.keys(openpgp.enums.compression).map(k => openpgp.enums.compression[k]);
|
||||||
|
|
||||||
|
@ -2596,6 +2711,90 @@ amnR6g==
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Specific encryption/signing key testing', async function () {
|
||||||
|
const encryptionKeyIds = [
|
||||||
|
keyIdType.fromId("87EAE0977B2185EA"),
|
||||||
|
keyIdType.fromId("F94F9B34AF93FA14"),
|
||||||
|
keyIdType.fromId("08F7D4C7C59545C0")
|
||||||
|
];
|
||||||
|
const signingKeyIds = [
|
||||||
|
keyIdType.fromId("663277AF60400638"),
|
||||||
|
keyIdType.fromId("BBE14491E6EE6366"),
|
||||||
|
keyIdType.fromId("3E0F20F1A71D6DFD")
|
||||||
|
];
|
||||||
|
const getPrimaryKey = async () => openpgp.readArmoredKey(
|
||||||
|
multipleEncryptionAndSigningSubkeys
|
||||||
|
);
|
||||||
|
|
||||||
|
it('Encrypt message with a specific encryption key id', async function () {
|
||||||
|
const primaryKey = await getPrimaryKey();
|
||||||
|
let m;
|
||||||
|
let p;
|
||||||
|
for (let i = 0; i < encryptionKeyIds.length; i++) {
|
||||||
|
m = await openpgp.readArmoredMessage(await openpgp.encrypt({
|
||||||
|
message: openpgp.Message.fromText("Hello World\n"),
|
||||||
|
publicKeys: primaryKey,
|
||||||
|
encryptionKeyIds: [encryptionKeyIds[i]]
|
||||||
|
}));
|
||||||
|
p = m.packets.filterByTag(openpgp.enums.packet.publicKeyEncryptedSessionKey);
|
||||||
|
expect(p.length).equals(1);
|
||||||
|
expect(p[0].publicKeyId.equals(encryptionKeyIds[i])).to.be.true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sign message with a specific signing key id', async function () {
|
||||||
|
const primaryKey = await getPrimaryKey();
|
||||||
|
let s;
|
||||||
|
let p;
|
||||||
|
for (let i = 0; i < signingKeyIds.length; i++) {
|
||||||
|
s = await openpgp.readArmoredSignature(await openpgp.sign({
|
||||||
|
message: openpgp.Message.fromText("Hello World\n"),
|
||||||
|
privateKeys: primaryKey,
|
||||||
|
signingKeyIds: [signingKeyIds[i]],
|
||||||
|
detached: true
|
||||||
|
}));
|
||||||
|
p = s.packets.filterByTag(openpgp.enums.packet.signature);
|
||||||
|
expect(p.length).equals(1);
|
||||||
|
expect(p[0].issuerKeyId.equals(signingKeyIds[i])).to.be.true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Encrypt and sign with specific encryption/signing key ids', async function () {
|
||||||
|
const primaryKey = await getPrimaryKey();
|
||||||
|
const plaintextMessage = openpgp.Message.fromText("Hello World\n");
|
||||||
|
|
||||||
|
const checkEncryptedPackets = (encryptionKeyIds, pKESKList) => {
|
||||||
|
pKESKList.forEach(({ publicKeyId }, i) => {
|
||||||
|
expect(publicKeyId.equals(encryptionKeyIds[i])).to.be.true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const checkSignatures = (signingKeyIds, signatures) => {
|
||||||
|
signatures.forEach(({ keyid }, i) => {
|
||||||
|
expect(keyid.equals(signingKeyIds[i])).to.be.true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const kIds = [encryptionKeyIds[1], encryptionKeyIds[0], encryptionKeyIds[2]];
|
||||||
|
const sIds = [signingKeyIds[2], signingKeyIds[1], signingKeyIds[0]];
|
||||||
|
const message = await openpgp.readArmoredMessage(await openpgp.encrypt({
|
||||||
|
message: plaintextMessage,
|
||||||
|
privateKeys: [primaryKey, primaryKey, primaryKey],
|
||||||
|
publicKeys: [primaryKey, primaryKey, primaryKey],
|
||||||
|
encryptionKeyIds: kIds,
|
||||||
|
signingKeyIds: sIds
|
||||||
|
}));
|
||||||
|
const pKESKList = message.packets.filterByTag(openpgp.enums.packet.publicKeyEncryptedSessionKey);
|
||||||
|
expect(pKESKList.length).equals(3);
|
||||||
|
checkEncryptedPackets(kIds, pKESKList);
|
||||||
|
const { signatures } = await openpgp.decrypt({
|
||||||
|
message,
|
||||||
|
privateKeys: [primaryKey, primaryKey, primaryKey]
|
||||||
|
});
|
||||||
|
expect(signatures.length).equals(3);
|
||||||
|
checkSignatures(sIds, signatures);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user