Last little things become async ...

This commit is contained in:
Mahrud Sayrafi 2018-03-07 13:19:48 -08:00 committed by Sanjana Rajan
parent 47006069d1
commit 0b2817ba39
5 changed files with 304 additions and 339 deletions

View File

@ -188,13 +188,9 @@ Key.prototype.getKeyIds = function() {
* @returns {Array<string>} array of userids * @returns {Array<string>} array of userids
*/ */
Key.prototype.getUserIds = function() { Key.prototype.getUserIds = function() {
const userids = []; return this.users.map(user => {
for (let i = 0; i < this.users.length; i++) { return user.userId ? util.encode_utf8(user.userId.userid) : null;
if (this.users[i].userId) { }).filter(userid => userid !== null);
userids.push(util.Uint8Array_to_str(this.users[i].userId.write()));
}
}
return userids;
}; };
/** /**
@ -254,33 +250,34 @@ Key.prototype.armor = function() {
}; };
function isValidSigningKeyPacket(keyPacket, signature, date=new Date()) { function isValidSigningKeyPacket(keyPacket, signature, date=new Date()) {
const normDate = util.normalizeDate(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) &&
signature.verified && !signature.revoked && !signature.isExpired(normDate) && signature.verified && !signature.revoked && !signature.isExpired(date) &&
(normDate === null || (keyPacket.created <= normDate && normDate < getExpirationTime(keyPacket, signature, Infinity))); !isDataExpired(keyPacket, signature, date);
} }
/** /**
* Returns first key packet or key packet by given keyId that is available for signing and verification * Returns first key packet or key packet by given keyId that is available for signing and verification
*
* NOTE: call verifyKeyPackets before calling this function.
* @param {module:type/keyid} keyId, optional * @param {module:type/keyid} keyId, optional
* @param {Date} date use the given date for verification instead of the current time * @param {Date} date use the given date for verification instead of the current time
* @returns {(module:packet/secret_subkey| * @returns {(module:packet/secret_subkey|
module:packet/secret_key|null)} key packet or null if no signing key has been found module:packet/secret_key|null)} key packet or null if no signing key has been found
*/ */
Key.prototype.getSigningKeyPacket = function (keyId=null, date=new Date()) { Key.prototype.getSigningKeyPacket = async function (keyId=null, date=new Date()) {
const primaryUser = this.getPrimaryUser(date); const primaryKey = this.primaryKey;
if (primaryUser && (!keyId || this.primaryKey.getKeyId().equals(keyId)) && const primaryUser = await this.getPrimaryUser(date);
isValidSigningKeyPacket(this.primaryKey, primaryUser.selfCertificate, date)) { if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) &&
return this.primaryKey; isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, date) &&
await this.verifyPrimaryKey(date)) {
return primaryKey;
} }
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)) {
// eslint-disable-next-line no-await-in-loop
await this.subKeys[i].verify(primaryKey, date);
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], date)) { if (isValidSigningKeyPacket(this.subKeys[i].subKey, this.subKeys[i].bindingSignatures[j], date)) {
return this.subKeys[i].subKey; return this.subKeys[i].subKey;
@ -288,7 +285,6 @@ Key.prototype.getSigningKeyPacket = function (keyId=null, date=new Date()) {
} }
} }
} }
// TODO how to throw descriptive error?
return null; return null;
}; };
@ -301,14 +297,12 @@ function isValidEncryptionKeyPacket(keyPacket, signature, date=new Date()) {
(!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) &&
signature.verified && !signature.revoked && !signature.isExpired(normDate) && signature.verified && !signature.revoked && !signature.isExpired(date) &&
(normDate === null || (keyPacket.created <= normDate && normDate < getExpirationTime(keyPacket, signature, Infinity))); !isDataExpired(keyPacket, signature, date);
} }
/** /**
* 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
*
* NOTE: call verifyKeyPackets before calling this function.
* @param {module:type/keyid} keyId, optional * @param {module:type/keyid} keyId, optional
* @param {Date} date, optional * @param {Date} date, optional
* @returns {(module:packet/public_subkey| * @returns {(module:packet/public_subkey|
@ -316,11 +310,14 @@ function isValidEncryptionKeyPacket(keyPacket, signature, date=new Date()) {
* module:packet/secret_key| * module:packet/secret_key|
* module:packet/public_key|null)} key packet or null if no encryption key has been found * module:packet/public_key|null)} key packet or null if no encryption key has been found
*/ */
Key.prototype.getEncryptionKeyPacket = function(keyId, date=new Date()) { Key.prototype.getEncryptionKeyPacket = async function(keyId, date=new Date()) {
const primaryKey = this.primaryKey;
// 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
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)) {
// eslint-disable-next-line no-await-in-loop
await this.subKeys[i].verify(primaryKey, date);
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], date)) { if (isValidEncryptionKeyPacket(this.subKeys[i].subKey, this.subKeys[i].bindingSignatures[j], date)) {
return this.subKeys[i].subKey; return this.subKeys[i].subKey;
@ -329,12 +326,12 @@ Key.prototype.getEncryptionKeyPacket = function(keyId, date=new Date()) {
} }
} }
// if no valid subkey for encryption, evaluate primary key // if no valid subkey for encryption, evaluate primary key
const primaryUser = this.getPrimaryUser(date); const primaryUser = await this.getPrimaryUser(date);
if (primaryUser && (!keyId || this.primaryKey.getKeyId().equals(keyId)) && if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) &&
isValidEncryptionKeyPacket(this.primaryKey, primaryUser.selfCertificate, date)) { isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification, date) &&
return this.primaryKey; await this.verifyPrimaryKey(date)) {
return primaryKey;
} }
// TODO how to throw descriptive error?
return null; return null;
}; };
@ -423,37 +420,26 @@ Key.prototype.verifyKeyPackets = async function(keyId=null, date=new Date()) {
* @returns {Promise<module:enums.keyStatus>} The status of the primary key * @returns {Promise<module:enums.keyStatus>} The status of the primary key
*/ */
Key.prototype.verifyPrimaryKey = async function(date=new Date()) { Key.prototype.verifyPrimaryKey = async function(date=new Date()) {
const primaryKey = this.primaryKey;
// check for key revocation signatures // check for key revocation signatures
if (await this.isRevoked(null, null, date)) { if (await this.isRevoked(null, null, date)) {
return enums.keyStatus.revoked; return enums.keyStatus.revoked;
} }
const creationTime = this.primaryKey.created.getTime();
const currentTime = util.normalizeDate(date);
// check V3 expiration time
if (date !== null && this.primaryKey.version === 3) {
const expirationTimeV3 = creationTime + (this.primaryKey.expirationTimeV3*24*3600*1000 || Infinity);
if (!(creationTime <= currentTime && currentTime < expirationTimeV3)) {
return enums.keyStatus.expired;
}
}
// check for at least one self signature. Self signature of user ID not mandatory // check for at least one self signature. Self signature of user ID not mandatory
// See {@link https://tools.ietf.org/html/rfc4880#section-11.1} // See {@link https://tools.ietf.org/html/rfc4880#section-11.1}
if (!this.users.some(user => user.userId && user.selfCertifications.length)) { if (!this.users.some(user => user.userId && user.selfCertifications.length)) {
return enums.keyStatus.no_self_cert; return enums.keyStatus.no_self_cert;
} }
// check for valid self signature // check for valid, unrevoked, unexpired self signature
await this.verifyPrimaryUser(); const { user, selfCertification } = await this.getPrimaryUser(date);
const primaryUser = this.getPrimaryUser(date); if (!user) {
if (!primaryUser) {
return enums.keyStatus.invalid; return enums.keyStatus.invalid;
} }
// check V4 expiration time // check for expiration time
if (date !== null && this.primaryKey.version === 4) { const currentTime = util.normalizeDate(date);
const expirationTime = primaryUser.selfCertificate.keyNeverExpires === false ? if ((primaryKey.version === 3 && isDataExpired(primaryKey, null, date)) ||
creationTime + primaryUser.selfCertificate.keyExpirationTime*1000 : Infinity; (primaryKey.version === 4 && isDataExpired(primaryKey, selfCertification, date))) {
if (!(creationTime <= currentTime && currentTime < expirationTime)) { return enums.keyStatus.expired;
return enums.keyStatus.expired;
}
} }
return enums.keyStatus.valid; return enums.keyStatus.valid;
}; };
@ -462,64 +448,46 @@ Key.prototype.verifyPrimaryKey = async function(date=new Date()) {
* Returns the expiration time of the primary key or null if key does not expire * Returns the expiration time of the primary key or null if key does not expire
* @returns {Date|null} * @returns {Date|null}
*/ */
Key.prototype.getExpirationTime = function() { Key.prototype.getExpirationTime = async function() {
if (this.primaryKey.version === 3) { if (this.primaryKey.version === 3) {
return getExpirationTime(this.primaryKey); return getExpirationTime(this.primaryKey);
} }
if (this.primaryKey.version === 4) { if (this.primaryKey.version === 4) {
const primaryUser = this.getPrimaryUser(); const primaryUser = await this.getPrimaryUser();
if (!primaryUser) { if (!primaryUser) {
return null; return null;
} }
return getExpirationTime(this.primaryKey, primaryUser.selfCertificate); return getExpirationTime(this.primaryKey, primaryUser.selfCertification);
} }
}; };
function getExpirationTime(keyPacket, selfCertificate, defaultValue=null) {
// check V3 expiration time
if (keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0) {
return new Date(keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000);
}
// check V4 expiration time
if (keyPacket.version === 4 && selfCertificate.keyNeverExpires === false) {
return new Date(keyPacket.created.getTime() + selfCertificate.keyExpirationTime*1000);
}
return defaultValue;
}
/** /**
* Returns primary user and most significant (latest valid) self signature * Returns primary user and most significant (latest valid) self signature
* - if multiple primary users exist, returns the one with the latest self signature * - if multiple primary users exist, returns the one with the latest self signature
* - otherwise, returns the user with the latest self signature * - otherwise, returns the user with the latest self signature
*
* NOTE: call verifyPrimaryUser before calling this function.
* This is because getPrimaryUser isn't async, so it cannot validate and instead
* relies on already validated certificates.
* @param {Date} date use the given date for verification instead of the current time * @param {Date} date use the given date for verification instead of the current time
* @returns {{user: Array<module:packet/User>, selfCertificate: Array<module:packet/signature>}|null} The primary user and the self signature * @returns {{user: Array<module:packet/User>, selfCertification: Array<module:packet/signature>}|null} The primary user and the self signature
*/ */
Key.prototype.getPrimaryUser = function(date=new Date()) { Key.prototype.getPrimaryUser = async function(date=new Date()) {
// FIXME
await this.verifyPrimaryUser();
let primaryUsers = []; let primaryUsers = [];
for (let i = 0; i < this.users.length; i++) { this.users.forEach((user, i) => {
// here we only check the primary user ID, ignoring the primary user attribute if (!user.userId) {
if (!this.users[i].userId || !this.users[i].selfCertifications.length) { return;
continue;
} }
for (let j = 0; j < this.users[i].selfCertifications.length; j++) { user.selfCertifications.forEach(cert => {
// only consider already validated certificates // only consider already validated certificates
if (!this.users[i].selfCertifications[j].verified || if (!cert.verified || cert.revoked || cert.isExpired(date)) {
this.users[i].selfCertifications[j].revoked || return;
this.users[i].selfCertifications[j].isExpired(date)) {
continue;
} }
primaryUsers.push({ index: i, user: this.users[i], selfCertificate: this.users[i].selfCertifications[j] }); primaryUsers.push({ index: i, user: user, selfCertification: cert });
} });
} });
// sort by primary user flag and signature creation time // sort by primary user flag and signature creation time
primaryUsers = primaryUsers.sort(function(a, b) { primaryUsers = primaryUsers.sort(function(a, b) {
const A = a.selfCertificate; const A = a.selfCertification;
const B = b.selfCertificate; const B = b.selfCertification;
return (B.isPrimaryUserID - A.isPrimaryUserID) || (B.created - A.created); return (B.isPrimaryUserID - A.isPrimaryUserID) || (B.created - A.created);
}); });
return primaryUsers.pop(); return primaryUsers.pop();
@ -629,8 +597,7 @@ Key.prototype.revoke = function() {
* @returns {Promise<module:key~Key>} new public key with new certificate signature * @returns {Promise<module:key~Key>} new public key with new certificate signature
*/ */
Key.prototype.signPrimaryUser = async function(privateKeys) { Key.prototype.signPrimaryUser = async function(privateKeys) {
await this.verifyPrimaryUser(); const { index, user } = await this.getPrimaryUser() || {};
const { index, user } = this.getPrimaryUser() || {};
if (!user) { if (!user) {
throw new Error('Could not find primary user'); throw new Error('Could not find primary user');
} }
@ -668,34 +635,32 @@ Key.prototype.verifyPrimaryUser = async function(keys) {
let lastCreated = null; let lastCreated = null;
let lastPrimaryUserID = null; let lastPrimaryUserID = null;
await Promise.all(this.users.map(async function(user) { await Promise.all(this.users.map(async function(user) {
// here we verify both the primary user ID or the primary user attribute if (!user.userId && !user.userAttribute) {
if (!(user.userId || user.userAttribute) || !user.selfCertifications.length) {
return; return;
} }
const dataToVerify = { userid: user.userId || user.userAttribute, key: primaryKey }; const dataToVerify = { userid: user.userId || user.userAttribute, key: primaryKey };
// TODO replace when Promise.forEach is implemented // TODO replace when Promise.forEach is implemented
for (let i = 0; i < user.selfCertifications.length; i++) { for (let i = 0; i < user.selfCertifications.length; i++) {
const selfCertification = user.selfCertifications[i]; const cert = user.selfCertifications[i];
// skip if certificate is not the most recent // skip if certificate is not the most recent
if ((selfCertification.isPrimaryUserID && if ((cert.isPrimaryUserID && cert.isPrimaryUserID < lastPrimaryUserID) ||
selfCertification.isPrimaryUserID < lastPrimaryUserID) || (!lastPrimaryUserID && cert.created < lastCreated)) {
(!lastPrimaryUserID && selfCertification.created < lastCreated)) {
return; return;
} }
// skip if certificates is invalid, revoked, or expired // skip if certificates is invalid, revoked, or expired
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
if (!(selfCertification.verified || await selfCertification.verify(primaryKey, dataToVerify))) { if (!(cert.verified || await cert.verify(primaryKey, dataToVerify))) {
return; return;
} }
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
if (selfCertification.revoked || await user.isRevoked(primaryKey, selfCertification)) { if (cert.revoked || await user.isRevoked(primaryKey, cert)) {
return; return;
} }
if (selfCertification.isExpired()) { if (cert.isExpired()) {
return; return;
} }
lastPrimaryUserID = selfCertification.isPrimaryUserID; lastPrimaryUserID = cert.isPrimaryUserID;
lastCreated = selfCertification.created; lastCreated = cert.created;
primaryUsers.push(user); primaryUsers.push(user);
} }
})); }));
@ -776,11 +741,10 @@ User.prototype.sign = async function(primaryKey, privateKeys) {
if (privateKey.primaryKey.getFingerprint() === primaryKey.getFingerprint()) { if (privateKey.primaryKey.getFingerprint() === primaryKey.getFingerprint()) {
throw new Error('Not implemented for self signing'); throw new Error('Not implemented for self signing');
} }
await privateKey.verifyKeyPackets(); const signingKeyPacket = await privateKey.getSigningKeyPacket();
const signingKeyPacket = privateKey.getSigningKeyPacket();
if (!signingKeyPacket) { if (!signingKeyPacket) {
throw new Error(`Could not find valid signing key packet in key ${ throw new Error('Could not find valid signing key packet in key ' +
privateKey.primaryKey.getKeyId().toHex()}`); 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.');
@ -790,7 +754,7 @@ User.prototype.sign = async function(primaryKey, privateKeys) {
signaturePacket.signatureType = enums.write(enums.signature, enums.signature.cert_generic); signaturePacket.signatureType = enums.write(enums.signature, enums.signature.cert_generic);
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey); signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey);
signaturePacket.signingKeyId = signingKeyPacket.getKeyId(); signaturePacket.signingKeyId = signingKeyPacket.getKeyId();
signaturePacket.sign(signingKeyPacket, dataToSign); signaturePacket.sign(signingKeyPacket, dataToSign);
return signaturePacket; return signaturePacket;
@ -835,8 +799,7 @@ User.prototype.verifyCertificate = async function(primaryKey, certificate, keys,
const dataToVerify = { userid: this.userId || this.userAttribute, key: primaryKey }; const dataToVerify = { userid: this.userId || this.userAttribute, key: primaryKey };
const results = await Promise.all(keys.map(async function(key) { const results = await Promise.all(keys.map(async function(key) {
if (!key.getKeyIds().some(id => id.equals(keyid))) { return; } if (!key.getKeyIds().some(id => id.equals(keyid))) { return; }
await key.verifyKeyPackets(); const keyPacket = await key.getSigningKeyPacket(keyid, date);
const keyPacket = key.getSigningKeyPacket(keyid, date);
if (certificate.revoked || await that.isRevoked(primaryKey, certificate, keyPacket)) { if (certificate.revoked || await that.isRevoked(primaryKey, certificate, keyPacket)) {
return enums.keyStatus.revoked; return enums.keyStatus.revoked;
} }
@ -979,17 +942,12 @@ SubKey.prototype.isRevoked = async function(primaryKey, signature, key, date=new
SubKey.prototype.verify = async function(primaryKey, date=new Date()) { SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
const that = this; const that = this;
const dataToVerify = { key: primaryKey, bind: this.subKey }; const dataToVerify = { key: primaryKey, bind: this.subKey };
const creationTime = this.subKey.created.getTime(); // check for V3 expiration time
const currentTime = util.normalizeDate(date); if (this.subKey.version === 3 && isDataExpired(this.subKey, null, date)) {
// check V3 expiration time return enums.keyStatus.expired;
if (currentTime !== null && this.subKey.version === 3) {
const expirationTime = creationTime + (this.subKey.expirationTimeV3*24*3600*1000 || Infinity);
if (!(creationTime <= currentTime && currentTime < expirationTime)) {
return enums.keyStatus.expired;
}
} }
// check subkey binding signatures (at least one valid binding sig needed) // check subkey binding signatures
// TODO replace when Promise.some or Promise.any are implemented // note: binding signatures can have different keyFlags, so we verify all.
const results = [enums.keyStatus.invalid].concat( const results = [enums.keyStatus.invalid].concat(
await Promise.all(this.bindingSignatures.map(async function(bindingSignature) { await Promise.all(this.bindingSignatures.map(async function(bindingSignature) {
// check binding signature is verified // check binding signature is verified
@ -1000,18 +958,10 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
if (bindingSignature.revoked || await that.isRevoked(primaryKey, bindingSignature, null, date)) { if (bindingSignature.revoked || await that.isRevoked(primaryKey, bindingSignature, null, date)) {
return enums.keyStatus.revoked; return enums.keyStatus.revoked;
} }
// check binding signature is not expired // check binding signature is not expired (ie, check for V4 expiration time)
if (bindingSignature.isExpired(date)) { if (bindingSignature.isExpired(date)) {
return enums.keyStatus.expired; return enums.keyStatus.expired;
} }
// check V4 expiration time
if (that.subKey.version === 4 && currentTime !== null) {
const expirationTime = bindingSignature.keyNeverExpires === false ?
(creationTime + bindingSignature.keyExpirationTime*1000) : Infinity;
if (!(creationTime <= currentTime && currentTime < expirationTime)) {
return enums.keyStatus.expired; // last V4 expired binding signature
}
}
return enums.keyStatus.valid; // found a binding signature that passed all checks return enums.keyStatus.valid; // found a binding signature that passed all checks
})) }))
); );
@ -1284,7 +1234,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
const signaturePacket = new packet.Signature(); const signaturePacket = new packet.Signature();
signaturePacket.signatureType = enums.signature.cert_generic; signaturePacket.signatureType = enums.signature.cert_generic;
signaturePacket.publicKeyAlgorithm = options.keyType; signaturePacket.publicKeyAlgorithm = options.keyType;
signaturePacket.hashAlgorithm = getPreferredHashAlgo(secretKeyPacket); signaturePacket.hashAlgorithm = await getPreferredHashAlgo(secretKeyPacket);
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.preferredSymmetricAlgorithms = []; signaturePacket.preferredSymmetricAlgorithms = [];
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
@ -1329,7 +1279,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
const subkeySignaturePacket = new packet.Signature(); const subkeySignaturePacket = new packet.Signature();
subkeySignaturePacket.signatureType = enums.signature.subkey_binding; subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
subkeySignaturePacket.publicKeyAlgorithm = options.keyType; subkeySignaturePacket.publicKeyAlgorithm = options.keyType;
subkeySignaturePacket.hashAlgorithm = getPreferredHashAlgo(secretSubkeyPacket); subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo(secretSubkeyPacket);
subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage]; subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
if (options.keyExpirationTime > 0) { if (options.keyExpirationTime > 0) {
subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime;
@ -1387,18 +1337,41 @@ async function isDataRevoked(primaryKey, dataToVerify, revocations, signature, k
return revocationKeyIds.length > 0; return revocationKeyIds.length > 0;
} }
function isDataExpired(keyPacket, signature, date=new Date()) {
const normDate = util.normalizeDate(date);
if (normDate !== null) {
const expirationTime = getExpirationTime(keyPacket, signature);
return !(keyPacket.created <= normDate && normDate < expirationTime) ||
(signature && signature.isExpired(date));
}
return false;
}
function getExpirationTime(keyPacket, signature) {
let expirationTime;
// check V3 expiration time
if (keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0) {
expirationTime = keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000;
}
// check V4 expiration time
if (keyPacket.version === 4 && signature.keyNeverExpires === false) {
expirationTime = signature.created.getTime() + signature.keyExpirationTime*1000;
}
return expirationTime ? new Date(expirationTime) : Infinity;
}
/** /**
* Returns the preferred signature hash algorithm of a key * Returns the preferred signature hash algorithm of a key
* @param {object} key * @param {object} key
* @returns {String} * @returns {String}
*/ */
export function getPreferredHashAlgo(key) { export async function getPreferredHashAlgo(key) {
let hash_algo = config.prefer_hash_algorithm; let hash_algo = config.prefer_hash_algorithm;
let pref_algo = hash_algo; let pref_algo = hash_algo;
if (key instanceof Key) { if (key instanceof Key) {
const primaryUser = key.getPrimaryUser(); const primaryUser = await key.getPrimaryUser();
if (primaryUser && primaryUser.selfCertificate.preferredHashAlgorithms) { if (primaryUser && primaryUser.selfCertification.preferredHashAlgorithms) {
[pref_algo] = primaryUser.selfCertificate.preferredHashAlgorithms; [pref_algo] = primaryUser.selfCertification.preferredHashAlgorithms;
hash_algo = crypto.hash.getHashByteLength(hash_algo) <= crypto.hash.getHashByteLength(pref_algo) ? hash_algo = crypto.hash.getHashByteLength(hash_algo) <= crypto.hash.getHashByteLength(pref_algo) ?
pref_algo : hash_algo; pref_algo : hash_algo;
} }
@ -1426,19 +1399,19 @@ export function getPreferredHashAlgo(key) {
* @param {Array<module:key~Key>} keys Set of keys * @param {Array<module:key~Key>} keys Set of keys
* @returns {enums.symmetric} Preferred symmetric algorithm * @returns {enums.symmetric} Preferred symmetric algorithm
*/ */
export function getPreferredSymAlgo(keys) { export async function getPreferredSymAlgo(keys) {
const prioMap = {}; const prioMap = {};
keys.forEach(function(key) { await Promise.all(keys.map(async function(key) {
const primaryUser = key.getPrimaryUser(); const primaryUser = await key.getPrimaryUser();
if (!primaryUser || !primaryUser.selfCertificate.preferredSymmetricAlgorithms) { if (!primaryUser || !primaryUser.selfCertification.preferredSymmetricAlgorithms) {
return config.encryption_cipher; return config.encryption_cipher;
} }
primaryUser.selfCertificate.preferredSymmetricAlgorithms.forEach(function(algo, index) { primaryUser.selfCertification.preferredSymmetricAlgorithms.forEach(function(algo, index) {
const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo }); const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo });
entry.prio += 64 >> index; entry.prio += 64 >> index;
entry.count++; entry.count++;
}); });
}); }));
let prefAlgo = { prio: 0, algo: config.encryption_cipher }; let prefAlgo = { prio: 0, algo: config.encryption_cipher };
for (const algo in prioMap) { for (const algo in prioMap) {
try { try {

View File

@ -253,7 +253,7 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
symAlgo = sessionKey.algorithm; symAlgo = sessionKey.algorithm;
sessionKey = sessionKey.data; sessionKey = sessionKey.data;
} else if (keys && keys.length) { } else if (keys && keys.length) {
symAlgo = enums.read(enums.symmetric, getPreferredSymAlgo(keys)); symAlgo = enums.read(enums.symmetric, await getPreferredSymAlgo(keys));
} else if (passwords && passwords.length) { } else if (passwords && passwords.length) {
symAlgo = enums.read(enums.symmetric, config.encryption_cipher); symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
} else { } else {
@ -303,8 +303,7 @@ export async function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwor
if (publicKeys) { if (publicKeys) {
const results = await Promise.all(publicKeys.map(async function(publicKey) { const results = await Promise.all(publicKeys.map(async function(publicKey) {
await publicKey.verifyKeyPackets(undefined, date); const encryptionKeyPacket = await publicKey.getEncryptionKeyPacket(undefined, date);
const encryptionKeyPacket = publicKey.getEncryptionKeyPacket(undefined, date);
if (!encryptionKeyPacket) { if (!encryptionKeyPacket) {
throw new Error('Could not find valid key packet for encryption in key ' + throw new Error('Could not find valid key packet for encryption in key ' +
publicKey.primaryKey.getKeyId().toHex()); publicKey.primaryKey.getKeyId().toHex());
@ -397,15 +396,14 @@ Message.prototype.sign = async function(privateKeys=[], signature=null, date=new
if (privateKey.isPublic()) { if (privateKey.isPublic()) {
throw new Error('Need private key for signing'); throw new Error('Need private key for signing');
} }
await privateKey.verifyKeyPackets(undefined, date); const signingKeyPacket = await privateKey.getSigningKeyPacket(undefined, date);
const signingKeyPacket = privateKey.getSigningKeyPacket(undefined, date);
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());
} }
const onePassSig = new packet.OnePassSignature(); const onePassSig = new packet.OnePassSignature();
onePassSig.type = signatureType; onePassSig.type = signatureType;
onePassSig.hashAlgorithm = getPreferredHashAlgo(privateKey); onePassSig.hashAlgorithm = await getPreferredHashAlgo(privateKey);
onePassSig.publicKeyAlgorithm = signingKeyPacket.algorithm; onePassSig.publicKeyAlgorithm = signingKeyPacket.algorithm;
onePassSig.signingKeyId = signingKeyPacket.getKeyId(); onePassSig.signingKeyId = signingKeyPacket.getKeyId();
if (i === privateKeys.length - 1) { if (i === privateKeys.length - 1) {
@ -476,8 +474,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');
} }
await privateKey.verifyKeyPackets(undefined, date); const signingKeyPacket = await privateKey.getSigningKeyPacket(undefined, date);
const signingKeyPacket = privateKey.getSigningKeyPacket(undefined, date);
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());
@ -488,7 +485,7 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig
const signaturePacket = new packet.Signature(date); const signaturePacket = new packet.Signature(date);
signaturePacket.signatureType = signatureType; signaturePacket.signatureType = signatureType;
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey); signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey);
await signaturePacket.sign(signingKeyPacket, literalDataPacket); await signaturePacket.sign(signingKeyPacket, literalDataPacket);
return signaturePacket; return signaturePacket;
})).then(signatureList => { })).then(signatureList => {
@ -550,8 +547,7 @@ export async function createVerificationObjects(signatureList, literalDataList,
let keyPacket = null; let keyPacket = null;
await Promise.all(keys.map(async function(key) { await Promise.all(keys.map(async function(key) {
// Look for the unique key packet that matches issuerKeyId of signature // Look for the unique key packet that matches issuerKeyId of signature
await key.verifyKeyPackets(signature.issuerKeyId, date); const result = await key.getSigningKeyPacket(signature.issuerKeyId, date);
const result = key.getSigningKeyPacket(signature.issuerKeyId, date);
if (result) { if (result) {
keyPacket = result; keyPacket = result;
} }

View File

@ -667,9 +667,9 @@ Signature.prototype.verify = async function (key, data) {
* @return {Boolean} true if expired * @return {Boolean} true if expired
*/ */
Signature.prototype.isExpired = function (date=new Date()) { Signature.prototype.isExpired = function (date=new Date()) {
if (date !== null) { const normDate = util.normalizeDate(date);
if (normDate !== null) {
const expirationTime = !this.signatureNeverExpires ? this.created.getTime() + this.signatureExpirationTime*1000 : Infinity; const expirationTime = !this.signatureNeverExpires ? this.created.getTime() + this.signatureExpirationTime*1000 : Infinity;
const normDate = util.normalizeDate(date);
return !(this.created <= normDate && normDate < expirationTime); return !(this.created <= normDate && normDate < expirationTime);
} }
return false; return false;

View File

@ -761,7 +761,7 @@ describe('Key', function() {
)).to.eventually.equal(openpgp.enums.keyStatus.revoked).notify(done); )).to.eventually.equal(openpgp.enums.keyStatus.revoked).notify(done);
}); });
it('Evaluate key flags to find valid encryption key packet', function() { it('Evaluate key flags to find valid encryption key packet', async function() {
const pubKeys = openpgp.key.readArmored(pub_sig_test); const pubKeys = openpgp.key.readArmored(pub_sig_test);
expect(pubKeys).to.exist; expect(pubKeys).to.exist;
expect(pubKeys.err).to.not.exist; expect(pubKeys.err).to.not.exist;
@ -771,24 +771,25 @@ describe('Key', function() {
// remove subkeys // remove subkeys
pubKey.subKeys = []; pubKey.subKeys = [];
// primary key has only key flags for signing // primary key has only key flags for signing
const keyPacket = pubKey.getEncryptionKeyPacket(); await pubKey.verifyKeyPackets();
const keyPacket = await pubKey.getEncryptionKeyPacket();
expect(keyPacket).to.not.exist; expect(keyPacket).to.not.exist;
}); });
it('Method getExpirationTime V4 Key', function() { it('Method getExpirationTime V4 Key', async function() {
const pubKey = openpgp.key.readArmored(twoKeys).keys[1]; const pubKey = openpgp.key.readArmored(twoKeys).keys[1];
expect(pubKey).to.exist; expect(pubKey).to.exist;
expect(pubKey).to.be.an.instanceof(openpgp.key.Key); expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
return pubKey.verifyPrimaryUser().then(() => { const expirationTime = await pubKey.getExpirationTime();
expect(pubKey.getExpirationTime().toISOString()).to.be.equal('2018-11-26T10:58:29.000Z'); expect(expirationTime.toISOString()).to.be.equal('2018-11-26T10:58:29.000Z');
});
}); });
it('Method getExpirationTime V4 SubKey', function() { it('Method getExpirationTime V4 SubKey', async function() {
const pubKey = openpgp.key.readArmored(twoKeys).keys[1]; const pubKey = openpgp.key.readArmored(twoKeys).keys[1];
expect(pubKey).to.exist; expect(pubKey).to.exist;
expect(pubKey).to.be.an.instanceof(openpgp.key.Key); expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
expect(pubKey.subKeys[0].getExpirationTime().toISOString()).to.be.equal('2018-11-26T10:58:29.000Z'); const expirationTime = await pubKey.subKeys[0].getExpirationTime();
expect(expirationTime.toISOString()).to.be.equal('2018-11-26T10:58:29.000Z');
}); });
it('update() - throw error if fingerprints not equal', function(done) { it('update() - throw error if fingerprints not equal', function(done) {
@ -926,34 +927,30 @@ describe('Key', function() {
}); });
}); });
it('getPreferredSymAlgo() - one key - AES256', function() { it('getPreferredSymAlgo() - one key - AES256', async function() {
const key1 = openpgp.key.readArmored(twoKeys).keys[0]; const key1 = openpgp.key.readArmored(twoKeys).keys[0];
return key1.verifyPrimaryUser().then(() => { const prefAlgo = await openpgp.key.getPreferredSymAlgo([key1]);
const prefAlgo = openpgp.key.getPreferredSymAlgo([key1]); expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
});
}); });
it('getPreferredSymAlgo() - two key - AES128', function() { it('getPreferredSymAlgo() - two key - AES128', async function() {
const keys = openpgp.key.readArmored(twoKeys).keys; const keys = openpgp.key.readArmored(twoKeys).keys;
const key1 = keys[0]; const key1 = keys[0];
const key2 = keys[1]; const key2 = keys[1];
return Promise.all([key1.verifyPrimaryUser(), key2.verifyPrimaryUser()]).then(() => { const primaryUser = await key2.getPrimaryUser();
key2.getPrimaryUser().selfCertificate.preferredSymmetricAlgorithms = [6,7,3]; primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,7,3];
const prefAlgo = openpgp.key.getPreferredSymAlgo([key1, key2]); const prefAlgo = await openpgp.key.getPreferredSymAlgo([key1, key2]);
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128); expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
});
}); });
it('getPreferredSymAlgo() - two key - one without pref', function() { it('getPreferredSymAlgo() - two key - one without pref', async function() {
const keys = openpgp.key.readArmored(twoKeys).keys; const keys = openpgp.key.readArmored(twoKeys).keys;
const key1 = keys[0]; const key1 = keys[0];
const key2 = keys[1]; const key2 = keys[1];
return Promise.all([key1.verifyPrimaryUser(), key2.verifyPrimaryUser()]).then(() => { const primaryUser = await key2.getPrimaryUser();
key2.getPrimaryUser().selfCertificate.preferredSymmetricAlgorithms = null; primaryUser.selfCertification.preferredSymmetricAlgorithms = null;
const prefAlgo = openpgp.key.getPreferredSymAlgo([key1, key2]); const prefAlgo = await openpgp.key.getPreferredSymAlgo([key1, key2]);
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher); expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
});
}); });
it('Preferences of generated key', function() { it('Preferences of generated key', function() {
@ -986,14 +983,12 @@ describe('Key', function() {
expect(key.users[1].userAttribute).eql(key2.users[1].userAttribute); expect(key.users[1].userAttribute).eql(key2.users[1].userAttribute);
}); });
it('getPrimaryUser()', function() { it('getPrimaryUser()', async function() {
const key = openpgp.key.readArmored(pub_sig_test).keys[0]; const key = openpgp.key.readArmored(pub_sig_test).keys[0];
return key.verifyPrimaryUser().then(() => { const primUser = await key.getPrimaryUser();
const primUser = key.getPrimaryUser(); expect(primUser).to.exist;
expect(primUser).to.exist; expect(primUser.user.userId.userid).to.equal('Signature Test <signature@test.com>');
expect(primUser.user.userId.userid).to.equal('Signature Test <signature@test.com>'); expect(primUser.selfCertification).to.be.an.instanceof(openpgp.packet.Signature);
expect(primUser.selfCertificate).to.be.an.instanceof(openpgp.packet.Signature);
});
}); });
it('Generated key is not unlocked by default', function() { it('Generated key is not unlocked by default', function() {
@ -1001,10 +996,10 @@ describe('Key', function() {
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
let key; let key;
return openpgp.generateKey(opt).then(function(newKey) { return openpgp.generateKey(opt).then(function(newKey) {
key = newKey; key = newKey.key;
return openpgp.message.fromText('hello').encrypt([key.key]); return openpgp.message.fromText('hello').encrypt([key]);
}).then(function(msg) { }).then(function(msg) {
return msg.message.decrypt([key.key]); return msg.message.decrypt([key]);
}).catch(function(err) { }).catch(function(err) {
expect(err.message).to.equal('Private key is not decrypted.'); expect(err.message).to.equal('Private key is not decrypted.');
}); });
@ -1061,113 +1056,99 @@ describe('Key', function() {
const userId = 'test <a@b.com>'; const userId = 'test <a@b.com>';
const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta}; const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
return openpgp.generateKey(opt).then(function(key) { return openpgp.generateKey(opt).then(async function(key) {
key = key.key; key = key.key;
return key.verifyPrimaryUser().then(() => { const expiration = await key.getExpirationTime();
const expiration = key.getExpirationTime(); expect(expiration).to.exist;
expect(expiration).to.exist;
const actual_delta = (new Date(expiration) - new Date()) / 1000; const actual_delta = (new Date(expiration) - new Date()) / 1000;
expect(Math.abs(actual_delta - expect_delta)).to.be.below(60); expect(Math.abs(actual_delta - expect_delta)).to.be.below(60);
const subKeyExpiration = key.subKeys[0].getExpirationTime(); const subKeyExpiration = await key.subKeys[0].getExpirationTime();
expect(subKeyExpiration).to.exist; expect(subKeyExpiration).to.exist;
const actual_subKeyDelta = (new Date(subKeyExpiration) - new Date()) / 1000; const actual_subKeyDelta = (new Date(subKeyExpiration) - new Date()) / 1000;
expect(Math.abs(actual_subKeyDelta - expect_delta)).to.be.below(60); expect(Math.abs(actual_subKeyDelta - expect_delta)).to.be.below(60);
});
}); });
}); });
it('Sign and verify key - primary user', function() { it('Sign and verify key - primary user', async function() {
const key = openpgp.key.readArmored(pub_sig_test).keys[0]; let publicKey = openpgp.key.readArmored(pub_sig_test).keys[0];
const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0]; const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0];
privateKey.decrypt('hello world'); await privateKey.decrypt('hello world');
return key.signPrimaryUser([privateKey]).then(key => { publicKey = await publicKey.signPrimaryUser([privateKey]);
return Promise.all( const signatures = await publicKey.verifyPrimaryUser([privateKey]);
[key.verifyPrimaryUser([privateKey]), privateKey.verifyPrimaryUser()] const publicKeyPacket = await publicKey.getSigningKeyPacket();
).then(results => { const privateKeyPacket = await privateKey.getSigningKeyPacket();
const signatures = results[0]; expect(signatures.length).to.equal(2);
expect(signatures.length).to.equal(2); expect(signatures[0].keyid.toHex()).to.equal(publicKeyPacket.getKeyId().toHex());
expect(signatures[0].keyid.toHex()).to.equal(key.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[0].valid).to.be.null;
expect(signatures[0].valid).to.be.null; expect(signatures[1].keyid.toHex()).to.equal(privateKeyPacket.getKeyId().toHex());
expect(signatures[1].keyid.toHex()).to.equal(privateKey.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[1].valid).to.be.true;
expect(signatures[1].valid).to.be.true;
});
});
}); });
it('Sign key and verify with wrong key - primary user', function() { it('Sign key and verify with wrong key - primary user', async function() {
const key = openpgp.key.readArmored(pub_sig_test).keys[0]; let publicKey = openpgp.key.readArmored(pub_sig_test).keys[0];
const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0]; const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0];
const wrongKey = openpgp.key.readArmored(wrong_key).keys[0]; const wrongKey = openpgp.key.readArmored(wrong_key).keys[0];
privateKey.decrypt('hello world'); await privateKey.decrypt('hello world');
return key.signPrimaryUser([privateKey]).then(key => { publicKey = await publicKey.signPrimaryUser([privateKey]);
return Promise.all( const signatures = await publicKey.verifyPrimaryUser([wrongKey]);
[key.verifyPrimaryUser([wrongKey]), privateKey.verifyPrimaryUser()] const publicKeyPacket = await publicKey.getSigningKeyPacket();
).then(results => { const privateKeyPacket = await privateKey.getSigningKeyPacket();
const signatures = results[0]; expect(signatures.length).to.equal(2);
expect(signatures.length).to.equal(2); expect(signatures[0].keyid.toHex()).to.equal(publicKeyPacket.getKeyId().toHex());
expect(signatures[0].keyid.toHex()).to.equal(key.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[0].valid).to.be.null;
expect(signatures[0].valid).to.be.null; expect(signatures[1].keyid.toHex()).to.equal(privateKeyPacket.getKeyId().toHex());
expect(signatures[1].keyid.toHex()).to.equal(privateKey.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[1].valid).to.be.null;
expect(signatures[1].valid).to.be.null;
});
});
}); });
it('Sign and verify key - all users', function() { it('Sign and verify key - all users', async function() {
const key = openpgp.key.readArmored(multi_uid_key).keys[0]; let publicKey = openpgp.key.readArmored(multi_uid_key).keys[0];
const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0]; const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0];
privateKey.decrypt('hello world'); await privateKey.decrypt('hello world');
return key.signAllUsers([privateKey]).then(key => { publicKey = await publicKey.signAllUsers([privateKey]);
return Promise.all( const signatures = await publicKey.verifyAllUsers([privateKey]);
[key.verifyAllUsers([privateKey]), key.verifyPrimaryUser(), privateKey.verifyPrimaryUser()] const publicKeyPacket = await publicKey.getSigningKeyPacket();
).then(results => { const privateKeyPacket = await privateKey.getSigningKeyPacket();
const signatures = results[0]; expect(signatures.length).to.equal(4);
expect(signatures.length).to.equal(4); expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid);
expect(signatures[0].userid).to.equal(key.users[0].userId.userid); expect(signatures[0].keyid.toHex()).to.equal(publicKeyPacket.getKeyId().toHex());
expect(signatures[0].keyid.toHex()).to.equal(key.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[0].valid).to.be.null;
expect(signatures[0].valid).to.be.null; expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid);
expect(signatures[1].userid).to.equal(key.users[0].userId.userid); expect(signatures[1].keyid.toHex()).to.equal(privateKeyPacket.getKeyId().toHex());
expect(signatures[1].keyid.toHex()).to.equal(privateKey.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[1].valid).to.be.true;
expect(signatures[1].valid).to.be.true; expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid);
expect(signatures[2].userid).to.equal(key.users[1].userId.userid); expect(signatures[2].keyid.toHex()).to.equal(publicKeyPacket.getKeyId().toHex());
expect(signatures[2].keyid.toHex()).to.equal(key.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[2].valid).to.be.null;
expect(signatures[2].valid).to.be.null; expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid);
expect(signatures[3].userid).to.equal(key.users[1].userId.userid); expect(signatures[3].keyid.toHex()).to.equal(privateKeyPacket.getKeyId().toHex());
expect(signatures[3].keyid.toHex()).to.equal(privateKey.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[3].valid).to.be.true;
expect(signatures[3].valid).to.be.true;
});
});
}); });
it('Sign key and verify with wrong key - all users', function() { it('Sign key and verify with wrong key - all users', async function() {
const key = openpgp.key.readArmored(multi_uid_key).keys[0]; let publicKey = openpgp.key.readArmored(multi_uid_key).keys[0];
const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0]; const privateKey = openpgp.key.readArmored(priv_key_rsa).keys[0];
const wrongKey = openpgp.key.readArmored(wrong_key).keys[0]; const wrongKey = openpgp.key.readArmored(wrong_key).keys[0];
privateKey.decrypt('hello world'); await privateKey.decrypt('hello world');
return key.signAllUsers([privateKey]).then(key => { publicKey = await publicKey.signAllUsers([privateKey]);
return Promise.all( const signatures = await publicKey.verifyAllUsers([wrongKey]);
[key.verifyAllUsers([wrongKey]), key.verifyPrimaryUser(), privateKey.verifyPrimaryUser()] const publicKeyPacket = await publicKey.getSigningKeyPacket();
).then(results => { const privateKeyPacket = await privateKey.getSigningKeyPacket()
const signatures = results[0]; expect(signatures.length).to.equal(4);
expect(signatures.length).to.equal(4); expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid);
expect(signatures[0].userid).to.equal(key.users[0].userId.userid); expect(signatures[0].keyid.toHex()).to.equal(publicKeyPacket.getKeyId().toHex());
expect(signatures[0].keyid.toHex()).to.equal(key.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[0].valid).to.be.null;
expect(signatures[0].valid).to.be.null; expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid);
expect(signatures[1].userid).to.equal(key.users[0].userId.userid); expect(signatures[1].keyid.toHex()).to.equal(privateKeyPacket.getKeyId().toHex());
expect(signatures[1].keyid.toHex()).to.equal(privateKey.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[1].valid).to.be.null;
expect(signatures[1].valid).to.be.null; expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid);
expect(signatures[2].userid).to.equal(key.users[1].userId.userid); expect(signatures[2].keyid.toHex()).to.equal(publicKeyPacket.getKeyId().toHex());
expect(signatures[2].keyid.toHex()).to.equal(key.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[2].valid).to.be.null;
expect(signatures[2].valid).to.be.null; expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid);
expect(signatures[3].userid).to.equal(key.users[1].userId.userid); expect(signatures[3].keyid.toHex()).to.equal(privateKeyPacket.getKeyId().toHex());
expect(signatures[3].keyid.toHex()).to.equal(privateKey.getSigningKeyPacket().getKeyId().toHex()); expect(signatures[3].valid).to.be.null;
expect(signatures[3].valid).to.be.null;
});
});
}); });
it('Reformat key without passphrase', function() { it('Reformat key without passphrase', function() {
@ -1213,9 +1194,12 @@ describe('Key', function() {
expect(newKey.users[0].userId.userid).to.equal(userId); expect(newKey.users[0].userId.userid).to.equal(userId);
expect(newKey.primaryKey.isDecrypted).to.be.true; expect(newKey.primaryKey.isDecrypted).to.be.true;
return openpgp.sign({data: 'hello', privateKeys: newKey, armor: true}).then(function(signed) { return openpgp.sign({data: 'hello', privateKeys: newKey, armor: true}).then(function(signed) {
return openpgp.verify({message: openpgp.cleartext.readArmored(signed.data), publicKeys: newKey.toPublic()}).then(function(verified) { return openpgp.verify(
{message: openpgp.cleartext.readArmored(signed.data), publicKeys: newKey.toPublic()}
).then(async function(verified) {
expect(verified.signatures[0].valid).to.be.true; expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(newKey.getSigningKeyPacket().getKeyId().toHex()); const newKeyPacket = await newKey.getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(newKeyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1277,11 +1261,10 @@ describe('Key', function() {
}); });
}); });
it('Find a valid subkey binding signature among many invalid ones', function() { it('Find a valid subkey binding signature among many invalid ones', async function() {
const k = openpgp.key.readArmored(valid_binding_sig_among_many_expired_sigs_pub).keys[0]; const key = openpgp.key.readArmored(valid_binding_sig_among_many_expired_sigs_pub).keys[0];
return k.verifyKeyPackets().then(() => { await key.verifyKeyPackets();
expect(k.getEncryptionKeyPacket()).to.not.be.null; expect(await key.getEncryptionKeyPacket()).to.not.be.null;
})
}); });
it('Reject encryption with revoked subkey', function() { it('Reject encryption with revoked subkey', function() {

View File

@ -626,7 +626,7 @@ describe('OpenPGP.js public api tests', function() {
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;
privateKey.keys[0].verifyPrimaryUser().then(() => done()); done();
}); });
afterEach(function() { afterEach(function() {
@ -729,7 +729,6 @@ describe('OpenPGP.js public api tests', function() {
beforeEach(async function() { beforeEach(async function() {
expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true; expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true;
await privateKey.keys[0].verifyPrimaryUser();
return true; return true;
}); });
@ -868,12 +867,8 @@ describe('OpenPGP.js public api tests', function() {
'=6XMW\r\n' + '=6XMW\r\n' +
'-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n'; '-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n';
beforeEach( async function () { beforeEach(async function () {
expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true; expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true;
await privateKey.keys[0].verifyPrimaryUser();
await privateKey_2000_2008.keys[0].verifyPrimaryUser();
await privateKey_1337.keys[0].verifyPrimaryUser();
await privateKey_2038_2045.keys[0].verifyPrimaryUser();
return true; return true;
}); });
@ -1039,10 +1034,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function (encrypted) { return openpgp.encrypt(encOpt).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1060,10 +1056,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function (encrypted) { return openpgp.encrypt(encOpt).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(''); expect(decrypted.data).to.equal('');
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1083,10 +1080,11 @@ describe('OpenPGP.js public api tests', function() {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
decOpt.signature = openpgp.signature.readArmored(encrypted.signature); decOpt.signature = openpgp.signature.readArmored(encrypted.signature);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1116,10 +1114,11 @@ describe('OpenPGP.js public api tests', function() {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
decOpt.signature = openpgp.signature.readArmored(encrypted.signature); decOpt.signature = openpgp.signature.readArmored(encrypted.signature);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1153,16 +1152,17 @@ describe('OpenPGP.js public api tests', function() {
}).then(function (encrypted) { }).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
let keyPacket;
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
expect(decrypted.signatures[1].valid).to.be.true; expect(decrypted.signatures[1].valid).to.be.true;
return privKeyDE.verifyPrimaryUser().then(() => { keyPacket = await privKeyDE.getSigningKeyPacket();
expect(decrypted.signatures[1].keyid.toHex()).to.equal(privKeyDE.getSigningKeyPacket().getKeyId().toHex()); expect(decrypted.signatures[1].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[1].signature.packets.length).to.equal(1); expect(decrypted.signatures[1].signature.packets.length).to.equal(1);
});
}); });
}); });
@ -1191,10 +1191,11 @@ describe('OpenPGP.js public api tests', function() {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
decOpt.signature = openpgp.signature.readArmored(encrypted.signature); decOpt.signature = openpgp.signature.readArmored(encrypted.signature);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null; expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1222,10 +1223,11 @@ describe('OpenPGP.js public api tests', function() {
}).then(function (encrypted) { }).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null; expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1243,10 +1245,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function (encrypted) { return openpgp.encrypt(encOpt).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null; expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1264,10 +1267,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function (encrypted) { return openpgp.encrypt(encOpt).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(''); expect(decrypted.data).to.equal('');
expect(decrypted.signatures[0].valid).to.be.null; expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1284,10 +1288,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function (encrypted) { return openpgp.encrypt(encOpt).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null; expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1307,10 +1312,11 @@ describe('OpenPGP.js public api tests', function() {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
decOpt.signature = openpgp.signature.readArmored(encrypted.signature); decOpt.signature = openpgp.signature.readArmored(encrypted.signature);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.null; expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1335,16 +1341,17 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.encrypt(encOpt).then(function (encrypted) { return openpgp.encrypt(encOpt).then(function (encrypted) {
decOpt.message = openpgp.message.readArmored(encrypted.data); decOpt.message = openpgp.message.readArmored(encrypted.data);
return openpgp.decrypt(decOpt); return openpgp.decrypt(decOpt);
}).then(function (decrypted) { }).then(async function (decrypted) {
let keyPacket;
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
expect(decrypted.signatures[1].valid).to.be.true; expect(decrypted.signatures[1].valid).to.be.true;
return privKeyDE.verifyPrimaryUser().then(() => { keyPacket = await privKeyDE.getSigningKeyPacket();
expect(decrypted.signatures[1].keyid.toHex()).to.equal(privKeyDE.getSigningKeyPacket().getKeyId().toHex()); expect(decrypted.signatures[1].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[1].signature.packets.length).to.equal(1); expect(decrypted.signatures[1].signature.packets.length).to.equal(1);
});
}); });
}); });
@ -1360,10 +1367,11 @@ describe('OpenPGP.js public api tests', function() {
expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/); expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/);
verifyOpt.message = openpgp.cleartext.readArmored(signed.data); verifyOpt.message = openpgp.cleartext.readArmored(signed.data);
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.true; expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1383,16 +1391,17 @@ describe('OpenPGP.js public api tests', function() {
expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/); expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/);
verifyOpt.message = openpgp.cleartext.readArmored(signed.data); verifyOpt.message = openpgp.cleartext.readArmored(signed.data);
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
let keyPacket;
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.true; expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
expect(verified.signatures[1].valid).to.be.true; expect(verified.signatures[1].valid).to.be.true;
return privKeyDE.verifyPrimaryUser().then(() => { keyPacket = await privKeyDE.getSigningKeyPacket();
expect(verified.signatures[1].keyid.toHex()).to.equal(privKeyDE.getSigningKeyPacket().getKeyId().toHex()); expect(verified.signatures[1].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[1].signature.packets.length).to.equal(1); expect(verified.signatures[1].signature.packets.length).to.equal(1);
});
}); });
}); });
@ -1409,10 +1418,11 @@ describe('OpenPGP.js public api tests', function() {
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext); verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
verifyOpt.signature = openpgp.signature.readArmored(signed.signature); verifyOpt.signature = openpgp.signature.readArmored(signed.signature);
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.true; expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1428,10 +1438,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.sign(signOpt).then(function (signed) { return openpgp.sign(signOpt).then(function (signed) {
verifyOpt.message = openpgp.cleartext.readArmored(signed.data); verifyOpt.message = openpgp.cleartext.readArmored(signed.data);
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.null; expect(verified.signatures[0].valid).to.be.null;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1449,10 +1460,11 @@ describe('OpenPGP.js public api tests', function() {
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext); verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
verifyOpt.signature = openpgp.signature.readArmored(signed.signature); verifyOpt.signature = openpgp.signature.readArmored(signed.signature);
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.null; expect(verified.signatures[0].valid).to.be.null;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1469,10 +1481,11 @@ describe('OpenPGP.js public api tests', function() {
return openpgp.sign(signOpt).then(function (signed) { return openpgp.sign(signOpt).then(function (signed) {
verifyOpt.message = signed.message; verifyOpt.message = signed.message;
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(verified.signatures[0].valid).to.be.true; expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1492,12 +1505,13 @@ describe('OpenPGP.js public api tests', function() {
verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext); verifyOpt.message = new openpgp.cleartext.CleartextMessage(plaintext);
verifyOpt.signature = signed.signature; verifyOpt.signature = signed.signature;
return openpgp.verify(verifyOpt); return openpgp.verify(verifyOpt);
}).then(function (verified) { }).then(async function (verified) {
expect(verified.data).to.equal(plaintext); expect(verified.data).to.equal(plaintext);
expect(+verified.signatures[0].signature.packets[0].created).to.be.lte(+openpgp.util.normalizeDate()); expect(+verified.signatures[0].signature.packets[0].created).to.be.lte(+openpgp.util.normalizeDate());
expect(+verified.signatures[0].signature.packets[0].created).to.be.gte(+start); expect(+verified.signatures[0].signature.packets[0].created).to.be.gte(+start);
expect(verified.signatures[0].valid).to.be.true; expect(verified.signatures[0].valid).to.be.true;
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex()); const keyPacket = await privateKey.keys[0].getSigningKeyPacket();
expect(verified.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(verified.signatures[0].signature.packets.length).to.equal(1); expect(verified.signatures[0].signature.packets.length).to.equal(1);
}); });
}); });
@ -1688,14 +1702,13 @@ describe('OpenPGP.js public api tests', function() {
publicKeys: pubKeyDE, publicKeys: pubKeyDE,
message: openpgp.message.readArmored(encrypted.data) message: openpgp.message.readArmored(encrypted.data)
}); });
}).then(function (decrypted) { }).then(async function (decrypted) {
expect(decrypted.data).to.exist; expect(decrypted.data).to.exist;
expect(decrypted.data).to.equal(plaintext); expect(decrypted.data).to.equal(plaintext);
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
return privKeyDE.verifyPrimaryUser().then(() => { const keyPacket = await privKeyDE.getSigningKeyPacket();
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privKeyDE.getSigningKeyPacket().getKeyId().toHex()); expect(decrypted.signatures[0].keyid.toHex()).to.equal(keyPacket.getKeyId().toHex());
expect(decrypted.signatures[0].signature.packets.length).to.equal(1); expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
});
}); });
}); });
}); });