mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-16 01:12:05 +01:00
Add detailled logging to OpenPgpMessageInputStream
This commit is contained in:
parent
789a0086c9
commit
f67f1954e7
3 changed files with 82 additions and 19 deletions
|
@ -59,6 +59,7 @@ import org.pgpainless.key.SubkeyIdentifier;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
|
import org.pgpainless.key.util.KeyIdUtil;
|
||||||
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.OnePassSignatureCheck;
|
import org.pgpainless.signature.consumer.OnePassSignatureCheck;
|
||||||
|
@ -234,6 +235,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
|
|
||||||
// Marker Packets need to be skipped and ignored
|
// Marker Packets need to be skipped and ignored
|
||||||
case MARKER:
|
case MARKER:
|
||||||
|
LOGGER.debug("Skipping Marker Packet");
|
||||||
packetInputStream.readMarker();
|
packetInputStream.readMarker();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -263,6 +265,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processLiteralData() throws IOException {
|
private void processLiteralData() throws IOException {
|
||||||
|
LOGGER.debug("Literal Data Packet at depth " + metadata.depth + " encountered");
|
||||||
automaton.next(InputAlphabet.LiteralData);
|
automaton.next(InputAlphabet.LiteralData);
|
||||||
PGPLiteralData literalData = packetInputStream.readLiteralData();
|
PGPLiteralData literalData = packetInputStream.readLiteralData();
|
||||||
this.metadata.setChild(new MessageMetadata.LiteralData(
|
this.metadata.setChild(new MessageMetadata.LiteralData(
|
||||||
|
@ -279,6 +282,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData(
|
MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData(
|
||||||
CompressionAlgorithm.fromId(compressedData.getAlgorithm()),
|
CompressionAlgorithm.fromId(compressedData.getAlgorithm()),
|
||||||
metadata.depth + 1);
|
metadata.depth + 1);
|
||||||
|
LOGGER.debug("Compressed Data Packet (" + compressionLayer.algorithm + ") at depth " + metadata.depth + " encountered");
|
||||||
InputStream decompressed = compressedData.getDataStream();
|
InputStream decompressed = compressedData.getDataStream();
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decompressed), options, compressionLayer, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(decompressed), options, compressionLayer, policy);
|
||||||
}
|
}
|
||||||
|
@ -286,6 +290,8 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
private void processOnePassSignature() throws PGPException, IOException {
|
private void processOnePassSignature() throws PGPException, IOException {
|
||||||
automaton.next(InputAlphabet.OnePassSignature);
|
automaton.next(InputAlphabet.OnePassSignature);
|
||||||
PGPOnePassSignature onePassSignature = packetInputStream.readOnePassSignature();
|
PGPOnePassSignature onePassSignature = packetInputStream.readOnePassSignature();
|
||||||
|
LOGGER.debug("One-Pass-Signature Packet by key " + KeyIdUtil.formatKeyId(onePassSignature.getKeyID()) +
|
||||||
|
"at depth " + metadata.depth + " encountered");
|
||||||
signatures.addOnePassSignature(onePassSignature);
|
signatures.addOnePassSignature(onePassSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,42 +300,59 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
|
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
|
||||||
automaton.next(InputAlphabet.Signature);
|
automaton.next(InputAlphabet.Signature);
|
||||||
PGPSignature signature = packetInputStream.readSignature();
|
PGPSignature signature = packetInputStream.readSignature();
|
||||||
|
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
||||||
if (isSigForOPS) {
|
if (isSigForOPS) {
|
||||||
|
LOGGER.debug("Signature Packet corresponding to One-Pass-Signature by key " +
|
||||||
|
KeyIdUtil.formatKeyId(keyId) +
|
||||||
|
" at depth " + metadata.depth + " encountered");
|
||||||
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, policy);
|
signatures.addCorrespondingOnePassSignature(signature, metadata, policy);
|
||||||
} else {
|
} else {
|
||||||
|
LOGGER.debug("Prepended Signature Packet by key " +
|
||||||
|
KeyIdUtil.formatKeyId(keyId) +
|
||||||
|
" at depth " + metadata.depth + " encountered");
|
||||||
signatures.addPrependedSignature(signature);
|
signatures.addPrependedSignature(signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean processEncryptedData() throws IOException, PGPException {
|
private boolean processEncryptedData() throws IOException, PGPException {
|
||||||
|
LOGGER.debug("Symmetrically Encrypted Data Packet at depth " + metadata.depth + " encountered");
|
||||||
automaton.next(InputAlphabet.EncryptedData);
|
automaton.next(InputAlphabet.EncryptedData);
|
||||||
PGPEncryptedDataList encDataList = packetInputStream.readEncryptedDataList();
|
PGPEncryptedDataList encDataList = packetInputStream.readEncryptedDataList();
|
||||||
|
|
||||||
// TODO: Replace with !encDataList.isIntegrityProtected()
|
// TODO: Replace with !encDataList.isIntegrityProtected()
|
||||||
// once BC ships it
|
// once BC ships it
|
||||||
if (!encDataList.get(0).isIntegrityProtected()) {
|
if (!encDataList.get(0).isIntegrityProtected()) {
|
||||||
|
LOGGER.debug("Symmetrically Encrypted Data Packet is not integrity-protected and is therefore rejected.");
|
||||||
throw new MessageNotIntegrityProtectedException();
|
throw new MessageNotIntegrityProtectedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedESKs esks = new SortedESKs(encDataList);
|
SortedESKs esks = new SortedESKs(encDataList);
|
||||||
|
LOGGER.debug("Symmetrically Encrypted Integrity-Protected Data has " +
|
||||||
|
esks.skesks.size() + " SKESK(s) and " +
|
||||||
|
(esks.pkesks.size() + esks.anonPkesks.size()) + " PKESK(s) from which " +
|
||||||
|
esks.anonPkesks.size() + " PKESK(s) have an anonymous recipient");
|
||||||
|
|
||||||
// Try custom decryptor factory
|
// Try custom decryptor factories
|
||||||
for (SubkeyIdentifier subkeyIdentifier : options.getCustomDecryptorFactories().keySet()) {
|
for (SubkeyIdentifier subkeyIdentifier : options.getCustomDecryptorFactories().keySet()) {
|
||||||
|
LOGGER.debug("Attempt decryption with custom decryptor factory with key " + subkeyIdentifier);
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = options.getCustomDecryptorFactories().get(subkeyIdentifier);
|
PublicKeyDataDecryptorFactory decryptorFactory = options.getCustomDecryptorFactories().get(subkeyIdentifier);
|
||||||
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
||||||
|
// find matching PKESK
|
||||||
if (pkesk.getKeyID() != subkeyIdentifier.getSubkeyId()) {
|
if (pkesk.getKeyID() != subkeyIdentifier.getSubkeyId()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attempt decryption
|
||||||
if (decryptPKESKAndStream(subkeyIdentifier, decryptorFactory, pkesk)) {
|
if (decryptPKESKAndStream(subkeyIdentifier, decryptorFactory, pkesk)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try session key
|
// Try provided session key
|
||||||
if (options.getSessionKey() != null) {
|
if (options.getSessionKey() != null) {
|
||||||
|
LOGGER.debug("Attempt decryption with provided session key");
|
||||||
SessionKey sessionKey = options.getSessionKey();
|
SessionKey sessionKey = options.getSessionKey();
|
||||||
throwIfUnacceptable(sessionKey.getAlgorithm());
|
throwIfUnacceptable(sessionKey.getAlgorithm());
|
||||||
|
|
||||||
|
@ -340,6 +363,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: Use BCs new API once shipped
|
// TODO: Use BCs new API once shipped
|
||||||
|
// see https://github.com/bcgit/bc-java/pull/1228 (discussion)
|
||||||
PGPEncryptedData esk = esks.all().get(0);
|
PGPEncryptedData esk = esks.all().get(0);
|
||||||
if (esk instanceof PGPPBEEncryptedData) {
|
if (esk instanceof PGPPBEEncryptedData) {
|
||||||
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
||||||
|
@ -347,6 +371,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
encryptedData.sessionKey = sessionKey;
|
encryptedData.sessionKey = sessionKey;
|
||||||
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, skesk, options);
|
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, skesk, options);
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
||||||
|
LOGGER.debug("Successfully decrypted data with provided session key");
|
||||||
return true;
|
return true;
|
||||||
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
||||||
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
||||||
|
@ -354,20 +379,29 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
encryptedData.sessionKey = sessionKey;
|
encryptedData.sessionKey = sessionKey;
|
||||||
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, pkesk, options);
|
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, pkesk, options);
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
||||||
|
LOGGER.debug("Successfully decrypted data with provided session key");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName());
|
throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName());
|
||||||
}
|
}
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
// Session key mismatch?
|
// Session key mismatch?
|
||||||
|
LOGGER.debug("Decryption using provided session key failed. Mismatched session key and message?", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try passwords
|
// Try passwords
|
||||||
for (PGPPBEEncryptedData skesk : esks.skesks) {
|
|
||||||
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
|
||||||
throwIfUnacceptable(kekAlgorithm);
|
|
||||||
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
||||||
|
for (PGPPBEEncryptedData skesk : esks.skesks) {
|
||||||
|
LOGGER.debug("Attempt decryption with provided passphrase");
|
||||||
|
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
||||||
|
try {
|
||||||
|
throwIfUnacceptable(kekAlgorithm);
|
||||||
|
} catch (UnacceptableAlgorithmException e) {
|
||||||
|
LOGGER.debug("Skipping SKESK with unacceptable encapsulation algorithm", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPBEDataDecryptorFactory(passphrase);
|
.getPBEDataDecryptorFactory(passphrase);
|
||||||
|
|
||||||
|
@ -381,22 +415,25 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
// Try (known) secret keys
|
// Try (known) secret keys
|
||||||
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
||||||
long keyId = pkesk.getKeyID();
|
long keyId = pkesk.getKeyID();
|
||||||
|
LOGGER.debug("Encountered PKESK with recipient " + KeyIdUtil.formatKeyId(keyId));
|
||||||
PGPSecretKeyRing decryptionKeys = getDecryptionKey(keyId);
|
PGPSecretKeyRing decryptionKeys = getDecryptionKey(keyId);
|
||||||
if (decryptionKeys == null) {
|
if (decryptionKeys == null) {
|
||||||
|
LOGGER.debug("Skipping PKESK because no matching key " + KeyIdUtil.formatKeyId(keyId) + " was provided");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PGPSecretKey secretKey = decryptionKeys.getSecretKey(keyId);
|
PGPSecretKey secretKey = decryptionKeys.getSecretKey(keyId);
|
||||||
|
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, secretKey.getKeyID());
|
||||||
|
LOGGER.debug("Attempt decryption using secret key " + decryptionKeyId);
|
||||||
|
|
||||||
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeys);
|
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeys);
|
||||||
// Postpone keys with missing passphrase
|
// Postpone keys with missing passphrase
|
||||||
if (!protector.hasPassphraseFor(keyId)) {
|
if (!protector.hasPassphraseFor(keyId)) {
|
||||||
|
LOGGER.debug("Missing passphrase for key " + decryptionKeyId + ". Postponing decryption until all other keys were tried");
|
||||||
postponedDueToMissingPassphrase.add(new Tuple<>(secretKey, pkesk));
|
postponedDueToMissingPassphrase.add(new Tuple<>(secretKey, pkesk));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSecretKey decryptionKey = decryptionKeys.getSecretKey(keyId);
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector);
|
||||||
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, decryptionKey.getKeyID());
|
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, protector);
|
|
||||||
|
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
.getPublicKeyDataDecryptorFactory(privateKey);
|
||||||
|
@ -408,16 +445,19 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
// try anonymous secret keys
|
// try anonymous secret keys
|
||||||
for (PGPPublicKeyEncryptedData pkesk : esks.anonPkesks) {
|
for (PGPPublicKeyEncryptedData pkesk : esks.anonPkesks) {
|
||||||
for (Tuple<PGPSecretKeyRing, PGPSecretKey> decryptionKeyCandidate : findPotentialDecryptionKeys(pkesk)) {
|
for (Tuple<PGPSecretKeyRing, PGPSecretKey> decryptionKeyCandidate : findPotentialDecryptionKeys(pkesk)) {
|
||||||
|
PGPSecretKeyRing decryptionKeys = decryptionKeyCandidate.getA();
|
||||||
PGPSecretKey secretKey = decryptionKeyCandidate.getB();
|
PGPSecretKey secretKey = decryptionKeyCandidate.getB();
|
||||||
|
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeys, secretKey.getKeyID());
|
||||||
|
LOGGER.debug("Attempt decryption of anonymous PKESK with key " + decryptionKeyId);
|
||||||
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeyCandidate.getA());
|
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeyCandidate.getA());
|
||||||
if (!protector.hasPassphraseFor(secretKey.getKeyID())) {
|
if (!protector.hasPassphraseFor(secretKey.getKeyID())) {
|
||||||
|
LOGGER.debug("Missing passphrase for key " + decryptionKeyId + ". Postponing decryption until all other keys were tried.");
|
||||||
postponedDueToMissingPassphrase.add(new Tuple<>(secretKey, pkesk));
|
postponedDueToMissingPassphrase.add(new Tuple<>(secretKey, pkesk));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKeyCandidate.getB(), protector);
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKeyCandidate.getB(), protector);
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
.getPublicKeyDataDecryptorFactory(privateKey);
|
||||||
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKeyCandidate.getA(), privateKey.getKeyID());
|
|
||||||
|
|
||||||
if (decryptPKESKAndStream(decryptionKeyId, decryptorFactory, pkesk)) {
|
if (decryptPKESKAndStream(decryptionKeyId, decryptorFactory, pkesk)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -442,9 +482,10 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
PGPSecretKey secretKey = missingPassphrases.getA();
|
PGPSecretKey secretKey = missingPassphrases.getA();
|
||||||
long keyId = secretKey.getKeyID();
|
long keyId = secretKey.getKeyID();
|
||||||
PGPSecretKeyRing decryptionKey = getDecryptionKey(keyId);
|
PGPSecretKeyRing decryptionKey = getDecryptionKey(keyId);
|
||||||
|
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKey, keyId);
|
||||||
|
LOGGER.debug("Attempt decryption with key " + decryptionKeyId + " while interactively requesting its passphrase");
|
||||||
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKey);
|
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKey);
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector.getDecryptor(keyId));
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector.getDecryptor(keyId));
|
||||||
SubkeyIdentifier decryptionKeyId = new SubkeyIdentifier(decryptionKey, keyId);
|
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
.getPublicKeyDataDecryptorFactory(privateKey);
|
||||||
|
|
||||||
|
@ -458,10 +499,13 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we did not yet succeed in decrypting any session key :/
|
// we did not yet succeed in decrypting any session key :/
|
||||||
|
|
||||||
|
LOGGER.debug("Failed to decrypt encrypted data packet");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean decryptSKESKAndStream(PGPPBEEncryptedData skesk, PBEDataDecryptorFactory decryptorFactory) throws IOException, UnacceptableAlgorithmException {
|
private boolean decryptSKESKAndStream(PGPPBEEncryptedData skesk, PBEDataDecryptorFactory decryptorFactory)
|
||||||
|
throws IOException, UnacceptableAlgorithmException {
|
||||||
try {
|
try {
|
||||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||||
SessionKey sessionKey = new SessionKey(skesk.getSessionKey(decryptorFactory));
|
SessionKey sessionKey = new SessionKey(skesk.getSessionKey(decryptorFactory));
|
||||||
|
@ -469,18 +513,19 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
sessionKey.getAlgorithm(), metadata.depth + 1);
|
sessionKey.getAlgorithm(), metadata.depth + 1);
|
||||||
encryptedData.sessionKey = sessionKey;
|
encryptedData.sessionKey = sessionKey;
|
||||||
|
LOGGER.debug("Successfully decrypted data with passphrase");
|
||||||
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, skesk, options);
|
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, skesk, options);
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), 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?
|
LOGGER.debug("Decryption of encrypted data packet using password failed. Password mismatch?", e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean decryptPKESKAndStream(SubkeyIdentifier subkeyIdentifier,
|
private boolean decryptPKESKAndStream(SubkeyIdentifier decryptionKeyId,
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory,
|
PublicKeyDataDecryptorFactory decryptorFactory,
|
||||||
PGPPublicKeyEncryptedData pkesk)
|
PGPPublicKeyEncryptedData pkesk)
|
||||||
throws IOException, UnacceptableAlgorithmException {
|
throws IOException, UnacceptableAlgorithmException {
|
||||||
|
@ -492,16 +537,17 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)),
|
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)),
|
||||||
metadata.depth + 1);
|
metadata.depth + 1);
|
||||||
encryptedData.decryptionKey = subkeyIdentifier;
|
encryptedData.decryptionKey = decryptionKeyId;
|
||||||
encryptedData.sessionKey = sessionKey;
|
encryptedData.sessionKey = sessionKey;
|
||||||
|
|
||||||
|
LOGGER.debug("Successfully decrypted data with key " + decryptionKeyId);
|
||||||
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, pkesk, options);
|
IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, pkesk, options);
|
||||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
nestedInputStream = new OpenPgpMessageInputStream(buffer(integrityProtected), options, encryptedData, policy);
|
||||||
return true;
|
return true;
|
||||||
} catch (UnacceptableAlgorithmException e) {
|
} catch (UnacceptableAlgorithmException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
|
LOGGER.debug("Decryption of encrypted data packet using secret key failed.", e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -823,8 +869,10 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
SignatureValidator.signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter())
|
SignatureValidator.signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter())
|
||||||
.verify(signature);
|
.verify(signature);
|
||||||
SignatureVerifier.verifyOnePassSignature(signature, onePassSignature.getVerificationKeys().getPublicKey(signature.getKeyID()), onePassSignature, policy);
|
SignatureVerifier.verifyOnePassSignature(signature, onePassSignature.getVerificationKeys().getPublicKey(signature.getKeyID()), onePassSignature, policy);
|
||||||
|
LOGGER.debug("Acceptable signature by key " + verification.getSigningKey());
|
||||||
layer.addVerifiedOnePassSignature(verification);
|
layer.addVerifiedOnePassSignature(verification);
|
||||||
} catch (SignatureValidationException e) {
|
} catch (SignatureValidationException e) {
|
||||||
|
LOGGER.debug("Rejected signature by key " + verification.getSigningKey(), e);
|
||||||
layer.addRejectedOnePassSignature(new SignatureVerification.Failure(verification, e));
|
layer.addRejectedOnePassSignature(new SignatureVerification.Failure(verification, e));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -929,8 +977,10 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
detached.getSignature(),
|
detached.getSignature(),
|
||||||
detached.getSigningKeyRing().getPublicKey(detached.getSigningKeyIdentifier().getKeyId()),
|
detached.getSigningKeyRing().getPublicKey(detached.getSigningKeyIdentifier().getKeyId()),
|
||||||
policy, detached.getSignature().getCreationTime());
|
policy, detached.getSignature().getCreationTime());
|
||||||
|
LOGGER.debug("Acceptable signature by key " + verification.getSigningKey());
|
||||||
layer.addVerifiedDetachedSignature(verification);
|
layer.addVerifiedDetachedSignature(verification);
|
||||||
} catch (SignatureValidationException e) {
|
} catch (SignatureValidationException e) {
|
||||||
|
LOGGER.debug("Rejected signature by key " + verification.getSigningKey(), e);
|
||||||
layer.addRejectedDetachedSignature(new SignatureVerification.Failure(verification, e));
|
layer.addRejectedDetachedSignature(new SignatureVerification.Failure(verification, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -944,8 +994,10 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
||||||
prepended.getSignature(),
|
prepended.getSignature(),
|
||||||
prepended.getSigningKeyRing().getPublicKey(prepended.getSigningKeyIdentifier().getKeyId()),
|
prepended.getSigningKeyRing().getPublicKey(prepended.getSigningKeyIdentifier().getKeyId()),
|
||||||
policy, prepended.getSignature().getCreationTime());
|
policy, prepended.getSignature().getCreationTime());
|
||||||
|
LOGGER.debug("Acceptable signature by key " + verification.getSigningKey());
|
||||||
layer.addVerifiedPrependedSignature(verification);
|
layer.addVerifiedPrependedSignature(verification);
|
||||||
} catch (SignatureValidationException e) {
|
} catch (SignatureValidationException e) {
|
||||||
|
LOGGER.debug("Rejected signature by key " + verification.getSigningKey(), e);
|
||||||
layer.addRejectedPrependedSignature(new SignatureVerification.Failure(verification, e));
|
layer.addRejectedPrependedSignature(new SignatureVerification.Failure(verification, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
package org.pgpainless.decryption_verification.automaton;
|
package org.pgpainless.decryption_verification.automaton;
|
||||||
|
|
||||||
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
|
@ -15,11 +17,11 @@ import static org.pgpainless.decryption_verification.automaton.StackAlphabet.ter
|
||||||
public class PDA {
|
public class PDA {
|
||||||
|
|
||||||
private static int ID = 0;
|
private static int ID = 0;
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(PDA.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of states of the automaton.
|
* Set of states of the automaton.
|
||||||
* Each state defines its valid transitions in their {@link NestingPDA.State#transition(InputAlphabet, NestingPDA)}
|
* Each state defines its valid transitions in their {@link State#transition(InputAlphabet, PDA)} method.
|
||||||
* method.
|
|
||||||
*/
|
*/
|
||||||
public enum State {
|
public enum State {
|
||||||
|
|
||||||
|
@ -199,7 +201,12 @@ public class PDA {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void next(InputAlphabet input) throws MalformedOpenPgpMessageException {
|
public void next(InputAlphabet input) throws MalformedOpenPgpMessageException {
|
||||||
|
try {
|
||||||
state = state.transition(input, this);
|
state = state.transition(input, this);
|
||||||
|
} catch (MalformedOpenPgpMessageException e) {
|
||||||
|
LOGGER.debug("Unexpected Packet or Token '" + input + "' encountered. Message is malformed.", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,4 +30,8 @@ public final class KeyIdUtil {
|
||||||
|
|
||||||
return new BigInteger(longKeyId, 16).longValue();
|
return new BigInteger(longKeyId, 16).longValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatKeyId(long keyId) {
|
||||||
|
return Long.toHexString(keyId).toUpperCase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue