mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-26 22:32:07 +01:00
Cleartext Signature Framework: Return OpenPgpMetadata
This commit is contained in:
parent
90a00e0541
commit
3994f87c78
3 changed files with 37 additions and 15 deletions
|
@ -20,9 +20,6 @@ import static org.pgpainless.signature.SignatureValidator.signatureWasCreatedInB
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -33,8 +30,13 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.StreamEncoding;
|
||||||
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.decryption_verification.ConsumerOptions;
|
import org.pgpainless.decryption_verification.ConsumerOptions;
|
||||||
|
import org.pgpainless.decryption_verification.OpenPgpMetadata;
|
||||||
import org.pgpainless.exception.SignatureValidationException;
|
import org.pgpainless.exception.SignatureValidationException;
|
||||||
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
import org.pgpainless.signature.CertificateValidator;
|
import org.pgpainless.signature.CertificateValidator;
|
||||||
import org.pgpainless.signature.SignatureVerifier;
|
import org.pgpainless.signature.SignatureVerifier;
|
||||||
import org.pgpainless.util.ArmoredInputStreamFactory;
|
import org.pgpainless.util.ArmoredInputStreamFactory;
|
||||||
|
@ -76,9 +78,13 @@ public class CleartextSignatureProcessor {
|
||||||
* @throws PGPException if the signature cannot be initialized.
|
* @throws PGPException if the signature cannot be initialized.
|
||||||
* @throws SignatureValidationException if the signature is invalid.
|
* @throws SignatureValidationException if the signature is invalid.
|
||||||
*/
|
*/
|
||||||
public PGPSignature process() throws IOException, PGPException {
|
public OpenPgpMetadata process() throws IOException, PGPException {
|
||||||
|
OpenPgpMetadata.Builder resultBuilder = OpenPgpMetadata.getBuilder();
|
||||||
|
resultBuilder.setCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED)
|
||||||
|
.setSymmetricKeyAlgorithm(SymmetricKeyAlgorithm.NULL)
|
||||||
|
.setFileEncoding(StreamEncoding.TEXT);
|
||||||
|
|
||||||
PGPSignatureList signatures = ClearsignedMessageUtil.detachSignaturesFromInbandClearsignedMessage(in, multiPassStrategy.getMessageOutputStream());
|
PGPSignatureList signatures = ClearsignedMessageUtil.detachSignaturesFromInbandClearsignedMessage(in, multiPassStrategy.getMessageOutputStream());
|
||||||
Map<PGPSignature, Exception> signatureValidationExceptions = new HashMap<>();
|
|
||||||
|
|
||||||
for (PGPSignature signature : signatures) {
|
for (PGPSignature signature : signatures) {
|
||||||
PGPPublicKeyRing certificate = null;
|
PGPPublicKeyRing certificate = null;
|
||||||
|
@ -90,23 +96,29 @@ public class CleartextSignatureProcessor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (signingKey == null) {
|
|
||||||
signatureValidationExceptions.put(signature, new NoSuchElementException("Missing verification key with key-id " + Long.toHexString(signature.getKeyID())));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (signingKey == null) {
|
||||||
|
throw new SignatureValidationException("Missing verification key with key-id " + Long.toHexString(signature.getKeyID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SubkeyIdentifier signingKeyIdentifier = new SubkeyIdentifier(certificate, signingKey.getKeyID());
|
||||||
|
|
||||||
signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter()).verify(signature);
|
signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter()).verify(signature);
|
||||||
SignatureVerifier.initializeSignatureAndUpdateWithSignedData(signature, multiPassStrategy.getMessageInputStream(), signingKey);
|
SignatureVerifier.initializeSignatureAndUpdateWithSignedData(signature, multiPassStrategy.getMessageInputStream(), signingKey);
|
||||||
CertificateValidator.validateCertificateAndVerifyInitializedSignature(signature, certificate, PGPainless.getPolicy());
|
CertificateValidator.validateCertificateAndVerifyInitializedSignature(signature, certificate, PGPainless.getPolicy());
|
||||||
return signature;
|
resultBuilder.addVerifiedInbandSignature(new SignatureVerification(signature, signingKeyIdentifier));
|
||||||
} catch (SignatureValidationException e) {
|
} catch (SignatureValidationException e) {
|
||||||
LOGGER.log(Level.INFO, "Cannot verify signature made by key " + Long.toHexString(signature.getKeyID()) + ": " + e.getMessage());
|
LOGGER.log(Level.INFO, "Cannot verify signature made by key " + Long.toHexString(signature.getKeyID()) + ": " + e.getMessage());
|
||||||
signatureValidationExceptions.put(signature, e);
|
SubkeyIdentifier signingKeyIdentifier = null;
|
||||||
|
if (signingKey != null) {
|
||||||
|
signingKeyIdentifier = new SubkeyIdentifier(certificate, signingKey.getKeyID());
|
||||||
|
}
|
||||||
|
resultBuilder.addInvalidInbandSignature(new SignatureVerification(signature, signingKeyIdentifier), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new SignatureValidationException("No valid signatures found.", signatureValidationExceptions);
|
return resultBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.pgpainless.signature.cleartext_signatures;
|
package org.pgpainless.signature.cleartext_signatures;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.pgpainless.exception.SignatureValidationException;
|
import org.pgpainless.exception.SignatureValidationException;
|
||||||
import org.pgpainless.key.SubkeyIdentifier;
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
|
@ -24,7 +26,7 @@ public class SignatureVerification {
|
||||||
private final PGPSignature signature;
|
private final PGPSignature signature;
|
||||||
private final SubkeyIdentifier signingKey;
|
private final SubkeyIdentifier signingKey;
|
||||||
|
|
||||||
public SignatureVerification(PGPSignature signature, SubkeyIdentifier signingKey) {
|
public SignatureVerification(PGPSignature signature, @Nullable SubkeyIdentifier signingKey) {
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
this.signingKey = signingKey;
|
this.signingKey = signingKey;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +35,7 @@ public class SignatureVerification {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public SubkeyIdentifier getSigningKey() {
|
public SubkeyIdentifier getSigningKey() {
|
||||||
return signingKey;
|
return signingKey;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.pgpainless.decryption_verification;
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -88,7 +89,10 @@ public class CleartextSignatureVerificationTest {
|
||||||
.withStrategy(multiPassStrategy)
|
.withStrategy(multiPassStrategy)
|
||||||
.withOptions(options);
|
.withOptions(options);
|
||||||
|
|
||||||
PGPSignature signature = processor.process();
|
OpenPgpMetadata result = processor.process();
|
||||||
|
assertTrue(result.isVerified());
|
||||||
|
|
||||||
|
PGPSignature signature = result.getVerifiedSignatures().values().iterator().next();
|
||||||
|
|
||||||
assertEquals(signature.getKeyID(), signingKeys.getPublicKey().getKeyID());
|
assertEquals(signature.getKeyID(), signingKeys.getPublicKey().getKeyID());
|
||||||
assertArrayEquals(MESSAGE_BODY, multiPassStrategy.getBytes());
|
assertArrayEquals(MESSAGE_BODY, multiPassStrategy.getBytes());
|
||||||
|
@ -108,7 +112,10 @@ public class CleartextSignatureVerificationTest {
|
||||||
.withStrategy(multiPassStrategy)
|
.withStrategy(multiPassStrategy)
|
||||||
.withOptions(options);
|
.withOptions(options);
|
||||||
|
|
||||||
PGPSignature signature = processor.process();
|
OpenPgpMetadata result = processor.process();
|
||||||
|
assertTrue(result.isVerified());
|
||||||
|
|
||||||
|
PGPSignature signature = result.getVerifiedSignatures().values().iterator().next();
|
||||||
|
|
||||||
assertEquals(signature.getKeyID(), signingKeys.getPublicKey().getKeyID());
|
assertEquals(signature.getKeyID(), signingKeys.getPublicKey().getKeyID());
|
||||||
FileInputStream fileIn = new FileInputStream(file);
|
FileInputStream fileIn = new FileInputStream(file);
|
||||||
|
|
Loading…
Reference in a new issue