1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-12-22 19:08:00 +01:00

Support version 3 signature packets

This commit is contained in:
Bastien JANSEN 2023-02-08 09:16:53 +01:00 committed by Paul Schaub
parent 6c2331d4e6
commit 30771f470a
3 changed files with 75 additions and 3 deletions

View file

@ -158,8 +158,10 @@ public abstract class SignatureValidator {
@Override
public void verify(PGPSignature signature) throws SignatureValidationException {
signatureIsNotMalformed(signingKey).verify(signature);
signatureDoesNotHaveCriticalUnknownNotations(policy.getNotationRegistry()).verify(signature);
signatureDoesNotHaveCriticalUnknownSubpackets().verify(signature);
if (signature.getVersion() >= 4) {
signatureDoesNotHaveCriticalUnknownNotations(policy.getNotationRegistry()).verify(signature);
signatureDoesNotHaveCriticalUnknownSubpackets().verify(signature);
}
signatureUsesAcceptableHashAlgorithm(policy).verify(signature);
signatureUsesAcceptablePublicKeyAlgorithm(policy, signingKey).verify(signature);
}
@ -373,7 +375,9 @@ public abstract class SignatureValidator {
return new SignatureValidator() {
@Override
public void verify(PGPSignature signature) throws SignatureValidationException {
signatureHasHashedCreationTime().verify(signature);
if (signature.getVersion() >= 4) {
signatureHasHashedCreationTime().verify(signature);
}
signatureDoesNotPredateSigningKey(creator).verify(signature);
if (signature.getSignatureType() != SignatureType.PRIMARYKEY_BINDING.getCode()) {
signatureDoesNotPredateSigningKeyBindingDate(creator).verify(signature);

View file

@ -141,6 +141,9 @@ public final class SignatureSubpacketsUtil {
* @return signature creation time subpacket
*/
public static @Nullable SignatureCreationTime getSignatureCreationTime(PGPSignature signature) {
if (signature.getVersion() == 3) {
return new SignatureCreationTime(false, signature.getCreationTime());
}
return hashed(signature, SignatureSubpacket.signatureCreationTime);
}

View file

@ -0,0 +1,65 @@
package org.pgpainless.decryption_verification;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPV3SignatureGenerator;
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.PublicKeyAlgorithm;
import org.pgpainless.algorithm.SignatureType;
import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertTrue;
class VerifyVersion3SignaturePacketTest {
protected static final byte[] DATA = "hello".getBytes(StandardCharsets.UTF_8);
@Test
void verifyDetachedVersion3Signature() throws PGPException, IOException {
PGPSignature version3Signature = generateV3Signature();
ConsumerOptions options = new ConsumerOptions()
.addVerificationCert(TestKeys.getEmilPublicKeyRing())
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(version3Signature.getEncoded()));
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(DATA))
.withOptions(options);
OpenPgpMetadata metadata = processSignedData(verifier);
assertTrue(metadata.containsVerifiedSignatureFrom(TestKeys.getEmilPublicKeyRing()));
}
private static PGPSignature generateV3Signature() throws IOException, PGPException {
PGPContentSignerBuilder builder = ImplementationFactory.getInstance().getPGPContentSignerBuilder(PublicKeyAlgorithm.ECDSA, HashAlgorithm.SHA512);
PGPV3SignatureGenerator signatureGenerator = new PGPV3SignatureGenerator(builder);
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
PGPPrivateKey privateKey = secretKeys.getSecretKey().extractPrivateKey(protector.getDecryptor(secretKeys.getSecretKey().getKeyID()));
signatureGenerator.init(SignatureType.CANONICAL_TEXT_DOCUMENT.getCode(), privateKey);
signatureGenerator.update(DATA);
return signatureGenerator.generate();
}
private OpenPgpMetadata processSignedData(DecryptionStream verifier) throws IOException {
Streams.drain(verifier);
verifier.close();
return verifier.getResult();
}
}