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, flag: reasonForRevocationFlag=enums.reasonForRevocation.no_reason,
string: reasonForRevocationString='' string: reasonForRevocationString=''
} = {}, date=new Date()) { } = {}, date=new Date()) {
if (privateKey.isPublic()) {
throw new Error('Need private key for revoking');
}
if (privateKey.primaryKey.getFingerprint() !== this.primaryKey.getFingerprint()) { if (privateKey.primaryKey.getFingerprint() !== this.primaryKey.getFingerprint()) {
throw new Error('Private key does not match public key'); 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 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()); 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; return key;
}; };
@ -833,29 +818,15 @@ User.prototype.toPacketlist = function() {
User.prototype.sign = async function(primaryKey, privateKeys) { User.prototype.sign = async function(primaryKey, privateKeys) {
const dataToSign = { userid: this.userId || this.userAttribute, key: primaryKey }; const dataToSign = { userid: this.userId || this.userAttribute, key: primaryKey };
const user = new User(dataToSign.userid); const user = new User(dataToSign.userid);
user.otherCertifications = await Promise.all(privateKeys.map(async function(privateKey) { user.otherCertifications = await Promise.all(privateKeys.map(function(privateKey) {
if (privateKey.isPublic()) {
throw new Error('Need private key for signing');
}
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');
} }
const signingKeyPacket = await privateKey.getSigningKeyPacket(); return createSignaturePacket(dataToSign, privateKey, {
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) // Most OpenPGP implementations use generic certification (0x10)
signaturePacket.signatureType = enums.write(enums.signature, enums.signature.cert_generic); signatureType: enums.signature.cert_generic,
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; keyFlags: [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; });
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey);
signaturePacket.sign(signingKeyPacket, dataToSign);
return signaturePacket;
})); }));
await user.update(this, primaryKey); await user.update(this, primaryKey);
return user; 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 * Verifies the user certificate
* @param {module:packet.SecretKey| * @param {module:packet.SecretKey|
@ -1134,31 +1137,16 @@ SubKey.prototype.revoke = async function(primaryKey, privateKey, {
flag: reasonForRevocationFlag=enums.reasonForRevocation.no_reason, flag: reasonForRevocationFlag=enums.reasonForRevocation.no_reason,
string: reasonForRevocationString='' string: reasonForRevocationString=''
} = {}, date=new Date()) { } = {}, date=new Date()) {
if (privateKey.isPublic()) {
throw new Error('Need private key for revoking');
}
if (privateKey.primaryKey.getFingerprint() !== primaryKey.getFingerprint()) { if (privateKey.primaryKey.getFingerprint() !== primaryKey.getFingerprint()) {
throw new Error('Private key does not match public key'); 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 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); 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); await subKey.update(this, primaryKey);
return subKey; return subKey;
}; };

View File

@ -36,7 +36,7 @@ import enums from './enums';
import util from './util'; import util from './util';
import packet from './packet'; import packet from './packet';
import { Signature } from './signature'; 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 ? const signatureType = literalDataPacket.text === null ?
enums.signature.binary : enums.signature.text; enums.signature.binary : enums.signature.text;
await Promise.all(privateKeys.map(async function(privateKey) { await Promise.all(privateKeys.map(privateKey => {
if (privateKey.isPublic()) { return createSignaturePacket(literalDataPacket, privateKey, {signatureType}, date, userId);
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;
})).then(signatureList => { })).then(signatureList => {
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket)); signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
}); });