Deduplicate signature packet creation

This commit is contained in:
Daniel Huigens 2018-03-02 23:50:44 +01:00
parent 1ed7943bf9
commit e411839ae3
2 changed files with 51 additions and 79 deletions

View File

@ -637,31 +637,16 @@ Key.prototype.revoke = async function(privateKey, {
flag: reasonForRevocationFlag=enums.reasonForRevocation.no_reason,
string: reasonForRevocationString=''
} = {}, date=new Date()) {
if (privateKey.isPublic()) {
throw new Error('Need private key for revoking');
}
if (privateKey.primaryKey.getFingerprint() !== this.primaryKey.getFingerprint()) {
throw new Error('Private key does not match public key');
}
await privateKey.verifyPrimaryUser();
const signingKeyPacket = privateKey.getSigningKeyPacket();
if (!signingKeyPacket) {
throw new Error(`Could not find valid signing key packet in key ${
privateKey.primaryKey.getKeyId().toHex()}`);
}
if (!signingKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
const dataToSign = { key: this.primaryKey };
const signaturePacket = new packet.Signature(date);
signaturePacket.signatureType = enums.write(enums.signature, enums.signature.key_revocation);
signaturePacket.reasonForRevocationFlag = enums.write(enums.reasonForRevocation, reasonForRevocationFlag);
signaturePacket.reasonForRevocationString = reasonForRevocationString;
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
await signaturePacket.sign(signingKeyPacket, dataToSign);
const key = new Key(this.toPacketlist());
key.revocationSignature = signaturePacket;
key.revocationSignature = await createSignaturePacket(dataToSign, privateKey, {
signatureType: enums.signature.key_revocation,
reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag),
reasonForRevocationString
}, date);
return key;
};
@ -833,29 +818,15 @@ User.prototype.toPacketlist = function() {
User.prototype.sign = async function(primaryKey, privateKeys) {
const dataToSign = { userid: this.userId || this.userAttribute, key: primaryKey };
const user = new User(dataToSign.userid);
user.otherCertifications = await Promise.all(privateKeys.map(async function(privateKey) {
if (privateKey.isPublic()) {
throw new Error('Need private key for signing');
}
user.otherCertifications = await Promise.all(privateKeys.map(function(privateKey) {
if (privateKey.primaryKey.getFingerprint() === primaryKey.getFingerprint()) {
throw new Error('Not implemented for self signing');
}
const signingKeyPacket = await privateKey.getSigningKeyPacket();
if (!signingKeyPacket) {
throw new Error('Could not find valid signing key packet in key ' +
privateKey.primaryKey.getKeyId().toHex());
}
if (!signingKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
const signaturePacket = new packet.Signature();
// Most OpenPGP implementations use generic certification (0x10)
signaturePacket.signatureType = enums.write(enums.signature, enums.signature.cert_generic);
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey);
signaturePacket.sign(signingKeyPacket, dataToSign);
return signaturePacket;
return createSignaturePacket(dataToSign, privateKey, {
// Most OpenPGP implementations use generic certification (0x10)
signatureType: enums.signature.cert_generic,
keyFlags: [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]
});
}));
await user.update(this, primaryKey);
return user;
@ -883,6 +854,38 @@ User.prototype.isRevoked = async function(primaryKey, certificate, key, date=new
);
};
/**
* Create signature packet
* @param {Object} dataToSign Contains packets to be signed
* @param {module:key~Key} privateKey private key with decrypted secret key data for signing
* @param {Object} signatureProperties (optional) properties to write on the signature packet before signing
* @param {Date} date (optional) override the creationtime of the signature
* @param {Object} userId (optional) user ID
* @return {module:packet/signature} signature packet
*/
export async function createSignaturePacket(dataToSign, privateKey, signatureProperties, date, userId) {
if (privateKey.isPublic()) {
throw new Error('Need private key for signing');
}
await privateKey.verifyPrimaryUser();
const signingKeyPacket = await privateKey.getSigningKeyPacket(undefined, date, userId);
if (!signingKeyPacket) {
throw new Error(`Could not find valid signing key packet in key ${
privateKey.primaryKey.getKeyId().toHex()}`);
}
if (!signingKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
const signaturePacket = new packet.Signature(date);
for(const [prop, value] of Object.entries(signatureProperties)) {
signaturePacket[prop] = value;
}
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, date, userId);
await signaturePacket.sign(signingKeyPacket, dataToSign);
return signaturePacket;
}
/**
* Verifies the user certificate
* @param {module:packet.SecretKey|
@ -1134,31 +1137,16 @@ SubKey.prototype.revoke = async function(primaryKey, privateKey, {
flag: reasonForRevocationFlag=enums.reasonForRevocation.no_reason,
string: reasonForRevocationString=''
} = {}, date=new Date()) {
if (privateKey.isPublic()) {
throw new Error('Need private key for revoking');
}
if (privateKey.primaryKey.getFingerprint() !== primaryKey.getFingerprint()) {
throw new Error('Private key does not match public key');
}
await privateKey.verifyPrimaryUser();
const signingKeyPacket = privateKey.getSigningKeyPacket();
if (!signingKeyPacket) {
throw new Error(`Could not find valid signing key packet in key ${
privateKey.primaryKey.getKeyId().toHex()}`);
}
if (!signingKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
const dataToSign = { key: primaryKey, bind: this.subKey };
const signaturePacket = new packet.Signature(date);
signaturePacket.signatureType = enums.write(enums.signature, enums.signature.subkey_revocation);
signaturePacket.reasonForRevocationFlag = enums.write(enums.reasonForRevocation, reasonForRevocationFlag);
signaturePacket.reasonForRevocationString = reasonForRevocationString;
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
await signaturePacket.sign(signingKeyPacket, dataToSign);
const subKey = new SubKey(this.subKey);
subKey.revocationSignature = signaturePacket;
subKey.revocationSignature = await createSignaturePacket(dataToSign, privateKey, {
signatureType: enums.signature.subkey_revocation,
reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag),
reasonForRevocationString
}, date);
await subKey.update(this, primaryKey);
return subKey;
};

View File

@ -36,7 +36,7 @@ import enums from './enums';
import util from './util';
import packet from './packet';
import { Signature } from './signature';
import { getPreferredHashAlgo, getPreferredAlgo, isAeadSupported } from './key';
import { getPreferredHashAlgo, getPreferredAlgo, isAeadSupported, createSignaturePacket } from './key';
/**
@ -499,24 +499,8 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig
const signatureType = literalDataPacket.text === null ?
enums.signature.binary : enums.signature.text;
await Promise.all(privateKeys.map(async function(privateKey) {
if (privateKey.isPublic()) {
throw new Error('Need private key for signing');
}
const signingKeyPacket = await privateKey.getSigningKeyPacket(undefined, date, userId);
if (!signingKeyPacket) {
throw new Error('Could not find valid key packet for signing in key ' +
privateKey.primaryKey.getKeyId().toHex());
}
if (!signingKeyPacket.isDecrypted) {
throw new Error('Private key is not decrypted.');
}
const signaturePacket = new packet.Signature(date);
signaturePacket.signatureType = signatureType;
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, date, userId);
await signaturePacket.sign(signingKeyPacket, literalDataPacket);
return signaturePacket;
await Promise.all(privateKeys.map(privateKey => {
return createSignaturePacket(literalDataPacket, privateKey, {signatureType}, date, userId);
})).then(signatureList => {
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
});