flag to allow verification with expired keys

This commit is contained in:
Sanjana Rajan 2018-01-17 18:37:25 +01:00
parent 3d2c0d784e
commit 50940b2a1e
3 changed files with 27 additions and 40 deletions

View File

@ -41,6 +41,7 @@ export default {
integrity_protect: true, // use integrity protection for symmetric encryption integrity_protect: true, // use integrity protection for symmetric encryption
ignore_mdc_error: false, // fail on decrypt if message is not integrity protected ignore_mdc_error: false, // fail on decrypt if message is not integrity protected
checksum_required: false, // do not throw error when armor is missing a checksum checksum_required: false, // do not throw error when armor is missing a checksum
verify_expired_keys: false, // allow signature verification with expired keys
rsa_blinding: true, rsa_blinding: true,
use_native: true, // use native node.js crypto and Web Crypto apis (if available) use_native: true, // use native node.js crypto and Web Crypto apis (if available)
zero_copy: false, // use transferable objects between the Web Worker and main thread zero_copy: false, // use transferable objects between the Web Worker and main thread

View File

@ -294,18 +294,21 @@ 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
* @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) { Key.prototype.getSigningKeyPacket = function(keyId, allowExpired=false) {
var primaryUser = this.getPrimaryUser(); var primaryUser = this.getPrimaryUser(allowExpired);
var verifyStatus = this.verifyPrimaryKey(allowExpired);
if (primaryUser && if (primaryUser &&
isValidSigningKeyPacket(this.primaryKey, primaryUser.selfCertificate) && isValidSigningKeyPacket(this.primaryKey, primaryUser.selfCertificate) &&
(!keyId || this.primaryKey.getKeyId().equals(keyId))) { (!keyId || this.primaryKey.getKeyId().equals(keyId)) &&
verifyStatus === enums.keyStatus.valid) {
return this.primaryKey; return this.primaryKey;
} }
if (this.subKeys) { if (this.subKeys) {
for (var i = 0; i < this.subKeys.length; i++) { for (var i = 0; i < this.subKeys.length; i++) {
if (this.subKeys[i].isValidSigningKey(this.primaryKey) && if (this.subKeys[i].isValidSigningKey(this.primaryKey, allowExpired) &&
(!keyId || this.subKeys[i].subKey.getKeyId().equals(keyId))) { (!keyId || this.subKeys[i].subKey.getKeyId().equals(keyId))) {
return this.subKeys[i].subKey; return this.subKeys[i].subKey;
} }
@ -430,9 +433,10 @@ Key.prototype.decryptKeyPacket = function(keyIds, passphrase) {
/** /**
* Verify primary key. Checks for revocation signatures, expiration time * Verify primary key. Checks for revocation signatures, expiration time
* and valid self signature * and valid self signature
* @param {Boolean} allowExpired allows signature verification with expired keys
* @return {module:enums.keyStatus} The status of the primary key * @return {module:enums.keyStatus} The status of the primary key
*/ */
Key.prototype.verifyPrimaryKey = function() { Key.prototype.verifyPrimaryKey = function(allowExpired=false) {
// check revocation signature // check revocation signature
if (this.revocationSignature && !this.revocationSignature.isExpired() && if (this.revocationSignature && !this.revocationSignature.isExpired() &&
(this.revocationSignature.verified || (this.revocationSignature.verified ||
@ -440,7 +444,7 @@ Key.prototype.verifyPrimaryKey = function() {
return enums.keyStatus.revoked; return enums.keyStatus.revoked;
} }
// check V3 expiration time // check V3 expiration time
if (this.primaryKey.version === 3 && this.primaryKey.expirationTimeV3 !== 0 && if (!allowExpired && this.primaryKey.version === 3 && this.primaryKey.expirationTimeV3 !== 0 &&
Date.now() > (this.primaryKey.created.getTime() + this.primaryKey.expirationTimeV3*24*3600*1000)) { Date.now() > (this.primaryKey.created.getTime() + this.primaryKey.expirationTimeV3*24*3600*1000)) {
return enums.keyStatus.expired; return enums.keyStatus.expired;
} }
@ -461,7 +465,7 @@ Key.prototype.verifyPrimaryKey = function() {
return enums.keyStatus.invalid; return enums.keyStatus.invalid;
} }
// check V4 expiration time // check V4 expiration time
if (this.primaryKey.version === 4 && primaryUser.selfCertificate.keyNeverExpires === false && if (!allowExpired && this.primaryKey.version === 4 && primaryUser.selfCertificate.keyNeverExpires === false &&
Date.now() > (this.primaryKey.created.getTime() + primaryUser.selfCertificate.keyExpirationTime*1000)) { Date.now() > (this.primaryKey.created.getTime() + primaryUser.selfCertificate.keyExpirationTime*1000)) {
return enums.keyStatus.expired; return enums.keyStatus.expired;
} }
@ -502,9 +506,10 @@ function getExpirationTime(keyPacket, selfCertificate) {
* Returns primary user and most significant (latest valid) self signature * Returns primary user and most significant (latest valid) self signature
* - if multiple users are marked as primary users returns the one with the latest self signature * - if multiple users are marked as primary users returns the one with the latest self signature
* - if no primary user is found returns the user with the latest self signature * - if no primary user is found returns the user with the latest self signature
* @param {Boolean} allowExpired allows signature verification with expired keys
* @return {{user: Array<module:packet/User>, selfCertificate: Array<module:packet/signature>}|null} The primary user and the self signature * @return {{user: Array<module:packet/User>, selfCertificate: Array<module:packet/signature>}|null} The primary user and the self signature
*/ */
Key.prototype.getPrimaryUser = function() { Key.prototype.getPrimaryUser = function(allowExpired=false) {
var primUser = []; var primUser = [];
for (var i = 0; i < this.users.length; i++) { for (var i = 0; i < this.users.length; i++) {
if (!this.users[i].userId || !this.users[i].selfCertifications) { if (!this.users[i].userId || !this.users[i].selfCertifications) {
@ -530,7 +535,7 @@ Key.prototype.getPrimaryUser = function() {
}); });
// return first valid // return first valid
for (var k = 0; k < primUser.length; k++) { for (var k = 0; k < primUser.length; k++) {
if (primUser[k].user.isValidSelfCertificate(this.primaryKey, primUser[k].selfCertificate)) { if (primUser[k].user.isValidSelfCertificate(this.primaryKey, primUser[k].selfCertificate, allowExpired)) {
return primUser[k]; return primUser[k];
} }
} }
@ -744,40 +749,18 @@ User.prototype.isRevoked = function(certificate, primaryKey) {
} }
}; };
/**
* Returns the most significant (latest valid) self signature of the user
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @return {module:packet/signature} The self signature
*/
User.prototype.getValidSelfCertificate = function(primaryKey) {
if (!this.selfCertifications) {
return null;
}
// most recent first
var validCert = this.selfCertifications.sort(function(a, b) {
a = a.created;
b = b.created;
return a>b ? -1 : a<b ? 1 : 0;
});
for (var i = 0; i < validCert.length; i++) {
if (this.isValidSelfCertificate(primaryKey, validCert[i])) {
return validCert[i];
}
}
return null;
};
/** /**
* Returns true if the self certificate is valid * Returns true if the self certificate is valid
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {module:packet/signature} selfCertificate A self certificate of this user * @param {module:packet/signature} selfCertificate A self certificate of this user
* @param {Boolean} allowExpired allows signature verification with expired keys
* @return {Boolean} * @return {Boolean}
*/ */
User.prototype.isValidSelfCertificate = function(primaryKey, selfCertificate) { User.prototype.isValidSelfCertificate = function(primaryKey, selfCertificate, allowExpired=false) {
if (this.isRevoked(selfCertificate, primaryKey)) { if (this.isRevoked(selfCertificate, primaryKey)) {
return false; return false;
} }
if (!selfCertificate.isExpired() && if ((!selfCertificate.isExpired() || allowExpired) &&
(selfCertificate.verified || (selfCertificate.verified ||
selfCertificate.verify(primaryKey, {userid: this.userId || this.userAttribute, key: primaryKey}))) { selfCertificate.verify(primaryKey, {userid: this.userId || this.userAttribute, key: primaryKey}))) {
return true; return true;
@ -944,7 +927,8 @@ SubKey.prototype.isValidEncryptionKey = function(primaryKey) {
* @return {Boolean} * @return {Boolean}
*/ */
SubKey.prototype.isValidSigningKey = function(primaryKey) { SubKey.prototype.isValidSigningKey = function(primaryKey) {
if(this.verify(primaryKey) !== enums.keyStatus.valid) { var verifyStatus = this.verify(primaryKey, config.verify_expired_keys);
if(verifyStatus !== enums.keyStatus.valid) {
return false; return false;
} }
for(var i = 0; i < this.bindingSignatures.length; i++) { for(var i = 0; i < this.bindingSignatures.length; i++) {
@ -958,9 +942,11 @@ SubKey.prototype.isValidSigningKey = function(primaryKey) {
/** /**
* Verify subkey. Checks for revocation signatures, expiration time * Verify subkey. Checks for revocation signatures, expiration time
* and valid binding signature * and valid binding signature
* @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet
* @param {Boolean} allowExpired allows signature verification with expired keys
* @return {module:enums.keyStatus} The status of the subkey * @return {module:enums.keyStatus} The status of the subkey
*/ */
SubKey.prototype.verify = function(primaryKey) { SubKey.prototype.verify = function(primaryKey, allowExpired=false) {
// check subkey revocation signature // check subkey revocation signature
if (this.revocationSignature && !this.revocationSignature.isExpired() && if (this.revocationSignature && !this.revocationSignature.isExpired() &&
(this.revocationSignature.verified || (this.revocationSignature.verified ||
@ -968,7 +954,7 @@ SubKey.prototype.verify = function(primaryKey) {
return enums.keyStatus.revoked; return enums.keyStatus.revoked;
} }
// check V3 expiration time // check V3 expiration time
if (this.subKey.version === 3 && this.subKey.expirationTimeV3 !== 0 && if (!allowExpired && this.subKey.version === 3 && this.subKey.expirationTimeV3 !== 0 &&
Date.now() > (this.subKey.created.getTime() + this.subKey.expirationTimeV3*24*3600*1000)) { Date.now() > (this.subKey.created.getTime() + this.subKey.expirationTimeV3*24*3600*1000)) {
return enums.keyStatus.expired; return enums.keyStatus.expired;
} }
@ -977,7 +963,7 @@ SubKey.prototype.verify = function(primaryKey) {
var isLast = (i === this.bindingSignatures.length - 1); var isLast = (i === this.bindingSignatures.length - 1);
var sig = this.bindingSignatures[i]; var sig = this.bindingSignatures[i];
// check binding signature is not expired // check binding signature is not expired
if(sig.isExpired()) { if(!allowExpired && sig.isExpired()) {
if(isLast) { if(isLast) {
return enums.keyStatus.expired; // last expired binding signature return enums.keyStatus.expired; // last expired binding signature
} else { } else {
@ -994,7 +980,7 @@ SubKey.prototype.verify = function(primaryKey) {
} }
// check V4 expiration time // check V4 expiration time
if (this.subKey.version === 4) { if (this.subKey.version === 4) {
if(sig.keyNeverExpires === false && Date.now() > (this.subKey.created.getTime() + sig.keyExpirationTime*1000)) { if(!allowExpired && sig.keyNeverExpires === false && Date.now() > (this.subKey.created.getTime() + sig.keyExpirationTime*1000)) {
if(isLast) { if(isLast) {
return enums.keyStatus.expired; // last V4 expired binding signature return enums.keyStatus.expired; // last V4 expired binding signature
} else { } else {

View File

@ -467,7 +467,7 @@ function createVerificationObjects(signatureList, literalDataList, keys) {
for (var i = 0; i < signatureList.length; i++) { for (var i = 0; i < signatureList.length; i++) {
var keyPacket = null; var keyPacket = null;
for (var j = 0; j < keys.length; j++) { for (var j = 0; j < keys.length; j++) {
keyPacket = keys[j].getSigningKeyPacket(signatureList[i].issuerKeyId); keyPacket = keys[j].getSigningKeyPacket(signatureList[i].issuerKeyId, config.verify_expired_keys);
if (keyPacket) { if (keyPacket) {
break; break;
} }