An attempt at more suitable signature verification logic

This commit is contained in:
Paul Schaub 2023-07-09 13:43:44 +02:00
parent b6cd1ff13c
commit db5908022a
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
2 changed files with 49 additions and 7 deletions

View File

@ -182,8 +182,8 @@ public abstract class SignatureValidator {
* @param signingKey signing key * @param signingKey signing key
* @return validator * @return validator
*/ */
private static SignatureValidator signatureUsesAcceptablePublicKeyAlgorithm(Policy policy, public static SignatureValidator signatureUsesAcceptablePublicKeyAlgorithm(Policy policy,
PGPPublicKey signingKey) { PGPPublicKey signingKey) {
return new SignatureValidator() { return new SignatureValidator() {
@Override @Override
public void verify(PGPSignature signature) throws SignatureValidationException { public void verify(PGPSignature signature) throws SignatureValidationException {
@ -207,7 +207,7 @@ public abstract class SignatureValidator {
* @param policy policy * @param policy policy
* @return validator * @return validator
*/ */
private static SignatureValidator signatureUsesAcceptableHashAlgorithm(Policy policy) { public static SignatureValidator signatureUsesAcceptableHashAlgorithm(Policy policy) {
return new SignatureValidator() { return new SignatureValidator() {
@Override @Override
public void verify(PGPSignature signature) throws SignatureValidationException { public void verify(PGPSignature signature) throws SignatureValidationException {

View File

@ -8,6 +8,7 @@ import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSignature import org.bouncycastle.openpgp.PGPSignature
import org.pgpainless.PGPainless import org.pgpainless.PGPainless
import org.pgpainless.algorithm.KeyFlag import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.exception.SignatureValidationException import org.pgpainless.exception.SignatureValidationException
import org.pgpainless.key.OpenPgpFingerprint import org.pgpainless.key.OpenPgpFingerprint
import org.pgpainless.key.info.KeyRingInfo import org.pgpainless.key.info.KeyRingInfo
@ -15,6 +16,7 @@ import org.pgpainless.key.util.KeyRingUtils
import org.pgpainless.key.util.RevocationAttributes import org.pgpainless.key.util.RevocationAttributes
import org.pgpainless.policy.Policy import org.pgpainless.policy.Policy
import org.pgpainless.signature.SignatureUtils import org.pgpainless.signature.SignatureUtils
import org.pgpainless.signature.consumer.SignatureValidator
import org.pgpainless.signature.consumer.SignatureVerifier import org.pgpainless.signature.consumer.SignatureVerifier
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil
import org.pgpainless.wot.network.* import org.pgpainless.wot.network.*
@ -193,8 +195,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
val issuer = nodeMap[issuerFingerprint]!! val issuer = nodeMap[issuerFingerprint]!!
try { try {
val valid = SignatureVerifier.verifyDirectKeySignature(delegation, issuerSigningKey, val valid = verifyDelegation(delegation, issuerSigningKey, targetPrimaryKey, policy)
targetPrimaryKey, policy, referenceTime.timestamp)
if (valid) { if (valid) {
networkBuilder.addEdge(fromDelegation(issuer, target, delegation)) networkBuilder.addEdge(fromDelegation(issuer, target, delegation))
return // we're done return // we're done
@ -207,6 +208,27 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
} }
} }
/**
* Verify a delegation signature over a primary key.
* This method returns true, if the signature is correct and well-formed.
* It does not reject expired or revoked signatures.
*/
fun verifyDelegation(signature: PGPSignature, signingKey: PGPPublicKey, signedKey: PGPPublicKey, policy: Policy): Boolean {
SignatureValidator.signatureIsOfType(SignatureType.KEY_REVOCATION, SignatureType.DIRECT_KEY).verify(signature)
SignatureValidator.signatureIsNotMalformed(signingKey).verify(signature)
if (signature.version >= 4) {
SignatureValidator.signatureDoesNotHaveCriticalUnknownNotations(policy.notationRegistry).verify(signature)
SignatureValidator.signatureDoesNotHaveCriticalUnknownSubpackets().verify(signature)
}
SignatureValidator.signatureUsesAcceptableHashAlgorithm(policy).verify(signature)
SignatureValidator.signatureUsesAcceptablePublicKeyAlgorithm(policy, signingKey).verify(signature)
SignatureValidator.signatureDoesNotPredateSignee(signedKey).verify(signature)
SignatureValidator.correctSignatureOverKey(signingKey, signedKey).verify(signature)
return true
}
/** /**
* Process a certification (third-party-issued certification over the given [userId]) * Process a certification (third-party-issued certification over the given [userId])
* and add it upon successful verification as an edge to the [Network.Builder]. * and add it upon successful verification as an edge to the [Network.Builder].
@ -231,8 +253,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
val issuer = nodeMap[issuerFingerprint]!! val issuer = nodeMap[issuerFingerprint]!!
try { try {
val valid = SignatureVerifier.verifySignatureOverUserId(userId, certification, val valid = verifyCertification(certification, issuerSigningKey, targetPrimaryKey, userId, policy)
issuerSigningKey, targetPrimaryKey, policy, referenceTime.timestamp)
if (valid) { if (valid) {
networkBuilder.addEdge(fromCertification(issuer, target, userId, certification)) networkBuilder.addEdge(fromCertification(issuer, target, userId, certification))
return // we're done return // we're done
@ -244,6 +265,27 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
} }
} }
/**
* Verify a certification over a user-ID.
* This method returns true, if the signature is correct and well-formed.
* It does not reject expired or revoked signatures.
*/
fun verifyCertification(signature: PGPSignature, signingKey: PGPPublicKey, signedKey: PGPPublicKey, userId: String, policy: Policy): Boolean {
SignatureValidator.signatureIsOfType(SignatureType.CERTIFICATION_REVOCATION, SignatureType.GENERIC_CERTIFICATION, SignatureType.NO_CERTIFICATION, SignatureType.CASUAL_CERTIFICATION, SignatureType.POSITIVE_CERTIFICATION).verify(signature)
SignatureValidator.signatureIsNotMalformed(signingKey).verify(signature)
if (signature.version >= 4) {
SignatureValidator.signatureDoesNotHaveCriticalUnknownNotations(policy.notationRegistry).verify(signature)
SignatureValidator.signatureDoesNotHaveCriticalUnknownSubpackets().verify(signature)
}
SignatureValidator.signatureUsesAcceptableHashAlgorithm(policy).verify(signature)
SignatureValidator.signatureUsesAcceptablePublicKeyAlgorithm(policy, signingKey).verify(signature)
SignatureValidator.signatureDoesNotPredateSignee(signedKey).verify(signature)
SignatureValidator.correctSignatureOverUserId(userId, signedKey, signingKey).verify(signature)
return true
}
/** /**
* Map an [OpenPgpFingerprint] to a [Fingerprint]. * Map an [OpenPgpFingerprint] to a [Fingerprint].
* *