mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 04:17:59 +01:00
Properly expose signatures
This commit is contained in:
parent
b2cf606638
commit
2a624d30f9
3 changed files with 171 additions and 114 deletions
|
@ -91,16 +91,24 @@ public class MessageMetadata {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nonnull List<SignatureVerification> getVerifiedSignatures() {
|
public List<SignatureVerification> getVerifiedDetachedSignatures() {
|
||||||
|
return new ArrayList<>(message.verifiedDetachedSignatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SignatureVerification.Failure> getRejectedDetachedSignatures() {
|
||||||
|
return new ArrayList<>(message.rejectedDetachedSignatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nonnull List<SignatureVerification> getVerifiedInlineSignatures() {
|
||||||
List<SignatureVerification> verifications = new ArrayList<>();
|
List<SignatureVerification> verifications = new ArrayList<>();
|
||||||
Iterator<List<SignatureVerification>> verificationsByLayer = getVerifiedSignaturesByLayer();
|
Iterator<List<SignatureVerification>> verificationsByLayer = getVerifiedInlineSignaturesByLayer();
|
||||||
while (verificationsByLayer.hasNext()) {
|
while (verificationsByLayer.hasNext()) {
|
||||||
verifications.addAll(verificationsByLayer.next());
|
verifications.addAll(verificationsByLayer.next());
|
||||||
}
|
}
|
||||||
return verifications;
|
return verifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nonnull Iterator<List<SignatureVerification>> getVerifiedSignaturesByLayer() {
|
public @Nonnull Iterator<List<SignatureVerification>> getVerifiedInlineSignaturesByLayer() {
|
||||||
return new LayerIterator<List<SignatureVerification>>(message) {
|
return new LayerIterator<List<SignatureVerification>>(message) {
|
||||||
@Override
|
@Override
|
||||||
boolean matches(Nested layer) {
|
boolean matches(Nested layer) {
|
||||||
|
@ -114,21 +122,24 @@ public class MessageMetadata {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
List<SignatureVerification> getProperty(Layer last) {
|
List<SignatureVerification> getProperty(Layer last) {
|
||||||
return new ArrayList<>(last.getVerifiedSignatures());
|
List<SignatureVerification> list = new ArrayList<>();
|
||||||
|
list.addAll(last.getVerifiedOnePassSignatures());
|
||||||
|
list.addAll(last.getVerifiedPrependedSignatures());
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nonnull List<SignatureVerification.Failure> getRejectedSignatures() {
|
public @Nonnull List<SignatureVerification.Failure> getRejectedInlineSignatures() {
|
||||||
List<SignatureVerification.Failure> rejected = new ArrayList<>();
|
List<SignatureVerification.Failure> rejected = new ArrayList<>();
|
||||||
Iterator<List<SignatureVerification.Failure>> rejectedByLayer = getRejectedSignaturesByLayer();
|
Iterator<List<SignatureVerification.Failure>> rejectedByLayer = getRejectedInlineSignaturesByLayer();
|
||||||
while (rejectedByLayer.hasNext()) {
|
while (rejectedByLayer.hasNext()) {
|
||||||
rejected.addAll(rejectedByLayer.next());
|
rejected.addAll(rejectedByLayer.next());
|
||||||
}
|
}
|
||||||
return rejected;
|
return rejected;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nonnull Iterator<List<SignatureVerification.Failure>> getRejectedSignaturesByLayer() {
|
public @Nonnull Iterator<List<SignatureVerification.Failure>> getRejectedInlineSignaturesByLayer() {
|
||||||
return new LayerIterator<List<SignatureVerification.Failure>>(message) {
|
return new LayerIterator<List<SignatureVerification.Failure>>(message) {
|
||||||
@Override
|
@Override
|
||||||
boolean matches(Nested layer) {
|
boolean matches(Nested layer) {
|
||||||
|
@ -142,7 +153,10 @@ public class MessageMetadata {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
List<SignatureVerification.Failure> getProperty(Layer last) {
|
List<SignatureVerification.Failure> getProperty(Layer last) {
|
||||||
return new ArrayList<>(last.getFailedSignatures());
|
List<SignatureVerification.Failure> list = new ArrayList<>();
|
||||||
|
list.addAll(last.getRejectedOnePassSignatures());
|
||||||
|
list.addAll(last.getRejectedPrependedSignatures());
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -169,8 +183,12 @@ public class MessageMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class Layer {
|
public abstract static class Layer {
|
||||||
protected final List<SignatureVerification> verifiedSignatures = new ArrayList<>();
|
protected final List<SignatureVerification> verifiedDetachedSignatures = new ArrayList<>();
|
||||||
protected final List<SignatureVerification.Failure> failedSignatures = new ArrayList<>();
|
protected final List<SignatureVerification.Failure> rejectedDetachedSignatures = new ArrayList<>();
|
||||||
|
protected final List<SignatureVerification> verifiedOnePassSignatures = new ArrayList<>();
|
||||||
|
protected final List<SignatureVerification.Failure> rejectedOnePassSignatures = new ArrayList<>();
|
||||||
|
protected final List<SignatureVerification> verifiedPrependedSignatures = new ArrayList<>();
|
||||||
|
protected final List<SignatureVerification.Failure> rejectedPrependedSignatures = new ArrayList<>();
|
||||||
protected Nested child;
|
protected Nested child;
|
||||||
|
|
||||||
public Nested getChild() {
|
public Nested getChild() {
|
||||||
|
@ -181,21 +199,54 @@ public class MessageMetadata {
|
||||||
this.child = child;
|
this.child = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SignatureVerification> getVerifiedSignatures() {
|
public List<SignatureVerification> getVerifiedDetachedSignatures() {
|
||||||
return new ArrayList<>(verifiedSignatures);
|
return new ArrayList<>(verifiedDetachedSignatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SignatureVerification.Failure> getFailedSignatures() {
|
public List<SignatureVerification.Failure> getRejectedDetachedSignatures() {
|
||||||
return new ArrayList<>(failedSignatures);
|
return new ArrayList<>(rejectedDetachedSignatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addVerifiedSignature(SignatureVerification signatureVerification) {
|
void addVerifiedDetachedSignature(SignatureVerification signatureVerification) {
|
||||||
verifiedSignatures.add(signatureVerification);
|
verifiedDetachedSignatures.add(signatureVerification);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFailedSignature(SignatureVerification.Failure failure) {
|
void addRejectedDetachedSignature(SignatureVerification.Failure failure) {
|
||||||
failedSignatures.add(failure);
|
rejectedDetachedSignatures.add(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<SignatureVerification> getVerifiedOnePassSignatures() {
|
||||||
|
return new ArrayList<>(verifiedOnePassSignatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SignatureVerification.Failure> getRejectedOnePassSignatures() {
|
||||||
|
return new ArrayList<>(rejectedOnePassSignatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addVerifiedOnePassSignature(SignatureVerification verifiedOnePassSignature) {
|
||||||
|
this.verifiedOnePassSignatures.add(verifiedOnePassSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRejectedOnePassSignature(SignatureVerification.Failure rejected) {
|
||||||
|
this.rejectedOnePassSignatures.add(rejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SignatureVerification> getVerifiedPrependedSignatures() {
|
||||||
|
return new ArrayList<>(verifiedPrependedSignatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SignatureVerification.Failure> getRejectedPrependedSignatures() {
|
||||||
|
return new ArrayList<>(rejectedPrependedSignatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addVerifiedPrependedSignature(SignatureVerification verified) {
|
||||||
|
this.verifiedPrependedSignatures.add(verified);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRejectedPrependedSignature(SignatureVerification.Failure rejected) {
|
||||||
|
this.rejectedPrependedSignatures.add(rejected);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Nested {
|
public interface Nested {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSessionKey;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory;
|
import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory;
|
||||||
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
|
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
|
||||||
|
@ -55,6 +56,7 @@ import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
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.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
import org.pgpainless.util.SessionKey;
|
import org.pgpainless.util.SessionKey;
|
||||||
import org.pgpainless.util.Tuple;
|
import org.pgpainless.util.Tuple;
|
||||||
|
@ -94,9 +96,9 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OpenPgpMessageInputStream(@Nonnull InputStream inputStream,
|
protected OpenPgpMessageInputStream(@Nonnull InputStream inputStream,
|
||||||
@Nonnull ConsumerOptions options,
|
@Nonnull ConsumerOptions options,
|
||||||
@Nonnull MessageMetadata.Layer metadata,
|
@Nonnull MessageMetadata.Layer metadata,
|
||||||
@Nonnull Policy policy)
|
@Nonnull Policy policy)
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
super(OpenPgpMetadata.getBuilder());
|
super(OpenPgpMetadata.getBuilder());
|
||||||
|
|
||||||
|
@ -173,7 +175,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
|
|
||||||
throw new MissingDecryptionMethodException("No working decryption method found.");
|
throw new MissingDecryptionMethodException("No working decryption method found.");
|
||||||
|
|
||||||
// Marker Packets need to be skipped and ignored
|
// Marker Packets need to be skipped and ignored
|
||||||
case MARKER:
|
case MARKER:
|
||||||
packetInputStream.readMarker();
|
packetInputStream.readMarker();
|
||||||
break;
|
break;
|
||||||
|
@ -236,7 +238,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
PGPSignature signature = packetInputStream.readSignature();
|
PGPSignature signature = packetInputStream.readSignature();
|
||||||
if (isSigForOPS) {
|
if (isSigForOPS) {
|
||||||
signatures.leaveNesting(); // TODO: Only leave nesting if all OPSs of the nesting layer are dealt with
|
signatures.leaveNesting(); // TODO: Only leave nesting if all OPSs of the nesting layer are dealt with
|
||||||
signatures.addCorrespondingOnePassSignature(signature, metadata);
|
signatures.addCorrespondingOnePassSignature(signature, metadata, policy);
|
||||||
} else {
|
} else {
|
||||||
signatures.addPrependedSignature(signature);
|
signatures.addPrependedSignature(signature);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +259,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
// Try session key
|
// Try session key
|
||||||
if (options.getSessionKey() != null) {
|
if (options.getSessionKey() != null) {
|
||||||
SessionKey sessionKey = options.getSessionKey();
|
SessionKey sessionKey = options.getSessionKey();
|
||||||
|
|
||||||
throwIfUnacceptable(sessionKey.getAlgorithm());
|
throwIfUnacceptable(sessionKey.getAlgorithm());
|
||||||
|
|
||||||
SessionKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
SessionKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
|
@ -270,11 +271,13 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
if (esk instanceof PGPPBEEncryptedData) {
|
if (esk instanceof PGPPBEEncryptedData) {
|
||||||
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
||||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||||
|
encryptedData.sessionKey = sessionKey;
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||||
return true;
|
return true;
|
||||||
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
||||||
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
||||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||||
|
encryptedData.sessionKey = sessionKey;
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -290,22 +293,22 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
||||||
throwIfUnacceptable(kekAlgorithm);
|
throwIfUnacceptable(kekAlgorithm);
|
||||||
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
||||||
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPBEDataDecryptorFactory(passphrase);
|
.getPBEDataDecryptorFactory(passphrase);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||||
SymmetricKeyAlgorithm sessionKeyAlgorithm = SymmetricKeyAlgorithm.requireFromId(
|
SessionKey sessionKey = new SessionKey(skesk.getSessionKey(decryptorFactory));
|
||||||
skesk.getSymmetricAlgorithm(decryptorFactory));
|
throwIfUnacceptable(sessionKey.getAlgorithm());
|
||||||
throwIfUnacceptable(sessionKeyAlgorithm);
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKey.getAlgorithm());
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKeyAlgorithm);
|
encryptedData.sessionKey = sessionKey;
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||||
return true;
|
return true;
|
||||||
} catch (UnacceptableAlgorithmException e) {
|
} catch (UnacceptableAlgorithmException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
// Password mismatch?
|
// Password mismatch?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,11 +326,13 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
.getPublicKeyDataDecryptorFactory(privateKey);
|
||||||
try {
|
try {
|
||||||
SymmetricKeyAlgorithm symAlg = SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory));
|
|
||||||
throwIfUnacceptable(symAlg);
|
|
||||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||||
|
SessionKey sessionKey = new SessionKey(pkesk.getSessionKey(decryptorFactory));
|
||||||
|
throwIfUnacceptable(sessionKey.getAlgorithm());
|
||||||
|
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||||
|
encryptedData.sessionKey = sessionKey;
|
||||||
|
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||||
return true;
|
return true;
|
||||||
|
@ -348,8 +353,12 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||||
|
SessionKey sessionKey = new SessionKey(pkesk.getSessionKey(decryptorFactory));
|
||||||
|
throwIfUnacceptable(sessionKey.getAlgorithm());
|
||||||
|
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||||
|
encryptedData.sessionKey = sessionKey;
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||||
return true;
|
return true;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
|
@ -427,7 +436,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
signatures.finish(metadata);
|
signatures.finish(metadata, policy);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -455,7 +464,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
signatures.finish(metadata);
|
signatures.finish(metadata, policy);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -588,7 +597,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCorrespondingOnePassSignature(PGPSignature signature, MessageMetadata.Layer layer) {
|
void addCorrespondingOnePassSignature(PGPSignature signature, MessageMetadata.Layer layer, Policy policy) {
|
||||||
for (int i = onePassSignatures.size() - 1; i >= 0; i--) {
|
for (int i = onePassSignatures.size() - 1; i >= 0; i--) {
|
||||||
OnePassSignature onePassSignature = onePassSignatures.get(i);
|
OnePassSignature onePassSignature = onePassSignatures.get(i);
|
||||||
if (onePassSignature.opSignature.getKeyID() != signature.getKeyID()) {
|
if (onePassSignature.opSignature.getKeyID() != signature.getKeyID()) {
|
||||||
|
@ -598,19 +607,32 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean verified = onePassSignature.verify(signature);
|
boolean correct = onePassSignature.verify(signature);
|
||||||
SignatureVerification verification = new SignatureVerification(signature,
|
SignatureVerification verification = new SignatureVerification(signature,
|
||||||
new SubkeyIdentifier(onePassSignature.certificate, onePassSignature.keyId));
|
new SubkeyIdentifier(onePassSignature.certificate, onePassSignature.keyId));
|
||||||
if (verified) {
|
if (correct) {
|
||||||
layer.addVerifiedSignature(verification);
|
PGPPublicKey signingKey = onePassSignature.certificate.getPublicKey(onePassSignature.keyId);
|
||||||
|
try {
|
||||||
|
checkSignatureValidity(signature, signingKey, policy);
|
||||||
|
layer.addVerifiedOnePassSignature(verification);
|
||||||
|
} catch (SignatureValidationException e) {
|
||||||
|
layer.addRejectedOnePassSignature(new SignatureVerification.Failure(verification, e));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
layer.addFailedSignature(new SignatureVerification.Failure(verification,
|
layer.addRejectedOnePassSignature(new SignatureVerification.Failure(verification,
|
||||||
new SignatureValidationException("Incorrect Signature.")));
|
new SignatureValidationException("Bad Signature.")));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean checkSignatureValidity(PGPSignature signature, PGPPublicKey signingKey, Policy policy) throws SignatureValidationException {
|
||||||
|
SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature);
|
||||||
|
SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature);
|
||||||
|
SignatureValidator.signatureIsEffective().verify(signature);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void enterNesting() {
|
void enterNesting() {
|
||||||
opsUpdateStack.push(literalOPS);
|
opsUpdateStack.push(literalOPS);
|
||||||
literalOPS = new ArrayList<>();
|
literalOPS = new ArrayList<>();
|
||||||
|
@ -699,27 +721,39 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish(MessageMetadata.Layer layer) {
|
public void finish(MessageMetadata.Layer layer, Policy policy) {
|
||||||
for (DetachedOrPrependedSignature detached : detachedSignatures) {
|
for (DetachedOrPrependedSignature detached : detachedSignatures) {
|
||||||
boolean verified = detached.verify();
|
boolean correct = detached.verify();
|
||||||
SignatureVerification verification = new SignatureVerification(
|
SignatureVerification verification = new SignatureVerification(
|
||||||
detached.signature, new SubkeyIdentifier(detached.certificate, detached.keyId));
|
detached.signature, new SubkeyIdentifier(detached.certificate, detached.keyId));
|
||||||
if (verified) {
|
if (correct) {
|
||||||
layer.addVerifiedSignature(verification);
|
try {
|
||||||
|
PGPPublicKey signingKey = detached.certificate.getPublicKey(detached.keyId);
|
||||||
|
checkSignatureValidity(detached.signature, signingKey, policy);
|
||||||
|
layer.addVerifiedDetachedSignature(verification);
|
||||||
|
} catch (SignatureValidationException e) {
|
||||||
|
layer.addRejectedDetachedSignature(new SignatureVerification.Failure(verification, e));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
layer.addFailedSignature(new SignatureVerification.Failure(
|
layer.addRejectedDetachedSignature(new SignatureVerification.Failure(
|
||||||
verification, new SignatureValidationException("Incorrect Signature.")));
|
verification, new SignatureValidationException("Incorrect Signature.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DetachedOrPrependedSignature prepended : prependedSignatures) {
|
for (DetachedOrPrependedSignature prepended : prependedSignatures) {
|
||||||
boolean verified = prepended.verify();
|
boolean correct = prepended.verify();
|
||||||
SignatureVerification verification = new SignatureVerification(
|
SignatureVerification verification = new SignatureVerification(
|
||||||
prepended.signature, new SubkeyIdentifier(prepended.certificate, prepended.keyId));
|
prepended.signature, new SubkeyIdentifier(prepended.certificate, prepended.keyId));
|
||||||
if (verified) {
|
if (correct) {
|
||||||
layer.addVerifiedSignature(verification);
|
try {
|
||||||
|
PGPPublicKey signingKey = prepended.certificate.getPublicKey(prepended.keyId);
|
||||||
|
checkSignatureValidity(prepended.signature, signingKey, policy);
|
||||||
|
layer.addVerifiedPrependedSignature(verification);
|
||||||
|
} catch (SignatureValidationException e) {
|
||||||
|
layer.addRejectedPrependedSignature(new SignatureVerification.Failure(verification, e));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
layer.addFailedSignature(new SignatureVerification.Failure(
|
layer.addRejectedPrependedSignature(new SignatureVerification.Failure(
|
||||||
verification, new SignatureValidationException("Incorrect Signature.")));
|
verification, new SignatureValidationException("Incorrect Signature.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -859,46 +893,18 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
resultBuilder.setFileEncoding(m.getFormat());
|
resultBuilder.setFileEncoding(m.getFormat());
|
||||||
resultBuilder.setSessionKey(m.getSessionKey());
|
resultBuilder.setSessionKey(m.getSessionKey());
|
||||||
|
|
||||||
for (Signatures.OnePassSignature ops : signatures.onePassSignatures) {
|
for (SignatureVerification accepted : m.getVerifiedDetachedSignatures()) {
|
||||||
if (!ops.finished) {
|
resultBuilder.addVerifiedDetachedSignature(accepted);
|
||||||
continue;
|
}
|
||||||
}
|
for (SignatureVerification.Failure rejected : m.getRejectedDetachedSignatures()) {
|
||||||
|
resultBuilder.addInvalidDetachedSignature(rejected.getSignatureVerification(), rejected.getValidationException());
|
||||||
SubkeyIdentifier identifier = new SubkeyIdentifier(ops.certificate, ops.keyId);
|
|
||||||
SignatureVerification verification = new SignatureVerification(ops.signature, identifier);
|
|
||||||
if (ops.valid) {
|
|
||||||
resultBuilder.addVerifiedInbandSignature(verification);
|
|
||||||
} else {
|
|
||||||
resultBuilder.addInvalidInbandSignature(verification, new SignatureValidationException("Incorrect signature."));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Signatures.DetachedOrPrependedSignature prep : signatures.prependedSignatures) {
|
for (SignatureVerification accepted : m.getVerifiedInlineSignatures()) {
|
||||||
if (!prep.finished) {
|
resultBuilder.addVerifiedInbandSignature(accepted);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubkeyIdentifier identifier = new SubkeyIdentifier(prep.certificate, prep.keyId);
|
|
||||||
SignatureVerification verification = new SignatureVerification(prep.signature, identifier);
|
|
||||||
if (prep.valid) {
|
|
||||||
resultBuilder.addVerifiedInbandSignature(verification);
|
|
||||||
} else {
|
|
||||||
resultBuilder.addInvalidInbandSignature(verification, new SignatureValidationException("Incorrect signature."));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (SignatureVerification.Failure rejected : m.getRejectedInlineSignatures()) {
|
||||||
for (Signatures.DetachedOrPrependedSignature det : signatures.detachedSignatures) {
|
resultBuilder.addInvalidInbandSignature(rejected.getSignatureVerification(), rejected.getValidationException());
|
||||||
if (!det.finished) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubkeyIdentifier identifier = new SubkeyIdentifier(det.certificate, det.keyId);
|
|
||||||
SignatureVerification verification = new SignatureVerification(det.signature, identifier);
|
|
||||||
if (det.valid) {
|
|
||||||
resultBuilder.addVerifiedDetachedSignature(verification);
|
|
||||||
} else {
|
|
||||||
resultBuilder.addInvalidDetachedSignature(verification, new SignatureValidationException("Incorrect signature."));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultBuilder.build();
|
return resultBuilder.build();
|
||||||
|
|
|
@ -332,8 +332,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
assertEquals("", metadata.getFilename());
|
assertEquals("", metadata.getFilename());
|
||||||
JUtils.assertDateEquals(new Date(0L), metadata.getModificationDate());
|
JUtils.assertDateEquals(new Date(0L), metadata.getModificationDate());
|
||||||
assertEquals(StreamEncoding.BINARY, metadata.getFormat());
|
assertEquals(StreamEncoding.BINARY, metadata.getFormat());
|
||||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
assertTrue(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process LIT LIT using {0}")
|
@ParameterizedTest(name = "Process LIT LIT using {0}")
|
||||||
|
@ -352,8 +352,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
assertEquals(PLAINTEXT, plain);
|
assertEquals(PLAINTEXT, plain);
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
|
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
|
||||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
assertTrue(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process COMP using {0}")
|
@ParameterizedTest(name = "Process COMP using {0}")
|
||||||
|
@ -377,8 +377,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
assertEquals(CompressionAlgorithm.BZIP2, compressionAlgorithms.next());
|
assertEquals(CompressionAlgorithm.BZIP2, compressionAlgorithms.next());
|
||||||
assertFalse(compressionAlgorithms.hasNext());
|
assertFalse(compressionAlgorithms.hasNext());
|
||||||
assertNull(metadata.getEncryptionAlgorithm());
|
assertNull(metadata.getEncryptionAlgorithm());
|
||||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
assertTrue(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process SIG COMP(LIT) using {0}")
|
@ParameterizedTest(name = "Process SIG COMP(LIT) using {0}")
|
||||||
|
@ -395,8 +395,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
|
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
|
||||||
assertNull(metadata.getEncryptionAlgorithm());
|
assertNull(metadata.getEncryptionAlgorithm());
|
||||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
assertFalse(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process SENC(LIT) using {0}")
|
@ParameterizedTest(name = "Process SENC(LIT) using {0}")
|
||||||
|
@ -410,8 +410,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertNull(metadata.getCompressionAlgorithm());
|
assertNull(metadata.getCompressionAlgorithm());
|
||||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
assertTrue(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process PENC(COMP(LIT)) using {0}")
|
@ParameterizedTest(name = "Process PENC(COMP(LIT)) using {0}")
|
||||||
|
@ -426,8 +426,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm());
|
assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm());
|
||||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
assertTrue(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process OPS LIT SIG using {0}")
|
@ParameterizedTest(name = "Process OPS LIT SIG using {0}")
|
||||||
|
@ -442,8 +442,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertNull(metadata.getEncryptionAlgorithm());
|
assertNull(metadata.getEncryptionAlgorithm());
|
||||||
assertNull(metadata.getCompressionAlgorithm());
|
assertNull(metadata.getCompressionAlgorithm());
|
||||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
assertFalse(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||||
|
@ -579,8 +579,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||||
assertNull(metadata.getCompressionAlgorithm());
|
assertNull(metadata.getCompressionAlgorithm());
|
||||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
assertFalse(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}")
|
@ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}")
|
||||||
|
@ -644,8 +644,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
MessageMetadata metadata = result.getB();
|
MessageMetadata metadata = result.getB();
|
||||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||||
assertNull(metadata.getCompressionAlgorithm());
|
assertNull(metadata.getCompressionAlgorithm());
|
||||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
assertFalse(metadata.getVerifiedInlineSignatures().isEmpty());
|
||||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
assertTrue(metadata.getRejectedInlineSignatures().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Tuple<String, MessageMetadata> processReadBuffered(String armoredMessage, ConsumerOptions options)
|
private static Tuple<String, MessageMetadata> processReadBuffered(String armoredMessage, ConsumerOptions options)
|
||||||
|
|
Loading…
Reference in a new issue