1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-12-23 11:27:57 +01:00

Explicitly reject non-self signatures when picking user-id self sigs

This commit is contained in:
Paul Schaub 2021-07-22 14:23:21 +02:00
parent 545c660815
commit 1f08815633
3 changed files with 48 additions and 0 deletions

View file

@ -239,6 +239,7 @@ public class SignaturePicker {
PGPSignature latestUserIdCert = null; PGPSignature latestUserIdCert = null;
for (PGPSignature signature : signatures) { for (PGPSignature signature : signatures) {
try { try {
SignatureValidator.verifyWasPossiblyMadeByKey(primaryKey, signature);
SignatureValidator.signatureIsCertification().verify(signature); SignatureValidator.signatureIsCertification().verify(signature);
SignatureValidator.signatureStructureIsAcceptable(primaryKey, policy).verify(signature); SignatureValidator.signatureStructureIsAcceptable(primaryKey, policy).verify(signature);
SignatureValidator.signatureIsAlreadyEffective(validationDate).verify(signature); SignatureValidator.signatureIsAlreadyEffective(validationDate).verify(signature);

View file

@ -38,6 +38,7 @@ import org.pgpainless.algorithm.SignatureSubpacket;
import org.pgpainless.algorithm.SignatureType; import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.exception.SignatureValidationException;
import org.pgpainless.implementation.ImplementationFactory; import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.policy.Policy; import org.pgpainless.policy.Policy;
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
import org.pgpainless.util.BCUtil; import org.pgpainless.util.BCUtil;
@ -103,6 +104,44 @@ public abstract class SignatureValidator {
} }
} }
/**
* Check, whether there is the possibility that the given signature was created by the given key.
* This method throws a {@link SignatureValidationException} if we can say with certainty that the signature
* was not created by the given key (e.g. if the sig carries another issuer, issuer fingerprint packet).
*
* If there is no information found in the signature about who created it (no issuer, no fingerprint),
* return true since it is plausible that the given key created the sig.
*
* @param signingKey signing key
* @param signature signature
* @return true only if the signing key either created the signature or the signature doesn't carry signer information
* @throws SignatureValidationException if the sig was not created by the key
*/
public static boolean verifyWasPossiblyMadeByKey(PGPPublicKey signingKey, PGPSignature signature) throws SignatureValidationException {
OpenPgpV4Fingerprint signingKeyFingerprint = new OpenPgpV4Fingerprint(signingKey);
Long issuer = SignatureSubpacketsUtil.getIssuerKeyIdAsLong(signature);
if (issuer != null) {
if (issuer != signingKey.getKeyID()) {
throw new SignatureValidationException("Signature was not created by " + signingKeyFingerprint + " (signature issuer: " + Long.toHexString(issuer) + ")");
} else {
return true;
}
}
OpenPgpV4Fingerprint fingerprint = SignatureSubpacketsUtil.getIssuerFingerprintAsOpenPgpV4Fingerprint(signature);
if (fingerprint != null) {
if (!fingerprint.equals(signingKeyFingerprint)) {
throw new SignatureValidationException("Signature was not created by " + signingKeyFingerprint + " (signature fingerprint: " + fingerprint + ")");
} else {
return true;
}
}
// No issuer information found, so we cannot rule out that we did not create the sig
return true;
}
public static boolean verifyUserIdCertification(String userId, PGPSignature signature, PGPPublicKey primaryKey, Policy policy, Date validationDate) public static boolean verifyUserIdCertification(String userId, PGPSignature signature, PGPPublicKey primaryKey, Policy policy, Date validationDate)
throws SignatureValidationException { throws SignatureValidationException {
return verifyUserIdCertification(userId, signature, primaryKey, primaryKey, policy, validationDate); return verifyUserIdCertification(userId, signature, primaryKey, primaryKey, policy, validationDate);

View file

@ -104,6 +104,14 @@ public class SignatureSubpacketsUtil {
return hashedOrUnhashed(signature, SignatureSubpacket.issuerKeyId); return hashedOrUnhashed(signature, SignatureSubpacket.issuerKeyId);
} }
public static Long getIssuerKeyIdAsLong(PGPSignature signature) {
IssuerKeyID keyID = getIssuerKeyId(signature);
if (keyID == null) {
return null;
}
return keyID.getKeyID();
}
/** /**
* Return the revocation reason subpacket of the signature. * Return the revocation reason subpacket of the signature.
* Since this packet is rather important for revocations, we only search for it in the * Since this packet is rather important for revocations, we only search for it in the