Compute signed data based on expected signature type
This commit is contained in:
parent
1071cb9bca
commit
997f3e8e38
44
src/key.js
44
src/key.js
|
@ -268,7 +268,7 @@ Key.prototype.armor = function() {
|
|||
* @returns {Promise<module:packet.Signature>} The latest valid signature
|
||||
* @async
|
||||
*/
|
||||
async function getLatestValidSignature(signatures, primaryKey, dataToVerify, date=new Date()) {
|
||||
async function getLatestValidSignature(signatures, primaryKey, signatureType, dataToVerify, date=new Date()) {
|
||||
let signature;
|
||||
for (let i = signatures.length - 1; i >= 0; i--) {
|
||||
if (
|
||||
|
@ -276,7 +276,7 @@ async function getLatestValidSignature(signatures, primaryKey, dataToVerify, dat
|
|||
// check binding signature is not expired (ie, check for V4 expiration time)
|
||||
!signatures[i].isExpired(date) &&
|
||||
// check binding signature is verified
|
||||
(signatures[i].verified || await signatures[i].verify(primaryKey, dataToVerify))
|
||||
(signatures[i].verified || await signatures[i].verify(primaryKey, signatureType, dataToVerify))
|
||||
) {
|
||||
signature = signatures[i];
|
||||
}
|
||||
|
@ -300,12 +300,12 @@ Key.prototype.getSigningKey = async function (keyId=null, date=new Date(), userI
|
|||
if (!keyId || subKeys[i].getKeyId().equals(keyId)) {
|
||||
if (await subKeys[i].verify(primaryKey, date) === enums.keyStatus.valid) {
|
||||
const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket };
|
||||
const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, dataToVerify, date);
|
||||
const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date);
|
||||
if (
|
||||
bindingSignature &&
|
||||
bindingSignature.embeddedSignature &&
|
||||
isValidSigningKeyPacket(subKeys[i].keyPacket, bindingSignature) &&
|
||||
await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, dataToVerify, date)
|
||||
await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, enums.signature.key_binding, dataToVerify, date)
|
||||
) {
|
||||
return subKeys[i];
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ Key.prototype.getEncryptionKey = async function(keyId, date=new Date(), userId={
|
|||
if (!keyId || subKeys[i].getKeyId().equals(keyId)) {
|
||||
if (await subKeys[i].verify(primaryKey, date) === enums.keyStatus.valid) {
|
||||
const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket };
|
||||
const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, dataToVerify, date);
|
||||
const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date);
|
||||
if (bindingSignature && isValidEncryptionKeyPacket(subKeys[i].keyPacket, bindingSignature)) {
|
||||
return subKeys[i];
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ Key.prototype.decrypt = async function(passphrases, keyId=null) {
|
|||
*/
|
||||
Key.prototype.isRevoked = async function(signature, key, date=new Date()) {
|
||||
return isDataRevoked(
|
||||
this.keyPacket, { key: this.keyPacket }, this.revocationSignatures, signature, key, date
|
||||
this.keyPacket, enums.signature.key_revocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -542,7 +542,7 @@ Key.prototype.getPrimaryUser = async function(date=new Date(), userId={}) {
|
|||
(userId.comment === undefined || user.userId.comment === userId.comment)
|
||||
)) continue;
|
||||
const dataToVerify = { userId: user.userId, key: primaryKey };
|
||||
const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, dataToVerify, date);
|
||||
const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.cert_generic, dataToVerify, date);
|
||||
if (!selfCertification) continue;
|
||||
users.push({ index: i, user, selfCertification });
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ Key.prototype.update = async function(key) {
|
|||
}
|
||||
// revocation signatures
|
||||
await mergeSignatures(key, this, 'revocationSignatures', srcRevSig => {
|
||||
return isDataRevoked(this.keyPacket, this, [srcRevSig], null, key.keyPacket);
|
||||
return isDataRevoked(this.keyPacket, enums.signature.key_revocation, this, [srcRevSig], null, key.keyPacket);
|
||||
});
|
||||
// direct signatures
|
||||
await mergeSignatures(key, this, 'directSignatures');
|
||||
|
@ -695,7 +695,7 @@ Key.prototype.revoke = async function({
|
|||
*/
|
||||
Key.prototype.getRevocationCertificate = async function() {
|
||||
const dataToVerify = { key: this.keyPacket };
|
||||
const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, dataToVerify);
|
||||
const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.key_revocation, dataToVerify);
|
||||
if (revocationSignature) {
|
||||
const packetlist = new packet.List();
|
||||
packetlist.push(revocationSignature);
|
||||
|
@ -725,7 +725,7 @@ Key.prototype.applyRevocationCertificate = async function(revocationCertificate)
|
|||
if (revocationSignature.isExpired()) {
|
||||
throw new Error('Revocation signature is expired');
|
||||
}
|
||||
if (!await revocationSignature.verify(this.keyPacket, { key: this.keyPacket })) {
|
||||
if (!await revocationSignature.verify(this.keyPacket, enums.signature.key_revocation, { key: this.keyPacket })) {
|
||||
throw new Error('Could not verify revocation signature');
|
||||
}
|
||||
const key = new Key(this.toPacketlist());
|
||||
|
@ -892,7 +892,7 @@ User.prototype.sign = async function(primaryKey, privateKeys) {
|
|||
*/
|
||||
User.prototype.isRevoked = async function(primaryKey, certificate, key, date=new Date()) {
|
||||
return isDataRevoked(
|
||||
primaryKey, {
|
||||
primaryKey, enums.signature.cert_revocation, {
|
||||
key: primaryKey,
|
||||
userId: this.userId,
|
||||
userAttribute: this.userAttribute
|
||||
|
@ -946,7 +946,7 @@ User.prototype.verifyCertificate = async function(primaryKey, certificate, keys,
|
|||
if (certificate.revoked || await that.isRevoked(primaryKey, certificate, signingKey.keyPacket)) {
|
||||
return enums.keyStatus.revoked;
|
||||
}
|
||||
if (!(certificate.verified || await certificate.verify(signingKey.keyPacket, dataToVerify))) {
|
||||
if (!(certificate.verified || await certificate.verify(signingKey.keyPacket, enums.signature.cert_generic, dataToVerify))) {
|
||||
return enums.keyStatus.invalid;
|
||||
}
|
||||
if (certificate.isExpired()) {
|
||||
|
@ -1002,7 +1002,7 @@ User.prototype.verify = async function(primaryKey) {
|
|||
if (selfCertification.revoked || await that.isRevoked(primaryKey, selfCertification)) {
|
||||
return enums.keyStatus.revoked;
|
||||
}
|
||||
if (!(selfCertification.verified || await selfCertification.verify(primaryKey, dataToVerify))) {
|
||||
if (!(selfCertification.verified || await selfCertification.verify(primaryKey, enums.signature.cert_generic, dataToVerify))) {
|
||||
return enums.keyStatus.invalid;
|
||||
}
|
||||
if (selfCertification.isExpired()) {
|
||||
|
@ -1030,13 +1030,13 @@ User.prototype.update = async function(user, primaryKey) {
|
|||
};
|
||||
// self signatures
|
||||
await mergeSignatures(user, this, 'selfCertifications', async function(srcSelfSig) {
|
||||
return srcSelfSig.verified || srcSelfSig.verify(primaryKey, dataToVerify);
|
||||
return srcSelfSig.verified || srcSelfSig.verify(primaryKey, enums.signature.cert_generic, dataToVerify);
|
||||
});
|
||||
// other signatures
|
||||
await mergeSignatures(user, this, 'otherCertifications');
|
||||
// revocation signatures
|
||||
await mergeSignatures(user, this, 'revocationSignatures', function(srcRevSig) {
|
||||
return isDataRevoked(primaryKey, dataToVerify, [srcRevSig]);
|
||||
return isDataRevoked(primaryKey, enums.signature.cert_revocation, dataToVerify, [srcRevSig]);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1086,7 +1086,7 @@ SubKey.prototype.toPacketlist = function() {
|
|||
*/
|
||||
SubKey.prototype.isRevoked = async function(primaryKey, signature, key, date=new Date()) {
|
||||
return isDataRevoked(
|
||||
primaryKey, {
|
||||
primaryKey, enums.signature.subkey_revocation, {
|
||||
key: primaryKey,
|
||||
bind: this.keyPacket
|
||||
}, this.revocationSignatures, signature, key, date
|
||||
|
@ -1106,7 +1106,7 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
|
|||
const that = this;
|
||||
const dataToVerify = { key: primaryKey, bind: this.keyPacket };
|
||||
// check subkey binding signatures
|
||||
const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, dataToVerify, date);
|
||||
const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date);
|
||||
// check binding signature is verified
|
||||
if (!bindingSignature) {
|
||||
return enums.keyStatus.invalid;
|
||||
|
@ -1133,7 +1133,7 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
|
|||
*/
|
||||
SubKey.prototype.getExpirationTime = async function(primaryKey, date=new Date()) {
|
||||
const dataToVerify = { key: primaryKey, bind: this.keyPacket };
|
||||
const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, dataToVerify, date);
|
||||
const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date);
|
||||
if (!bindingSignature) return null;
|
||||
const keyExpiry = getExpirationTime(this.keyPacket, bindingSignature);
|
||||
const sigExpiry = bindingSignature.getExpirationTime();
|
||||
|
@ -1164,7 +1164,7 @@ SubKey.prototype.update = async function(subKey, primaryKey) {
|
|||
const that = this;
|
||||
const dataToVerify = { key: primaryKey, bind: that.keyPacket };
|
||||
await mergeSignatures(subKey, this, 'bindingSignatures', async function(srcBindSig) {
|
||||
if (!(srcBindSig.verified || await srcBindSig.verify(primaryKey, dataToVerify))) {
|
||||
if (!(srcBindSig.verified || await srcBindSig.verify(primaryKey, enums.signature.subkey_binding, dataToVerify))) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < that.bindingSignatures.length; i++) {
|
||||
|
@ -1179,7 +1179,7 @@ SubKey.prototype.update = async function(subKey, primaryKey) {
|
|||
});
|
||||
// revocation signatures
|
||||
await mergeSignatures(subKey, this, 'revocationSignatures', function(srcRevSig) {
|
||||
return isDataRevoked(primaryKey, dataToVerify, [srcRevSig]);
|
||||
return isDataRevoked(primaryKey, enums.signature.subkey_revocation, dataToVerify, [srcRevSig]);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1580,7 +1580,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
|||
* @returns {Promise<Boolean>} True if the signature revokes the data
|
||||
* @async
|
||||
*/
|
||||
async function isDataRevoked(primaryKey, dataToVerify, revocations, signature, key, date=new Date()) {
|
||||
async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date=new Date()) {
|
||||
key = key || primaryKey;
|
||||
const normDate = util.normalizeDate(date);
|
||||
const revocationKeyIds = [];
|
||||
|
@ -1596,7 +1596,7 @@ async function isDataRevoked(primaryKey, dataToVerify, revocations, signature, k
|
|||
// `verifyAllCertifications`.)
|
||||
(!signature || revocationSignature.issuerKeyId.equals(signature.issuerKeyId)) &&
|
||||
!(config.revocations_expire && revocationSignature.isExpired(normDate)) &&
|
||||
(revocationSignature.verified || await revocationSignature.verify(key, dataToVerify))
|
||||
(revocationSignature.verified || await revocationSignature.verify(key, signatureType, dataToVerify))
|
||||
) {
|
||||
// TODO get an identifier of the revoked object instead
|
||||
revocationKeyIds.push(revocationSignature.issuerKeyId);
|
||||
|
|
|
@ -559,7 +559,7 @@ Message.prototype.verify = async function(keys, date=new Date(), streaming) {
|
|||
onePassSig.correspondingSigReject = reject;
|
||||
});
|
||||
onePassSig.signatureData = stream.fromAsync(async () => (await onePassSig.correspondingSig).signatureData);
|
||||
onePassSig.hashed = await onePassSig.hash(literalDataList[0], undefined, streaming);
|
||||
onePassSig.hashed = await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, streaming);
|
||||
}));
|
||||
msg.packets.stream = stream.transformPair(msg.packets.stream, async (readable, writable) => {
|
||||
const reader = stream.getReader(readable);
|
||||
|
@ -625,7 +625,7 @@ async function createVerificationObject(signature, literalDataList, keys, date=n
|
|||
|
||||
const verifiedSig = {
|
||||
keyid: signature.issuerKeyId,
|
||||
verified: keyPacket ? signature.verify(keyPacket, literalDataList[0]) : Promise.resolve(null)
|
||||
verified: keyPacket ? signature.verify(keyPacket, signature.signatureType, literalDataList[0]) : Promise.resolve(null)
|
||||
};
|
||||
|
||||
verifiedSig.signature = Promise.resolve(signature.correspondingSig || signature).then(signature => {
|
||||
|
|
|
@ -171,8 +171,8 @@ Signature.prototype.sign = async function (key, data) {
|
|||
|
||||
this.signatureData = util.concat(arr);
|
||||
|
||||
const toHash = this.toHash(data);
|
||||
const hash = await this.hash(data, toHash);
|
||||
const toHash = this.toHash(signatureType, data);
|
||||
const hash = await this.hash(signatureType, data, toHash);
|
||||
|
||||
this.signedHashValue = stream.slice(stream.clone(hash), 0, 2);
|
||||
|
||||
|
@ -637,19 +637,17 @@ Signature.prototype.calculateTrailer = function () {
|
|||
};
|
||||
|
||||
|
||||
Signature.prototype.toHash = function(data) {
|
||||
const signatureType = enums.write(enums.signature, this.signatureType);
|
||||
|
||||
Signature.prototype.toHash = function(signatureType, data) {
|
||||
const bytes = this.toSign(signatureType, data);
|
||||
|
||||
return util.concat([bytes, this.signatureData, this.calculateTrailer()]);
|
||||
};
|
||||
|
||||
Signature.prototype.hash = async function(data, toHash, streaming=true) {
|
||||
Signature.prototype.hash = async function(signatureType, data, toHash, streaming=true) {
|
||||
const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
|
||||
if (!toHash) toHash = this.toHash(data);
|
||||
if (!toHash) toHash = this.toHash(signatureType, data);
|
||||
if (!streaming && util.isStream(toHash)) {
|
||||
return stream.fromAsync(async () => this.hash(data, await stream.readToEnd(toHash)));
|
||||
return stream.fromAsync(async () => this.hash(signatureType, data, await stream.readToEnd(toHash)));
|
||||
}
|
||||
return crypto.hash.digest(hashAlgorithm, toHash);
|
||||
};
|
||||
|
@ -657,13 +655,14 @@ Signature.prototype.hash = async function(data, toHash, streaming=true) {
|
|||
|
||||
/**
|
||||
* verifys the signature packet. Note: not signature types are implemented
|
||||
* @param {String|Object} data data which on the signature applies
|
||||
* @param {module:packet.PublicSubkey|module:packet.PublicKey|
|
||||
* module:packet.SecretSubkey|module:packet.SecretKey} key the public key to verify the signature
|
||||
* @param {module:enums.signature} signatureType expected signature type
|
||||
* @param {String|Object} data data which on the signature applies
|
||||
* @returns {Promise<Boolean>} True if message is verified, else false.
|
||||
* @async
|
||||
*/
|
||||
Signature.prototype.verify = async function (key, data) {
|
||||
Signature.prototype.verify = async function (key, signatureType, data) {
|
||||
const publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
||||
const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
|
||||
|
||||
|
@ -672,8 +671,8 @@ Signature.prototype.verify = async function (key, data) {
|
|||
if (this.hashed) {
|
||||
hash = this.hashed;
|
||||
} else {
|
||||
toHash = this.toHash(data);
|
||||
hash = await this.hash(data, toHash);
|
||||
toHash = this.toHash(signatureType, data);
|
||||
hash = await this.hash(signatureType, data, toHash);
|
||||
}
|
||||
hash = await stream.readToEnd(hash);
|
||||
|
||||
|
|
|
@ -729,11 +729,13 @@ describe("Packet", function() {
|
|||
await key.read((await openpgp.armor.decode(armored_key)).data);
|
||||
return Promise.all([
|
||||
expect(key[2].verify(key[0],
|
||||
openpgp.enums.signature.cert_generic,
|
||||
{
|
||||
userId: key[1],
|
||||
key: key[0]
|
||||
})).to.eventually.be.true,
|
||||
expect(key[4].verify(key[0],
|
||||
openpgp.enums.signature.key_binding,
|
||||
{
|
||||
key: key[0],
|
||||
bind: key[3]
|
||||
|
@ -773,7 +775,7 @@ describe("Packet", function() {
|
|||
|
||||
await Promise.all([
|
||||
expect(payload[2].verify(
|
||||
key[0], payload[1]
|
||||
key[0], openpgp.enums.signature.binary, payload[1]
|
||||
)).to.eventually.be.true,
|
||||
openpgp.stream.pipe(payload[1].getBytes(), new WritableStream())
|
||||
]);
|
||||
|
@ -900,7 +902,7 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu
|
|||
signed2.concat(await openpgp.stream.readToEnd(signed2.stream, arr => arr));
|
||||
|
||||
await Promise.all([
|
||||
expect(signed2[1].verify(key, signed2[0])).to.eventually.be.true,
|
||||
expect(signed2[1].verify(key, openpgp.enums.signature.text, signed2[0])).to.eventually.be.true,
|
||||
openpgp.stream.pipe(signed2[0].getBytes(), new WritableStream())
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -839,7 +839,7 @@ hkJiXopCSWKSlQInL1devkJJUWJmTmZeugJYlpdLAagQJM0JpsCqIQZwKgAA
|
|||
it('Verify primary key revocation signatures', async function() {
|
||||
const pubKey = (await openpgp.key.readArmored(pub_revoked)).keys[0];
|
||||
await expect(pubKey.revocationSignatures[0].verify(
|
||||
pubKey.primaryKey, {key: pubKey.primaryKey}
|
||||
pubKey.primaryKey, openpgp.enums.signature.key_revocation, {key: pubKey.primaryKey}
|
||||
)).to.eventually.be.true;
|
||||
});
|
||||
|
||||
|
@ -847,7 +847,7 @@ hkJiXopCSWKSlQInL1devkJJUWJmTmZeugJYlpdLAagQJM0JpsCqIQZwKgAA
|
|||
it('Verify subkey revocation signatures', async function() {
|
||||
const pubKey = (await openpgp.key.readArmored(pub_revoked)).keys[0];
|
||||
await expect(pubKey.subKeys[0].revocationSignatures[0].verify(
|
||||
pubKey.primaryKey, {key: pubKey.primaryKey, bind: pubKey.subKeys[0].keyPacket}
|
||||
pubKey.primaryKey, openpgp.enums.signature.subkey_revocation, {key: pubKey.primaryKey, bind: pubKey.subKeys[0].keyPacket}
|
||||
)).to.eventually.be.true;
|
||||
});
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ describe('X25519 Cryptography', function () {
|
|||
// Self Certificate is valid
|
||||
const user = hi.users[0];
|
||||
await expect(user.selfCertifications[0].verify(
|
||||
primaryKey, { userId: user.userId, key: primaryKey }
|
||||
primaryKey, openpgp.enums.signature.cert_generic, { userId: user.userId, key: primaryKey }
|
||||
)).to.eventually.be.true;
|
||||
await expect(user.verifyCertificate(
|
||||
primaryKey, user.selfCertifications[0], [hi.toPublic()]
|
||||
|
@ -261,7 +261,7 @@ describe('X25519 Cryptography', function () {
|
|||
// Self Certificate is valid
|
||||
const user = bye.users[0];
|
||||
await expect(user.selfCertifications[0].verify(
|
||||
bye.primaryKey, { userId: user.userId, key: bye.primaryKey }
|
||||
bye.primaryKey, openpgp.enums.signature.cert_generic, { userId: user.userId, key: bye.primaryKey }
|
||||
)).to.eventually.be.true;
|
||||
await expect(user.verifyCertificate(
|
||||
bye.primaryKey, user.selfCertifications[0], [bye.toPublic()]
|
||||
|
@ -271,7 +271,7 @@ describe('X25519 Cryptography', function () {
|
|||
// Hi trusts Bye!
|
||||
bye.toPublic().signPrimaryUser([hi]).then(trustedBye => {
|
||||
expect(trustedBye.users[0].otherCertifications[0].verify(
|
||||
primaryKey, { userId: user.userId, key: bye.toPublic().primaryKey }
|
||||
primaryKey, openpgp.enums.signature.cert_generic, { userId: user.userId, key: bye.toPublic().primaryKey }
|
||||
)).to.eventually.be.true;
|
||||
}),
|
||||
// Signing message
|
||||
|
|
Loading…
Reference in New Issue
Block a user