Add timeparameter to signing and encryption
This commit is contained in:
parent
be7973b904
commit
7e66ea20db
|
@ -68,22 +68,26 @@ CleartextMessage.prototype.getSigningKeyIds = function() {
|
||||||
/**
|
/**
|
||||||
* 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 {Date} creationDate The creation time of the signature that should be created
|
||||||
* @return {module:message~CleartextMessage} new cleartext message with signed content
|
* @return {module:message~CleartextMessage} new cleartext message with signed content
|
||||||
*/
|
*/
|
||||||
CleartextMessage.prototype.sign = async function(privateKeys) {
|
CleartextMessage.prototype.sign = async function(privateKeys, signature = null, creationDate = new Date()) {
|
||||||
return new CleartextMessage(this.text, await this.signDetached(privateKeys));
|
return new CleartextMessage(this.text, await this.signDetached(privateKeys, signature, creationDate));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {Date} creationDate The creation time of the signature that should be created
|
||||||
* @return {module:signature~Signature} new detached signature of message content
|
* @return {module:signature~Signature} new detached signature of message content
|
||||||
*/
|
*/
|
||||||
CleartextMessage.prototype.signDetached = async function(privateKeys) {
|
CleartextMessage.prototype.signDetached = async function(privateKeys, signature = null, creationDate = new Date()) {
|
||||||
const literalDataPacket = new packet.Literal();
|
const literalDataPacket = new packet.Literal();
|
||||||
literalDataPacket.setText(this.text);
|
literalDataPacket.setText(this.text);
|
||||||
|
|
||||||
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys));
|
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, creationDate));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
30
src/key.js
30
src/key.js
|
@ -301,19 +301,20 @@ Key.prototype.armor = function() {
|
||||||
* Returns first key packet or key packet by given keyId that is available for signing or signature verification
|
* 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 {module:type/keyid} keyId, optional
|
||||||
* @param {Boolean} allowExpired allows signature verification with expired keys
|
* @param {Boolean} allowExpired allows signature verification with expired keys
|
||||||
|
* @param {Date} currentDate the current date
|
||||||
* @return {(module:packet/secret_subkey|module:packet/secret_key|null)} key packet or null if no signing key has been found
|
* @return {(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, allowExpired=false) {
|
Key.prototype.getSigningKeyPacket = function(keyId, allowExpired=false, currentDate = new Date()) {
|
||||||
const primaryUser = this.getPrimaryUser(allowExpired);
|
const primaryUser = this.getPrimaryUser(allowExpired);
|
||||||
if (primaryUser && (!keyId || this.primaryKey.getKeyId().equals(keyId)) &&
|
if (primaryUser && (!keyId || this.primaryKey.getKeyId().equals(keyId)) &&
|
||||||
isValidSigningKeyPacket(this.primaryKey, primaryUser.selfCertificate, allowExpired)) {
|
isValidSigningKeyPacket(this.primaryKey, primaryUser.selfCertificate, allowExpired, currentDate)) {
|
||||||
return this.primaryKey;
|
return this.primaryKey;
|
||||||
}
|
}
|
||||||
if (this.subKeys) {
|
if (this.subKeys) {
|
||||||
for (let i = 0; i < this.subKeys.length; i++) {
|
for (let i = 0; i < this.subKeys.length; i++) {
|
||||||
if (!keyId || this.subKeys[i].subKey.getKeyId().equals(keyId)) {
|
if (!keyId || this.subKeys[i].subKey.getKeyId().equals(keyId)) {
|
||||||
for (let j = 0; j < this.subKeys[i].bindingSignatures.length; j++) {
|
for (let j = 0; j < this.subKeys[i].bindingSignatures.length; j++) {
|
||||||
if (isValidSigningKeyPacket(this.subKeys[i].subKey, this.subKeys[i].bindingSignatures[j], allowExpired)) {
|
if (isValidSigningKeyPacket(this.subKeys[i].subKey, this.subKeys[i].bindingSignatures[j], allowExpired, currentDate)) {
|
||||||
return this.subKeys[i].subKey;
|
return this.subKeys[i].subKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,7 +324,7 @@ Key.prototype.getSigningKeyPacket = function(keyId, allowExpired=false) {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
function isValidEncryptionKeyPacket(keyPacket, signature, allowExpired=false) {
|
function isValidEncryptionKeyPacket(keyPacket, signature, allowExpired=false, currentDate = new Date()) {
|
||||||
return keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.dsa) &&
|
return keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.dsa) &&
|
||||||
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.rsa_sign) &&
|
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.rsa_sign) &&
|
||||||
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.ecdsa) &&
|
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.ecdsa) &&
|
||||||
|
@ -331,43 +332,44 @@ function isValidEncryptionKeyPacket(keyPacket, signature, allowExpired=false) {
|
||||||
(!signature.keyFlags ||
|
(!signature.keyFlags ||
|
||||||
(signature.keyFlags[0] & enums.keyFlags.encrypt_communication) !== 0 ||
|
(signature.keyFlags[0] & enums.keyFlags.encrypt_communication) !== 0 ||
|
||||||
(signature.keyFlags[0] & enums.keyFlags.encrypt_storage) !== 0) &&
|
(signature.keyFlags[0] & enums.keyFlags.encrypt_storage) !== 0) &&
|
||||||
(allowExpired || (!signature.isExpired() &&
|
(allowExpired || (!signature.isExpired(currentDate) &&
|
||||||
// check expiration time of V3 key packet
|
// check expiration time of V3 key packet
|
||||||
!(keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0 &&
|
!(keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0 &&
|
||||||
Date.now() > (keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000)) &&
|
+currentDate > (keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000)) &&
|
||||||
// check expiration time of V4 key packet
|
// check expiration time of V4 key packet
|
||||||
!(keyPacket.version === 4 && signature.keyNeverExpires === false &&
|
!(keyPacket.version === 4 && signature.keyNeverExpires === false &&
|
||||||
Date.now() > (keyPacket.created.getTime() + signature.keyExpirationTime*1000))));
|
+currentDate > (keyPacket.created.getTime() + signature.keyExpirationTime*1000))));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidSigningKeyPacket(keyPacket, signature, allowExpired=false) {
|
function isValidSigningKeyPacket(keyPacket, signature, allowExpired=false, currentDate = new Date()) {
|
||||||
return keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.rsa_encrypt) &&
|
return keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.rsa_encrypt) &&
|
||||||
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.elgamal) &&
|
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.elgamal) &&
|
||||||
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.ecdh) &&
|
keyPacket.algorithm !== enums.read(enums.publicKey, enums.publicKey.ecdh) &&
|
||||||
(!signature.keyFlags ||
|
(!signature.keyFlags ||
|
||||||
(signature.keyFlags[0] & enums.keyFlags.sign_data) !== 0) &&
|
(signature.keyFlags[0] & enums.keyFlags.sign_data) !== 0) &&
|
||||||
(allowExpired || (!signature.isExpired() &&
|
(allowExpired || (!signature.isExpired(currentDate) &&
|
||||||
// check expiration time of V3 key packet
|
// check expiration time of V3 key packet
|
||||||
!(keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0 &&
|
!(keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0 &&
|
||||||
Date.now() > (keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000)) &&
|
+currentDate > (keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000)) &&
|
||||||
// check expiration time of V4 key packet
|
// check expiration time of V4 key packet
|
||||||
!(keyPacket.version === 4 && signature.keyNeverExpires === false &&
|
!(keyPacket.version === 4 && signature.keyNeverExpires === false &&
|
||||||
Date.now() > (keyPacket.created.getTime() + signature.keyExpirationTime*1000))));
|
+currentDate > (keyPacket.created.getTime() + signature.keyExpirationTime*1000))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns first key packet or key packet by given keyId that is available for encryption or decryption
|
* Returns first key packet or key packet by given keyId that is available for encryption or decryption
|
||||||
* @param {module:type/keyid} keyId, optional
|
* @param {module:type/keyid} keyId, optional
|
||||||
|
* @param {Date} currentDate optional
|
||||||
* @returns {(module:packet/public_subkey|module:packet/secret_subkey|module:packet/secret_key|module:packet/public_key|null)} key packet or null if no encryption key has been found
|
* @returns {(module:packet/public_subkey|module:packet/secret_subkey|module:packet/secret_key|module:packet/public_key|null)} key packet or null if no encryption key has been found
|
||||||
*/
|
*/
|
||||||
Key.prototype.getEncryptionKeyPacket = function(keyId) {
|
Key.prototype.getEncryptionKeyPacket = function(keyId, currentDate = new Date()) {
|
||||||
// V4: by convention subkeys are preferred for encryption service
|
// V4: by convention subkeys are preferred for encryption service
|
||||||
// V3: keys MUST NOT have subkeys
|
// V3: keys MUST NOT have subkeys
|
||||||
if (this.subKeys) {
|
if (this.subKeys) {
|
||||||
for (let i = 0; i < this.subKeys.length; i++) {
|
for (let i = 0; i < this.subKeys.length; i++) {
|
||||||
if (!keyId || this.subKeys[i].subKey.getKeyId().equals(keyId)) {
|
if (!keyId || this.subKeys[i].subKey.getKeyId().equals(keyId)) {
|
||||||
for (let j = 0; j < this.subKeys[i].bindingSignatures.length; j++) {
|
for (let j = 0; j < this.subKeys[i].bindingSignatures.length; j++) {
|
||||||
if (isValidEncryptionKeyPacket(this.subKeys[i].subKey, this.subKeys[i].bindingSignatures[j])) {
|
if (isValidEncryptionKeyPacket(this.subKeys[i].subKey, this.subKeys[i].bindingSignatures[j], false, currentDate)) {
|
||||||
return this.subKeys[i].subKey;
|
return this.subKeys[i].subKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +379,7 @@ Key.prototype.getEncryptionKeyPacket = function(keyId) {
|
||||||
// if no valid subkey for encryption, evaluate primary key
|
// if no valid subkey for encryption, evaluate primary key
|
||||||
const primaryUser = this.getPrimaryUser();
|
const primaryUser = this.getPrimaryUser();
|
||||||
if (primaryUser && (!keyId || this.primaryKey.getKeyId().equals(keyId)) &&
|
if (primaryUser && (!keyId || this.primaryKey.getKeyId().equals(keyId)) &&
|
||||||
isValidEncryptionKeyPacket(this.primaryKey, primaryUser.selfCertificate)) {
|
isValidEncryptionKeyPacket(this.primaryKey, primaryUser.selfCertificate, false, currentDate)) {
|
||||||
return this.primaryKey;
|
return this.primaryKey;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -239,9 +239,10 @@ Message.prototype.getText = function() {
|
||||||
* @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 }
|
* @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 {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
* @param {Date} creationDate (optional) the current date of encryption
|
||||||
* @return {Message} new message with encrypted content
|
* @return {Message} new message with encrypted content
|
||||||
*/
|
*/
|
||||||
Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard = false) {
|
Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard = false, creationDate = new Date()) {
|
||||||
let symAlgo;
|
let symAlgo;
|
||||||
let msg;
|
let msg;
|
||||||
let symEncryptedPacket;
|
let symEncryptedPacket;
|
||||||
|
@ -264,7 +265,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard = fal
|
||||||
sessionKey = crypto.generateSessionKey(symAlgo);
|
sessionKey = crypto.generateSessionKey(symAlgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard);
|
msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard, creationDate);
|
||||||
|
|
||||||
if (config.aead_protect) {
|
if (config.aead_protect) {
|
||||||
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
|
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
|
||||||
|
@ -296,16 +297,17 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard = fal
|
||||||
* @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 {Date} creationDate (optional) the date used to encrypt
|
||||||
* @return {Message} new message with encrypted content
|
* @return {Message} new message with encrypted content
|
||||||
*/
|
*/
|
||||||
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false) {
|
export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false, creationDate = new Date()) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
return Promise.resolve().then(async () => {
|
return Promise.resolve().then(async () => {
|
||||||
if (publicKeys) {
|
if (publicKeys) {
|
||||||
const results = await Promise.all(publicKeys.map(async function(key) {
|
const results = await Promise.all(publicKeys.map(async function(key) {
|
||||||
await key.verifyPrimaryUser();
|
await key.verifyPrimaryUser();
|
||||||
const encryptionKeyPacket = key.getEncryptionKeyPacket();
|
const encryptionKeyPacket = key.getEncryptionKeyPacket(undefined, creationDate);
|
||||||
if (!encryptionKeyPacket) {
|
if (!encryptionKeyPacket) {
|
||||||
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
|
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
|
||||||
}
|
}
|
||||||
|
@ -358,11 +360,12 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wi
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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>} privateKey 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 {Date} creationDate} (optional) the creation date of the signature used for creating a new signature
|
||||||
* @return {module:message~Message} new message with signed content
|
* @return {module:message~Message} new message with signed content
|
||||||
*/
|
*/
|
||||||
Message.prototype.sign = async function(privateKeys=[], signature=null) {
|
Message.prototype.sign = async function(privateKeys=[], signature=null, creationDate = new Date()) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
||||||
|
@ -397,7 +400,7 @@ Message.prototype.sign = async function(privateKeys=[], signature=null) {
|
||||||
throw new Error('Need private key for signing');
|
throw new Error('Need private key for signing');
|
||||||
}
|
}
|
||||||
await privateKey.verifyPrimaryUser();
|
await privateKey.verifyPrimaryUser();
|
||||||
const signingKeyPacket = privateKey.getSigningKeyPacket();
|
const signingKeyPacket = privateKey.getSigningKeyPacket(undefined, undefined, creationDate);
|
||||||
if (!signingKeyPacket) {
|
if (!signingKeyPacket) {
|
||||||
throw new Error('Could not find valid key packet for signing in key ' +
|
throw new Error('Could not find valid key packet for signing in key ' +
|
||||||
privateKey.primaryKey.getKeyId().toHex());
|
privateKey.primaryKey.getKeyId().toHex());
|
||||||
|
@ -416,7 +419,7 @@ Message.prototype.sign = async function(privateKeys=[], signature=null) {
|
||||||
});
|
});
|
||||||
|
|
||||||
packetlist.push(literalDataPacket);
|
packetlist.push(literalDataPacket);
|
||||||
packetlist.concat(await createSignaturePackets(literalDataPacket, privateKeys, signature));
|
packetlist.concat(await createSignaturePackets(literalDataPacket, privateKeys, signature, creationDate));
|
||||||
|
|
||||||
return new Message(packetlist);
|
return new Message(packetlist);
|
||||||
};
|
};
|
||||||
|
@ -443,26 +446,30 @@ Message.prototype.compress = function(compression) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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>} privateKey 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 {Date} creationDate (optional) the creation date to sign the message with
|
||||||
* @return {module:signature~Signature} new detached signature of message content
|
* @return {module:signature~Signature} new detached signature of message content
|
||||||
*/
|
*/
|
||||||
Message.prototype.signDetached = async function(privateKeys=[], signature=null) {
|
Message.prototype.signDetached = async function(privateKeys=[], signature=null, creationDate = new Date()) {
|
||||||
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
||||||
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));
|
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, creationDate));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create signature packets for the message
|
* Create signature packets for the message
|
||||||
* @param {module:packet/literal} the literal data packet to sign
|
* @param {module:packet/literal} literalDataPacket the literal data packet to sign
|
||||||
* @param {Array<module:key~Key>} privateKey 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 {Date} creationDate (optional) the creation date to sign the message with
|
||||||
* @return {module:packet/packetlist} list of signature packets
|
* @return {module:packet/packetlist} list of signature packets
|
||||||
*/
|
*/
|
||||||
export async function createSignaturePackets(literalDataPacket, privateKeys, signature=null) {
|
export async function createSignaturePackets(literalDataPacket, privateKeys, signature=null, creationDate = new Date()) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
const literalFormat = enums.write(enums.literal, literalDataPacket.format);
|
const literalFormat = enums.write(enums.literal, literalDataPacket.format);
|
||||||
|
@ -474,14 +481,14 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig
|
||||||
throw new Error('Need private key for signing');
|
throw new Error('Need private key for signing');
|
||||||
}
|
}
|
||||||
await privateKey.verifyPrimaryUser();
|
await privateKey.verifyPrimaryUser();
|
||||||
const signingKeyPacket = privateKey.getSigningKeyPacket();
|
const signingKeyPacket = privateKey.getSigningKeyPacket(undefined, undefined, creationDate);
|
||||||
if (!signingKeyPacket) {
|
if (!signingKeyPacket) {
|
||||||
throw new Error('Could not find valid key packet for signing in key ' + privateKey.primaryKey.getKeyId().toHex());
|
throw new Error('Could not find valid key packet for signing in key ' + privateKey.primaryKey.getKeyId().toHex());
|
||||||
}
|
}
|
||||||
if (!signingKeyPacket.isDecrypted) {
|
if (!signingKeyPacket.isDecrypted) {
|
||||||
throw new Error('Private key is not decrypted.');
|
throw new Error('Private key is not decrypted.');
|
||||||
}
|
}
|
||||||
const signaturePacket = new packet.Signature();
|
const signaturePacket = new packet.Signature(creationDate);
|
||||||
signaturePacket.signatureType = signatureType;
|
signaturePacket.signatureType = signatureType;
|
||||||
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
||||||
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
|
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
|
||||||
|
@ -626,11 +633,12 @@ export function readSignedContent(content, detachedSignature) {
|
||||||
* creates new message object from text
|
* creates new message object from text
|
||||||
* @param {String} text
|
* @param {String} text
|
||||||
* @param {String} filename (optional)
|
* @param {String} filename (optional)
|
||||||
|
* @param {Date} creationDate (optional)
|
||||||
* @return {module:message~Message} new message object
|
* @return {module:message~Message} new message object
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function fromText(text, filename) {
|
export function fromText(text, filename, creationDate = new Date()) {
|
||||||
const literalDataPacket = new packet.Literal();
|
const literalDataPacket = new packet.Literal(creationDate);
|
||||||
// text will be converted to UTF8
|
// text will be converted to UTF8
|
||||||
literalDataPacket.setText(text);
|
literalDataPacket.setText(text);
|
||||||
if (filename !== undefined) {
|
if (filename !== undefined) {
|
||||||
|
@ -645,15 +653,16 @@ export function fromText(text, filename) {
|
||||||
* creates new message object from binary data
|
* creates new message object from binary data
|
||||||
* @param {Uint8Array} bytes
|
* @param {Uint8Array} bytes
|
||||||
* @param {String} filename (optional)
|
* @param {String} filename (optional)
|
||||||
|
* @param {Date} creationDate (optional)
|
||||||
* @return {module:message~Message} new message object
|
* @return {module:message~Message} new message object
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function fromBinary(bytes, filename) {
|
export function fromBinary(bytes, filename, creationDate = new Date()) {
|
||||||
if (!util.isUint8Array(bytes)) {
|
if (!util.isUint8Array(bytes)) {
|
||||||
throw new Error('Data must be in the form of a Uint8Array');
|
throw new Error('Data must be in the form of a Uint8Array');
|
||||||
}
|
}
|
||||||
|
|
||||||
const literalDataPacket = new packet.Literal();
|
const literalDataPacket = new packet.Literal(creationDate);
|
||||||
if (filename) {
|
if (filename) {
|
||||||
literalDataPacket.setFilename(filename);
|
literalDataPacket.setFilename(filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,33 +202,34 @@ export function decryptKey({ privateKey, passphrase }) {
|
||||||
* @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} returnSessionKey (optional) if the unencrypted session key should be added to returned object
|
* @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 {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
|
* @param {Date} creationDate (optional) the creation date used to encrypt and sign the message
|
||||||
* @return {Promise<Object>} encrypted (and optionally signed message) in the form:
|
* @return {Promise<Object>} encrypted (and optionally signed message) in the form:
|
||||||
* {data: ASCII armored message if 'armor' is true,
|
* {data: ASCII armored message if 'armor' is true,
|
||||||
* message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true}
|
* message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true}
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, compression = config.compression, armor = true, detached = false, signature = null, returnSessionKey = false, wildcard = false}) {
|
export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, compression = config.compression, armor = true, detached = false, signature = null, returnSessionKey = false, wildcard = false, creationDate = new Date()}) {
|
||||||
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
|
checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
|
||||||
|
|
||||||
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
|
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
|
||||||
return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey, wildcard });
|
return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey, wildcard, creationDate });
|
||||||
}
|
}
|
||||||
const result = {};
|
const result = {};
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
let message = createMessage(data, filename);
|
let message = createMessage(data, filename, creationDate);
|
||||||
if (!privateKeys) {
|
if (!privateKeys) {
|
||||||
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
|
||||||
if (detached) {
|
if (detached) {
|
||||||
const detachedSignature = await message.signDetached(privateKeys, signature);
|
const detachedSignature = await message.signDetached(privateKeys, signature, creationDate);
|
||||||
result.signature = armor ? detachedSignature.armor() : detachedSignature;
|
result.signature = armor ? detachedSignature.armor() : detachedSignature;
|
||||||
} else {
|
} else {
|
||||||
message = await message.sign(privateKeys, signature);
|
message = await message.sign(privateKeys, signature, creationDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message = message.compress(compression);
|
message = message.compress(compression);
|
||||||
return message.encrypt(publicKeys, passwords, sessionKey, wildcard);
|
return message.encrypt(publicKeys, passwords, sessionKey, wildcard, creationDate);
|
||||||
|
|
||||||
}).then(encrypted => {
|
}).then(encrypted => {
|
||||||
if (armor) {
|
if (armor) {
|
||||||
|
@ -291,20 +292,21 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
|
||||||
* @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
|
* @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
|
||||||
* @param {Boolean} armor (optional) if the return value should be ascii armored or the message object
|
* @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 {Boolean} detached (optional) if the return value should contain a detached signature
|
||||||
|
* @param {Date} creationDate (optional) the creation date used to sign the message
|
||||||
* @return {Promise<Object>} signed cleartext in the form:
|
* @return {Promise<Object>} signed cleartext in the form:
|
||||||
* {data: ASCII armored message if 'armor' is true,
|
* {data: ASCII armored message if 'armor' is true,
|
||||||
* message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true}
|
* message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true}
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function sign({
|
export function sign({
|
||||||
data, privateKeys, armor=true, detached=false
|
data, privateKeys, armor=true, detached=false, creationDate = new Date()
|
||||||
}) {
|
}) {
|
||||||
checkData(data);
|
checkData(data);
|
||||||
privateKeys = toArray(privateKeys);
|
privateKeys = toArray(privateKeys);
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.delegate('sign', {
|
return asyncProxy.delegate('sign', {
|
||||||
data, privateKeys, armor, detached
|
data, privateKeys, armor, detached, creationDate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,10 +315,10 @@ export function sign({
|
||||||
let message = util.isString(data) ? new CleartextMessage(data) : messageLib.fromBinary(data);
|
let message = util.isString(data) ? new CleartextMessage(data) : messageLib.fromBinary(data);
|
||||||
|
|
||||||
if (detached) {
|
if (detached) {
|
||||||
const signature = await message.signDetached(privateKeys);
|
const signature = await message.signDetached(privateKeys, undefined, creationDate);
|
||||||
result.signature = armor ? signature.armor() : signature;
|
result.signature = armor ? signature.armor() : signature;
|
||||||
} else {
|
} else {
|
||||||
message = await message.sign(privateKeys);
|
message = await message.sign(privateKeys, undefined, creationDate);
|
||||||
if (armor) {
|
if (armor) {
|
||||||
result.data = message.armor();
|
result.data = message.armor();
|
||||||
} else {
|
} else {
|
||||||
|
@ -493,14 +495,15 @@ function toArray(param) {
|
||||||
* Creates a message obejct either from a Uint8Array or a string.
|
* Creates a message obejct either from a Uint8Array or a string.
|
||||||
* @param {String|Uint8Array} data the payload for the message
|
* @param {String|Uint8Array} data the payload for the message
|
||||||
* @param {String} filename the literal data packet's filename
|
* @param {String} filename the literal data packet's filename
|
||||||
|
* @param {Date} creationDate the creation date of the package
|
||||||
* @return {Message} a message object
|
* @return {Message} a message object
|
||||||
*/
|
*/
|
||||||
function createMessage(data, filename) {
|
function createMessage(data, filename, creationDate = new Date()) {
|
||||||
let msg;
|
let msg;
|
||||||
if (util.isUint8Array(data)) {
|
if (util.isUint8Array(data)) {
|
||||||
msg = messageLib.fromBinary(data, filename);
|
msg = messageLib.fromBinary(data, filename, creationDate);
|
||||||
} else if (util.isString(data)) {
|
} else if (util.isString(data)) {
|
||||||
msg = messageLib.fromText(data, filename);
|
msg = messageLib.fromText(data, filename, creationDate);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Data must be of type String or Uint8Array');
|
throw new Error('Data must be of type String or Uint8Array');
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,10 @@ import enums from '../enums.js';
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export default function Literal() {
|
export default function Literal(creationDate = new Date()) {
|
||||||
this.tag = enums.packet.literal;
|
this.tag = enums.packet.literal;
|
||||||
this.format = 'utf8'; // default format for literal data packets
|
this.format = 'utf8'; // default format for literal data packets
|
||||||
this.date = new Date();
|
this.date = creationDate;
|
||||||
this.data = new Uint8Array(0); // literal data representation
|
this.data = new Uint8Array(0); // literal data representation
|
||||||
this.filename = 'msg.txt';
|
this.filename = 'msg.txt';
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ import type_keyid from '../type/keyid.js';
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export default function Signature() {
|
export default function Signature(creationDate = new Date()) {
|
||||||
this.tag = enums.packet.signature;
|
this.tag = enums.packet.signature;
|
||||||
this.version = 4;
|
this.version = 4;
|
||||||
this.signatureType = null;
|
this.signatureType = null;
|
||||||
|
@ -52,7 +52,7 @@ export default function Signature() {
|
||||||
this.unhashedSubpackets = null;
|
this.unhashedSubpackets = null;
|
||||||
this.signedHashValue = null;
|
this.signedHashValue = null;
|
||||||
|
|
||||||
this.created = new Date();
|
this.created = creationDate;
|
||||||
this.signatureExpirationTime = null;
|
this.signatureExpirationTime = null;
|
||||||
this.signatureNeverExpires = true;
|
this.signatureNeverExpires = true;
|
||||||
this.exportable = null;
|
this.exportable = null;
|
||||||
|
@ -663,9 +663,9 @@ Signature.prototype.verify = async function (key, data) {
|
||||||
* Verifies signature expiration date
|
* Verifies signature expiration date
|
||||||
* @return {Boolean} true if expired
|
* @return {Boolean} true if expired
|
||||||
*/
|
*/
|
||||||
Signature.prototype.isExpired = function () {
|
Signature.prototype.isExpired = function (currentDate = new Date()) {
|
||||||
if (!this.signatureNeverExpires) {
|
if (!this.signatureNeverExpires) {
|
||||||
return Date.now() > (this.created.getTime() + this.signatureExpirationTime*1000);
|
return +currentDate > (this.created.getTime() + this.signatureExpirationTime*1000);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,6 +158,182 @@ const priv_key_de =
|
||||||
'=kyeP',
|
'=kyeP',
|
||||||
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
||||||
|
|
||||||
|
const priv_key_2000_2008 = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
|
xcEYBDioN2gBBACy5VEu8/dlQHOd12v8tNY2Aic+C+k6yyKe7eHRf1Pqwd0d
|
||||||
|
OdMk+0EvMi1Z+i0x/cQj89te81F7TCmVd+qrIWR6rKc/6WQzg9FQ0h1WQKxD
|
||||||
|
YizEIyia0ZNEuYd7F1H6ycx352tymepAth05i6t1LxI5jExFDq+d8z8L5ezq
|
||||||
|
+/6BZQARAQABAAP5AY01ySGNEQKq2LY0WyaqCqG1+5azW72aIS+WKztpO9VE
|
||||||
|
HhuGXmD+gFK1VtKHFKgAjOucc2RKszYmey56ftL6kdvBs404GEFGCtZOkr4a
|
||||||
|
PcnSBM7SNZrUlOIBN9u6U4McnNYdEhyARIf+Qm9NGTbzZCoZ13f40/QjX2TG
|
||||||
|
2T6cTwECAOeTJBaIinz+OInqPzWbEndnbWKIXbPhPtpvU/D2OyLquwMmma8r
|
||||||
|
khX78V9ZduLVwtzP2DyGnQ+yHBmLCgjxEQECAMXDxAlcx3LbAGew6OA2u938
|
||||||
|
Cf+O0fJWid3/e0gNppvnbayTtisXF0uENX4pJv82S02QgqxFL3FYrdON5KVW
|
||||||
|
zGUB/3rtIzMQJaSYZAJFc4SDOn1RNkl4nUroPf1IbB17nDX/GcB6acquJxQq
|
||||||
|
0q5FtJCrnNR2K25u6t2AGDcZLleSaFSamc0TdGVzdCA8dGVzdEBleGFtcGxl
|
||||||
|
PsKtBBMBCgAXBQI4qDdoAhsvAwsJBwMVCggCHgECF4AACgkQXPAg04i7hHT2
|
||||||
|
rwQAip3cACXdbShpxvKEsQs0oBN1H5PAx1BAGXanw+jxDFUkrDk1DOSrZFnM
|
||||||
|
aohuoJrYyoE/RkLz061g8tFc/KETmnyJAcXL/PPic3tPCCs1cphVAsAjELsY
|
||||||
|
wPL4UQpFnRU2e+phgzX9M/G78wvqiOGcM/K0SZTnyRvYaAHHuLFE2xnHwRgE
|
||||||
|
OKg3aAEEALOt5AUdDf7fz0DwOkIokGj4zeiFuphsTPwpRAS6c1o9xAzS/C8h
|
||||||
|
LFShhTKL4Z9znYkdaMHuFIs7AJ3P5tKlvG0/cZAl3u286lz0aTtQluHMCKNy
|
||||||
|
UyhuZ0K1VgZOj+HcDKo8jQ+aejcwjHDg02yPvfzrXHBjWAJMjglV4W+YPFYj
|
||||||
|
ABEBAAEAA/9FbqPXagPXgssG8A3DNQOg3MxM1yhk8CzLoHKdVSNwMsAIqJs0
|
||||||
|
5x/HUGc1QiKcyEOPEaNClWqw5sr1MLqkmdD2y9xU6Ys1VyJY92GKQyVAgLej
|
||||||
|
tAvgeUb7NoHKU7b8F/oDfZezY8rs5fBRNVO5hHd+aAD4gcAAfIeAmy7AHRU9
|
||||||
|
wQIA7UPEpAI/lil5fDByHz7wyo1k/7yLqY18tHEAcUbPwUWvYCuvv3ASts78
|
||||||
|
0kQETsqn0bZZuuiR+IRdFxZzsElLAwIAwd4M85ewucF2tsyJYWJq4A+dETJC
|
||||||
|
WJfcSboagENXUYjOsLgtU/H8b9JD9CWpsd0DkcPshKAjuum6c3cUaTROYQIA
|
||||||
|
lp2kWrnzdLZxXELA2RDTaqsp/M+XhwKhChuG53FH+AKMVrwDImG7qVVL07gI
|
||||||
|
Rv+gGkG79PGvej7YZLZvHIq/+qTWwsCDBBgBCgAPBQI4qDdoBQkPCZwAAhsu
|
||||||
|
AKgJEFzwINOIu4R0nSAEGQEKAAYFAjioN2gACgkQ4fPj4++ExKB1EQP+Ppm5
|
||||||
|
hmv2c04836wMXHjjCIX1fsBhJNSeWNZljxPOcPgb0kAd2hY1S/Vn9ZDogeYm
|
||||||
|
DBUQ/JHj42Edda2IYax/74dAwUTV2KnDsdBT8Tb9ljHnY3GM7JqEKi/u09u7
|
||||||
|
Zfwq3auRDH8RW/hRHQ058dfkSoorpN5iCUfzYJemM4ZmA7NPCwP+PsQ63uIP
|
||||||
|
mDB49M2sQwV1GsBc+YB+aD3hggsRv7UHh4gvr2GCcukRlHDi/pOEO/ZTaoyS
|
||||||
|
un3m7b2M4n31bEj1lknZBtMZLo0uWww6YpAQEwFFXhVcAOYQqOb2KfF1rJGB
|
||||||
|
6w10tmpXdNWm5JPANu6RqaXIzkuMcRUqlYcNLfz6SUHHwRgEOKg3aAEEALfQ
|
||||||
|
/ENJxzybgdKLQBhF8RN3xb1V8DiYFtfgDkboavjiSD7PVEDNO286cLoe/uAk
|
||||||
|
E+Dgm2oEFmZ/IJShX+BL1JkHreNKuWTW0Gz0jkqYbE44Kssy5ywCXc0ItW4y
|
||||||
|
rMtabXPI5zqXzePd9Fwp7ZOt8QN/jU+TUfGUMwEv2tDKq/+7ABEBAAEAA/4l
|
||||||
|
tAGSQbdSqKj7ySE3+Vyl/Bq8p7xyt0t0Mxpqk/ChJTThYUBsXExVF70YiBQK
|
||||||
|
YIwNQ7TNDZKUqn3BzsnuJU+xTHKx8/mg7cGo+EzBstLMz7tGQJ9GN2LwrTZj
|
||||||
|
/yA2JZk3t54Ip/eNCkg7j5OaJG9l3RaW3DKPskRFY63gnitC8QIA745VRJmw
|
||||||
|
FwmHQ0H4ZoggO26+Q77ViYn84s8gio7AWkrFlt5sWhSdkrGcy/IIeSqzq0ZU
|
||||||
|
2p7zsXR8qz85+RyTcQIAxG8mwRGHkboHVa6qKt+lAxpqCuxe/buniw0LZuzu
|
||||||
|
wJQU+E6Y0oybSAcOjleIMkxULljc3Us7a5/HDKdQi4mX6wH/bVPlW8koygus
|
||||||
|
mDVIPSP2rmjBA9YVLn5CBPG+u0oGAMY9tfJ848V22S/ZPYNZe9ksFSjEuFDL
|
||||||
|
Xnmz/O1jI3Xht6IGwsCDBBgBCgAPBQI4qDdoBQkPCZwAAhsuAKgJEFzwINOI
|
||||||
|
u4R0nSAEGQEKAAYFAjioN2gACgkQJVG+vfNJQKhK6gP+LB5qXTJKCduuqZm7
|
||||||
|
VhFvPeOu4W0pyORo29zZI0owKZnD2ZKZrZhKXZC/1+xKXi8aX4V2ygRth2P1
|
||||||
|
tGFLJRqRiA3C20NVewdI4tQtEqWWSlfNFDz4EsbNspyodQ4jPsKPk2R8pFjA
|
||||||
|
wmpXLizPg2UyPKUJ/2GnNWjleP0UNyUXgD1MkgP+IkxXTYgDF5/LrOlrq7Th
|
||||||
|
WqFqQ/prQCBy7xxNLjpVKLDxGYbXVER6p0pkD6DXlaOgSB3i32dQJnU96l44
|
||||||
|
TlUyaUK/dJP7JPbVUOFq/awSxJiCxFxF6Oarc10qQ+OG5ESdJAjpCMHGCzlb
|
||||||
|
t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
|
||||||
|
=C0fJ
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
const pub_key_2000_2008 = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
xo0EOKg3aAEEALLlUS7z92VAc53Xa/y01jYCJz4L6TrLIp7t4dF/U+rB3R050yT7
|
||||||
|
QS8yLVn6LTH9xCPz217zUXtMKZV36qshZHqspz/pZDOD0VDSHVZArENiLMQjKJrR
|
||||||
|
k0S5h3sXUfrJzHfna3KZ6kC2HTmLq3UvEjmMTEUOr53zPwvl7Or7/oFlABEBAAHN
|
||||||
|
E3Rlc3QgPHRlc3RAZXhhbXBsZT7CrQQTAQoAFwUCOKg3aAIbLwMLCQcDFQoIAh4B
|
||||||
|
AheAAAoJEFzwINOIu4R09q8EAIqd3AAl3W0oacbyhLELNKATdR+TwMdQQBl2p8Po
|
||||||
|
8QxVJKw5NQzkq2RZzGqIbqCa2MqBP0ZC89OtYPLRXPyhE5p8iQHFy/zz4nN7Twgr
|
||||||
|
NXKYVQLAIxC7GMDy+FEKRZ0VNnvqYYM1/TPxu/ML6ojhnDPytEmU58kb2GgBx7ix
|
||||||
|
RNsZzo0EOKg3aAEEALOt5AUdDf7fz0DwOkIokGj4zeiFuphsTPwpRAS6c1o9xAzS
|
||||||
|
/C8hLFShhTKL4Z9znYkdaMHuFIs7AJ3P5tKlvG0/cZAl3u286lz0aTtQluHMCKNy
|
||||||
|
UyhuZ0K1VgZOj+HcDKo8jQ+aejcwjHDg02yPvfzrXHBjWAJMjglV4W+YPFYjABEB
|
||||||
|
AAHCwIMEGAEKAA8FAjioN2gFCQ8JnAACGy4AqAkQXPAg04i7hHSdIAQZAQoABgUC
|
||||||
|
OKg3aAAKCRDh8+Pj74TEoHURA/4+mbmGa/ZzTjzfrAxceOMIhfV+wGEk1J5Y1mWP
|
||||||
|
E85w+BvSQB3aFjVL9Wf1kOiB5iYMFRD8kePjYR11rYhhrH/vh0DBRNXYqcOx0FPx
|
||||||
|
Nv2WMedjcYzsmoQqL+7T27tl/Crdq5EMfxFb+FEdDTnx1+RKiiuk3mIJR/Ngl6Yz
|
||||||
|
hmYDs08LA/4+xDre4g+YMHj0zaxDBXUawFz5gH5oPeGCCxG/tQeHiC+vYYJy6RGU
|
||||||
|
cOL+k4Q79lNqjJK6febtvYziffVsSPWWSdkG0xkujS5bDDpikBATAUVeFVwA5hCo
|
||||||
|
5vYp8XWskYHrDXS2ald01abkk8A27pGppcjOS4xxFSqVhw0t/PpJQc6NBDioN2gB
|
||||||
|
BAC30PxDScc8m4HSi0AYRfETd8W9VfA4mBbX4A5G6Gr44kg+z1RAzTtvOnC6Hv7g
|
||||||
|
JBPg4JtqBBZmfyCUoV/gS9SZB63jSrlk1tBs9I5KmGxOOCrLMucsAl3NCLVuMqzL
|
||||||
|
Wm1zyOc6l83j3fRcKe2TrfEDf41Pk1HxlDMBL9rQyqv/uwARAQABwsCDBBgBCgAP
|
||||||
|
BQI4qDdoBQkPCZwAAhsuAKgJEFzwINOIu4R0nSAEGQEKAAYFAjioN2gACgkQJVG+
|
||||||
|
vfNJQKhK6gP+LB5qXTJKCduuqZm7VhFvPeOu4W0pyORo29zZI0owKZnD2ZKZrZhK
|
||||||
|
XZC/1+xKXi8aX4V2ygRth2P1tGFLJRqRiA3C20NVewdI4tQtEqWWSlfNFDz4EsbN
|
||||||
|
spyodQ4jPsKPk2R8pFjAwmpXLizPg2UyPKUJ/2GnNWjleP0UNyUXgD1MkgP+IkxX
|
||||||
|
TYgDF5/LrOlrq7ThWqFqQ/prQCBy7xxNLjpVKLDxGYbXVER6p0pkD6DXlaOgSB3i
|
||||||
|
32dQJnU96l44TlUyaUK/dJP7JPbVUOFq/awSxJiCxFxF6Oarc10qQ+OG5ESdJAjp
|
||||||
|
CMHGCzlbt/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
|
||||||
|
=kwK1
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----`;
|
||||||
|
|
||||||
|
const priv_key_2038_2045 = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
|
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
|
||||||
|
0uyeibPdgJTjARMuQzDFA8bdbM540vBf5Q==
|
||||||
|
=WLIN
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
const pub_key_2038_2045 = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
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
|
||||||
|
=yV+n
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----`;
|
||||||
|
|
||||||
const passphrase = 'hello world';
|
const passphrase = 'hello world';
|
||||||
const plaintext = 'short message\nnext line\n한국어/조선말';
|
const plaintext = 'short message\nnext line\n한국어/조선말';
|
||||||
const password1 = 'I am a password';
|
const password1 = 'I am a password';
|
||||||
|
@ -465,6 +641,10 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('encrypt, decrypt, sign, verify - integration tests', function() {
|
describe('encrypt, decrypt, sign, verify - integration tests', function() {
|
||||||
|
let privateKey_2000_2008;
|
||||||
|
let publicKey_2000_2008;
|
||||||
|
let privateKey_2038_2045;
|
||||||
|
let publicKey_2038_2045;
|
||||||
let privateKey;
|
let privateKey;
|
||||||
let publicKey;
|
let publicKey;
|
||||||
let zero_copyVal;
|
let zero_copyVal;
|
||||||
|
@ -478,6 +658,18 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
privateKey = openpgp.key.readArmored(priv_key);
|
privateKey = openpgp.key.readArmored(priv_key);
|
||||||
expect(privateKey.keys).to.have.length(1);
|
expect(privateKey.keys).to.have.length(1);
|
||||||
expect(privateKey.err).to.not.exist;
|
expect(privateKey.err).to.not.exist;
|
||||||
|
publicKey_2000_2008 = openpgp.key.readArmored(pub_key_2000_2008);
|
||||||
|
expect(publicKey_2000_2008.keys).to.have.length(1);
|
||||||
|
expect(publicKey_2000_2008.err).to.not.exist;
|
||||||
|
privateKey_2000_2008 = openpgp.key.readArmored(priv_key_2000_2008);
|
||||||
|
expect(privateKey_2000_2008.keys).to.have.length(1);
|
||||||
|
expect(privateKey_2000_2008.err).to.not.exist;
|
||||||
|
publicKey_2038_2045 = openpgp.key.readArmored(pub_key_2038_2045);
|
||||||
|
expect(publicKey_2038_2045.keys).to.have.length(1);
|
||||||
|
expect(publicKey_2038_2045.err).to.not.exist;
|
||||||
|
privateKey_2038_2045 = openpgp.key.readArmored(priv_key_2038_2045);
|
||||||
|
expect(privateKey_2038_2045.keys).to.have.length(1);
|
||||||
|
expect(privateKey_2038_2045.err).to.not.exist;
|
||||||
zero_copyVal = openpgp.config.zero_copy;
|
zero_copyVal = openpgp.config.zero_copy;
|
||||||
use_nativeVal = openpgp.config.use_native;
|
use_nativeVal = openpgp.config.use_native;
|
||||||
aead_protectVal = openpgp.config.aead_protect;
|
aead_protectVal = openpgp.config.aead_protect;
|
||||||
|
@ -1347,26 +1539,317 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should sign and verify cleartext data and not armor with detached signatures', function () {
|
it('should sign and verify cleartext data and not armor with detached signatures', function () {
|
||||||
const signOpt = {
|
const start = Date.now();
|
||||||
data: plaintext,
|
const signOpt = {
|
||||||
privateKeys: privateKey.keys,
|
data: plaintext,
|
||||||
detached: true,
|
privateKeys: privateKey.keys,
|
||||||
armor: false
|
detached: true,
|
||||||
};
|
armor: false
|
||||||
const verifyOpt = {
|
};
|
||||||
publicKeys: publicKey.keys
|
const verifyOpt = {
|
||||||
};
|
publicKeys: publicKey.keys
|
||||||
return openpgp.sign(signOpt).then(function (signed) {
|
};
|
||||||
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
|
return openpgp.sign(signOpt).then(function (signed) {
|
||||||
verifyOpt.signature = signed.signature;
|
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
|
||||||
return openpgp.verify(verifyOpt);
|
verifyOpt.signature = signed.signature;
|
||||||
}).then(function (verified) {
|
return openpgp.verify(verifyOpt);
|
||||||
expect(verified.data).to.equal(plaintext);
|
}).then(function (verified) {
|
||||||
expect(verified.signatures[0].valid).to.be.true;
|
expect(verified.data).to.equal(plaintext);
|
||||||
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
expect(+verified.signatures[0].signature.packets[0].created).to.be.lte(Date.now());
|
||||||
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
expect(+verified.signatures[0].signature.packets[0].created).to.be.gte(start);
|
||||||
});
|
expect(verified.signatures[0].valid).to.be.true;
|
||||||
|
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||||
|
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should sign and verify cleartext data with a date in the past', function () {
|
||||||
|
const past = new Date(2005, 5, 5, 5, 5, 5, 0);
|
||||||
|
const signOpt = {
|
||||||
|
data: plaintext,
|
||||||
|
privateKeys: privateKey_2000_2008.keys,
|
||||||
|
detached: true,
|
||||||
|
creationDate: past,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const verifyOpt = {
|
||||||
|
publicKeys: publicKey_2000_2008.keys
|
||||||
|
};
|
||||||
|
return openpgp.sign(signOpt).then(function (signed) {
|
||||||
|
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
|
||||||
|
verifyOpt.signature = signed.signature;
|
||||||
|
return openpgp.verify(verifyOpt);
|
||||||
|
}).then(function (verified) {
|
||||||
|
expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past);
|
||||||
|
expect(verified.data).to.equal(plaintext);
|
||||||
|
expect(verified.signatures[0].valid).to.be.true;
|
||||||
|
expect(signOpt.privateKeys[0].getSigningKeyPacket(verified.signatures[0].keyid, undefined, past))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should sign and verify binary data with a date in the future', function () {
|
||||||
|
const future = new Date(2040, 5, 5, 5, 5, 5, 0);
|
||||||
|
const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]);
|
||||||
|
const signOpt = {
|
||||||
|
data,
|
||||||
|
privateKeys: privateKey_2038_2045.keys,
|
||||||
|
detached: true,
|
||||||
|
creationDate: future,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const verifyOpt = {
|
||||||
|
publicKeys: publicKey_2038_2045.keys
|
||||||
|
};
|
||||||
|
return openpgp.sign(signOpt).then(function (signed) {
|
||||||
|
verifyOpt.message = openpgp.message.fromBinary(data);
|
||||||
|
verifyOpt.signature = signed.signature;
|
||||||
|
return openpgp.verify(verifyOpt);
|
||||||
|
}).then(function (verified) {
|
||||||
|
expect(+verified.signatures[0].signature.packets[0].created).to.equal(+future);
|
||||||
|
expect(verified.data).to.equal(data);
|
||||||
|
expect(verified.signatures[0].valid).to.be.true;
|
||||||
|
expect(signOpt.privateKeys[0].getSigningKeyPacket(verified.signatures[0].keyid, undefined, future))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt and decrypt cleartext data with a date in the future', function () {
|
||||||
|
const future = new Date(2040, 5, 5, 5, 5, 5, 0);
|
||||||
|
const encryptOpt = {
|
||||||
|
data: plaintext,
|
||||||
|
publicKeys: publicKey_2038_2045.keys,
|
||||||
|
creationDate: future,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const decryptOpt = {
|
||||||
|
privateKeys: privateKey_2038_2045.keys
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
decryptOpt.message = encrypted.message;
|
||||||
|
return encrypted.message.decrypt(decryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+future);
|
||||||
|
expect(packets.getText()).to.equal(plaintext);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should encrypt and decrypt binary data with a date in the past', function () {
|
||||||
|
const past = new Date(2005, 5, 5, 5, 5, 5, 0);
|
||||||
|
const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]);
|
||||||
|
const encryptOpt = {
|
||||||
|
data,
|
||||||
|
publicKeys: publicKey_2000_2008.keys,
|
||||||
|
creationDate: past,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const decryptOpt = {
|
||||||
|
privateKeys: privateKey_2000_2008.keys
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
decryptOpt.message = encrypted.message;
|
||||||
|
return encrypted.message.decrypt(decryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+past);
|
||||||
|
expect(packets.getLiteralData()).to.deep.equal(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sign, encrypt and decrypt, verify cleartext data with a date in the past', function () {
|
||||||
|
const past = new Date(2005, 5, 5, 5, 5, 5, 0);
|
||||||
|
const encryptOpt = {
|
||||||
|
data: plaintext,
|
||||||
|
publicKeys: publicKey_2000_2008.keys,
|
||||||
|
privateKeys: privateKey_2000_2008.keys,
|
||||||
|
creationDate: past,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
return encrypted.message.decrypt(encryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+past);
|
||||||
|
expect(packets.getText()).to.equal(plaintext);
|
||||||
|
return packets.verify(encryptOpt.publicKeys);
|
||||||
|
}).then(function (signatures) {
|
||||||
|
expect(+signatures[0].signature.packets[0].created).to.equal(+past);
|
||||||
|
expect(signatures[0].valid).to.be.true;
|
||||||
|
expect(encryptOpt.privateKeys[0].getSigningKeyPacket(signatures[0].keyid, undefined, past))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should sign, encrypt and decrypt, verify binary data with a date in the future', function () {
|
||||||
|
const future = new Date(2040, 5, 5, 5, 5, 5, 0);
|
||||||
|
const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]);
|
||||||
|
const encryptOpt = {
|
||||||
|
data,
|
||||||
|
publicKeys: publicKey_2038_2045.keys,
|
||||||
|
privateKeys: privateKey_2038_2045.keys,
|
||||||
|
creationDate: future,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
return encrypted.message.decrypt(encryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+future);
|
||||||
|
expect(packets.getLiteralData()).to.deep.equal(data);
|
||||||
|
return packets.verify(encryptOpt.publicKeys);
|
||||||
|
}).then(function (signatures) {
|
||||||
|
expect(+signatures[0].signature.packets[0].created).to.equal(+future);
|
||||||
|
expect(signatures[0].valid).to.be.true;
|
||||||
|
expect(encryptOpt.privateKeys[0].getSigningKeyPacket(signatures[0].keyid, undefined, future))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sign and verify cleartext data with a date in the past', function () {
|
||||||
|
const past = new Date(2005, 5, 5, 5, 5, 5, 0);
|
||||||
|
const signOpt = {
|
||||||
|
data: plaintext,
|
||||||
|
privateKeys: privateKey_2000_2008.keys,
|
||||||
|
detached: true,
|
||||||
|
creationDate: past,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const verifyOpt = {
|
||||||
|
publicKeys: publicKey_2000_2008.keys
|
||||||
|
};
|
||||||
|
return openpgp.sign(signOpt).then(function (signed) {
|
||||||
|
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
|
||||||
|
verifyOpt.signature = signed.signature;
|
||||||
|
return openpgp.verify(verifyOpt);
|
||||||
|
}).then(function (verified) {
|
||||||
|
expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past);
|
||||||
|
expect(verified.data).to.equal(plaintext);
|
||||||
|
expect(verified.signatures[0].valid).to.be.true;
|
||||||
|
expect(signOpt.privateKeys[0].getSigningKeyPacket(verified.signatures[0].keyid, undefined, past))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt and decrypt cleartext data with a date in the future', function () {
|
||||||
|
const future = new Date(2040, 5, 5, 5, 5, 5, 0);
|
||||||
|
const encryptOpt = {
|
||||||
|
data: plaintext,
|
||||||
|
publicKeys: publicKey_2038_2045.keys,
|
||||||
|
creationDate: future,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const decryptOpt = {
|
||||||
|
privateKeys: privateKey_2038_2045.keys
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
decryptOpt.message = encrypted.message;
|
||||||
|
return encrypted.message.decrypt(decryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+future);
|
||||||
|
expect(packets.getText()).to.equal(plaintext);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should encrypt and decrypt binary data with a date in the past', function () {
|
||||||
|
const past = new Date(2005, 5, 5, 5, 5, 5, 0);
|
||||||
|
const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]);
|
||||||
|
const encryptOpt = {
|
||||||
|
data,
|
||||||
|
publicKeys: publicKey_2000_2008.keys,
|
||||||
|
creationDate: past,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
const decryptOpt = {
|
||||||
|
privateKeys: privateKey_2000_2008.keys
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
decryptOpt.message = encrypted.message;
|
||||||
|
return encrypted.message.decrypt(decryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+past);
|
||||||
|
expect(packets.getLiteralData()).to.deep.equal(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sign, encrypt and decrypt, verify cleartext data with a date in the past', function () {
|
||||||
|
const past = new Date(2005, 5, 5, 5, 5, 5, 0);
|
||||||
|
const encryptOpt = {
|
||||||
|
data: plaintext,
|
||||||
|
publicKeys: publicKey_2000_2008.keys,
|
||||||
|
privateKeys: privateKey_2000_2008.keys,
|
||||||
|
creationDate: past,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
return encrypted.message.decrypt(encryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+past);
|
||||||
|
expect(packets.getText()).to.equal(plaintext);
|
||||||
|
return packets.verify(encryptOpt.publicKeys);
|
||||||
|
}).then(function (signatures) {
|
||||||
|
expect(+signatures[0].signature.packets[0].created).to.equal(+past);
|
||||||
|
expect(signatures[0].valid).to.be.true;
|
||||||
|
expect(encryptOpt.privateKeys[0].getSigningKeyPacket(signatures[0].keyid, undefined, past))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should sign, encrypt and decrypt, verify binary data with a date in the future', function () {
|
||||||
|
const future = new Date(2040, 5, 5, 5, 5, 5, 0);
|
||||||
|
const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]);
|
||||||
|
const encryptOpt = {
|
||||||
|
data,
|
||||||
|
publicKeys: publicKey_2038_2045.keys,
|
||||||
|
privateKeys: privateKey_2038_2045.keys,
|
||||||
|
creationDate: future,
|
||||||
|
armor: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return openpgp.encrypt(encryptOpt).then(function (encrypted) {
|
||||||
|
return encrypted.message.decrypt(encryptOpt.privateKeys);
|
||||||
|
}).then(function (packets) {
|
||||||
|
const literals = packets.packets.filterByTag(openpgp.enums.packet.literal);
|
||||||
|
expect(literals.length).to.equal(1);
|
||||||
|
expect(+literals[0].date).to.equal(+future);
|
||||||
|
expect(packets.getLiteralData()).to.deep.equal(data);
|
||||||
|
return packets.verify(encryptOpt.publicKeys);
|
||||||
|
}).then(function (signatures) {
|
||||||
|
expect(+signatures[0].signature.packets[0].created).to.equal(+future);
|
||||||
|
expect(signatures[0].valid).to.be.true;
|
||||||
|
expect(encryptOpt.privateKeys[0].getSigningKeyPacket(signatures[0].keyid, undefined, future))
|
||||||
|
.to.be.not.a('null');
|
||||||
|
expect(signatures[0].signature.packets.length).to.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ELG / DSA encrypt, decrypt, sign, verify', function() {
|
describe('ELG / DSA encrypt, decrypt, sign, verify', function() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user