1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-23 04:42:06 +01:00

First Refactoring of DecryptionStreamFactory

This commit is contained in:
Paul Schaub 2020-01-10 17:12:13 +01:00
parent be33206d03
commit db09a0ffbe
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311

View file

@ -65,7 +65,7 @@ public final class DecryptionStreamFactory {
private final OpenPgpMetadata.Builder resultBuilder = OpenPgpMetadata.getBuilder(); private final OpenPgpMetadata.Builder resultBuilder = OpenPgpMetadata.getBuilder();
private final PGPContentVerifierBuilderProvider verifierBuilderProvider = new BcPGPContentVerifierBuilderProvider(); private final PGPContentVerifierBuilderProvider verifierBuilderProvider = new BcPGPContentVerifierBuilderProvider();
private final KeyFingerPrintCalculator fingerCalc = new BcKeyFingerprintCalculator(); private final KeyFingerPrintCalculator keyFingerprintCalculator = new BcKeyFingerprintCalculator();
private final Map<OpenPgpV4Fingerprint, PGPOnePassSignature> verifiableOnePassSignatures = new HashMap<>(); private final Map<OpenPgpV4Fingerprint, PGPOnePassSignature> verifiableOnePassSignatures = new HashMap<>();
private DecryptionStreamFactory(@Nullable PGPSecretKeyRingCollection decryptionKeys, private DecryptionStreamFactory(@Nullable PGPSecretKeyRingCollection decryptionKeys,
@ -85,51 +85,65 @@ public final class DecryptionStreamFactory {
@Nullable MissingPublicKeyCallback missingPublicKeyCallback) @Nullable MissingPublicKeyCallback missingPublicKeyCallback)
throws IOException, PGPException { throws IOException, PGPException {
DecryptionStreamFactory factory = new DecryptionStreamFactory(decryptionKeys, DecryptionStreamFactory factory = new DecryptionStreamFactory(decryptionKeys, decryptor, verificationKeys,
decryptor,
verificationKeys,
missingPublicKeyCallback); missingPublicKeyCallback);
PGPObjectFactory objectFactory = new PGPObjectFactory( PGPObjectFactory objectFactory = new PGPObjectFactory(
PGPUtil.getDecoderStream(inputStream), new BcKeyFingerprintCalculator()); PGPUtil.getDecoderStream(inputStream), new BcKeyFingerprintCalculator());
return new DecryptionStream(factory.wrap(objectFactory), factory.resultBuilder); return new DecryptionStream(factory.processPGPPackets(objectFactory), factory.resultBuilder);
} }
private InputStream wrap(@Nonnull PGPObjectFactory objectFactory) throws IOException, PGPException { private InputStream processPGPPackets(@Nonnull PGPObjectFactory objectFactory) throws IOException, PGPException {
Object pgpObj; Object nextPgpObject;
while ((pgpObj = objectFactory.nextObject()) != null) { while ((nextPgpObject = objectFactory.nextObject()) != null) {
if (nextPgpObject instanceof PGPEncryptedDataList) {
return processPGPEncryptedDataList((PGPEncryptedDataList) nextPgpObject);
}
if (nextPgpObject instanceof PGPCompressedData) {
return processPGPCompressedData((PGPCompressedData) nextPgpObject);
}
if (nextPgpObject instanceof PGPOnePassSignatureList) {
return processOnePassSignatureList(objectFactory, (PGPOnePassSignatureList) nextPgpObject);
}
if (nextPgpObject instanceof PGPLiteralData) {
return processPGPLiteralData(objectFactory, (PGPLiteralData) nextPgpObject);
}
}
if (pgpObj instanceof PGPEncryptedDataList) { throw new PGPException("No Literal Data Packet found");
}
private InputStream processPGPEncryptedDataList(PGPEncryptedDataList pgpEncryptedDataList)
throws PGPException, IOException {
LOGGER.log(LEVEL, "Encountered PGPEncryptedDataList"); LOGGER.log(LEVEL, "Encountered PGPEncryptedDataList");
PGPEncryptedDataList encDataList = (PGPEncryptedDataList) pgpObj; InputStream decryptedDataStream = decrypt(pgpEncryptedDataList);
InputStream nextStream = decrypt(encDataList); return processPGPPackets(new PGPObjectFactory(PGPUtil.getDecoderStream(decryptedDataStream), keyFingerprintCalculator));
objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(nextStream), fingerCalc);
return wrap(objectFactory);
} }
if (pgpObj instanceof PGPCompressedData) { private InputStream processPGPCompressedData(PGPCompressedData pgpCompressedData)
PGPCompressedData compressedData = (PGPCompressedData) pgpObj; throws PGPException, IOException {
InputStream nextStream = compressedData.getDataStream(); CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.fromId(pgpCompressedData.getAlgorithm());
resultBuilder.setCompressionAlgorithm(CompressionAlgorithm.fromId(compressedData.getAlgorithm())); LOGGER.log(LEVEL, "Encountered PGPCompressedData: " + compressionAlgorithm);
objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(nextStream), fingerCalc); resultBuilder.setCompressionAlgorithm(compressionAlgorithm);
LOGGER.log(LEVEL, "Encountered PGPCompressedData: " +
CompressionAlgorithm.fromId(compressedData.getAlgorithm())); InputStream dataStream = pgpCompressedData.getDataStream();
return wrap(objectFactory); PGPObjectFactory objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(dataStream), keyFingerprintCalculator);
return processPGPPackets(objectFactory);
} }
if (pgpObj instanceof PGPOnePassSignatureList) { private InputStream processOnePassSignatureList(@Nonnull PGPObjectFactory objectFactory, PGPOnePassSignatureList onePassSignatures)
PGPOnePassSignatureList onePassSignatures = (PGPOnePassSignatureList) pgpObj; throws PGPException, IOException {
LOGGER.log(LEVEL, "Encountered PGPOnePassSignatureList of size " + onePassSignatures.size()); LOGGER.log(LEVEL, "Encountered PGPOnePassSignatureList of size " + onePassSignatures.size());
initOnePassSignatures(onePassSignatures); initOnePassSignatures(onePassSignatures);
return wrap(objectFactory); return processPGPPackets(objectFactory);
} }
if (pgpObj instanceof PGPLiteralData) { private InputStream processPGPLiteralData(@Nonnull PGPObjectFactory objectFactory, PGPLiteralData pgpLiteralData) {
LOGGER.log(LEVEL, "Found PGPLiteralData"); LOGGER.log(LEVEL, "Found PGPLiteralData");
PGPLiteralData literalData = (PGPLiteralData) pgpObj; InputStream literalDataInputStream = pgpLiteralData.getInputStream();
InputStream literalDataInputStream = literalData.getInputStream();
if (verifiableOnePassSignatures.isEmpty()) { if (verifiableOnePassSignatures.isEmpty()) {
LOGGER.log(LEVEL, "No OnePassSignatures found -> We are done"); LOGGER.log(LEVEL, "No OnePassSignatures found -> We are done");
@ -139,22 +153,18 @@ public final class DecryptionStreamFactory {
return new SignatureVerifyingInputStream(literalDataInputStream, return new SignatureVerifyingInputStream(literalDataInputStream,
objectFactory, verifiableOnePassSignatures, resultBuilder); objectFactory, verifiableOnePassSignatures, resultBuilder);
} }
}
throw new PGPException("No Literal Data Packet found");
}
private InputStream decrypt(@Nonnull PGPEncryptedDataList encryptedDataList) private InputStream decrypt(@Nonnull PGPEncryptedDataList encryptedDataList)
throws PGPException { throws PGPException {
Iterator<?> iterator = encryptedDataList.getEncryptedDataObjects(); Iterator<?> encryptedDataIterator = encryptedDataList.getEncryptedDataObjects();
if (!iterator.hasNext()) { if (!encryptedDataIterator.hasNext()) {
throw new PGPException("Decryption failed - EncryptedDataList has no items"); throw new PGPException("Decryption failed - EncryptedDataList has no items");
} }
PGPPrivateKey decryptionKey = null; PGPPrivateKey decryptionKey = null;
PGPPublicKeyEncryptedData encryptedSessionKey = null; PGPPublicKeyEncryptedData encryptedSessionKey = null;
while (iterator.hasNext()) { while (encryptedDataIterator.hasNext()) {
PGPPublicKeyEncryptedData encryptedData = (PGPPublicKeyEncryptedData) iterator.next(); PGPPublicKeyEncryptedData encryptedData = (PGPPublicKeyEncryptedData) encryptedDataIterator.next();
long keyId = encryptedData.getKeyID(); long keyId = encryptedData.getKeyID();
resultBuilder.addRecipientKeyId(keyId); resultBuilder.addRecipientKeyId(keyId);
@ -187,9 +197,8 @@ public final class DecryptionStreamFactory {
LOGGER.log(LEVEL, "Message is not integrity protected"); LOGGER.log(LEVEL, "Message is not integrity protected");
resultBuilder.setIntegrityProtected(false); resultBuilder.setIntegrityProtected(false);
} }
InputStream decryptionStream = encryptedSessionKey.getDataStream(keyDecryptor);
return decryptionStream; return encryptedSessionKey.getDataStream(keyDecryptor);
} }
private void initOnePassSignatures(@Nonnull PGPOnePassSignatureList onePassSignatureList) throws PGPException { private void initOnePassSignatures(@Nonnull PGPOnePassSignatureList onePassSignatureList) throws PGPException {
@ -204,33 +213,57 @@ public final class DecryptionStreamFactory {
private void processOnePassSignatures(Iterator<PGPOnePassSignature> signatures) throws PGPException { private void processOnePassSignatures(Iterator<PGPOnePassSignature> signatures) throws PGPException {
while (signatures.hasNext()) { while (signatures.hasNext()) {
PGPOnePassSignature signature = signatures.next(); PGPOnePassSignature signature = signatures.next();
processOnePassSignature(signature);
}
}
private void processOnePassSignature(PGPOnePassSignature signature) throws PGPException {
final long keyId = signature.getKeyID(); final long keyId = signature.getKeyID();
resultBuilder.addUnverifiedSignatureKeyId(keyId); resultBuilder.addUnverifiedSignatureKeyId(keyId);
LOGGER.log(LEVEL, "Message contains OnePassSignature from " + Long.toHexString(keyId)); LOGGER.log(LEVEL, "Message contains OnePassSignature from " + Long.toHexString(keyId));
// Find public key // Find public key
PGPPublicKey verificationKey = findSignatureVerificationKey(keyId);
if (verificationKey == null) {
return;
}
signature.init(verifierBuilderProvider, verificationKey);
verifiableOnePassSignatures.put(new OpenPgpV4Fingerprint(verificationKey), signature);
}
private PGPPublicKey findSignatureVerificationKey(long keyId) {
PGPPublicKey verificationKey = null; PGPPublicKey verificationKey = null;
for (PGPPublicKeyRing publicKeyRing : verificationKeys) { for (PGPPublicKeyRing publicKeyRing : verificationKeys) {
verificationKey = publicKeyRing.getPublicKey(keyId); verificationKey = publicKeyRing.getPublicKey(keyId);
if (verificationKey != null) { if (verificationKey != null) {
LOGGER.log(LEVEL, "Found respective public key " + Long.toHexString(keyId)); LOGGER.log(LEVEL, "Found public key " + Long.toHexString(keyId) + " for signature verification");
break; break;
} }
} }
if (verificationKey == null) { if (verificationKey == null) {
LOGGER.log(Level.FINER, "No public key for signature of " + Long.toHexString(keyId) + " found."); verificationKey = handleMissingVerificationKey(keyId);
}
return verificationKey;
}
private PGPPublicKey handleMissingVerificationKey(long keyId) {
LOGGER.log(Level.FINER, "No public key found for signature of " + Long.toHexString(keyId));
if (missingPublicKeyCallback == null) { if (missingPublicKeyCallback == null) {
LOGGER.log(Level.FINER, "Skip signature of " + Long.toHexString(keyId)); LOGGER.log(Level.FINER, "No MissingPublicKeyCallback registered. " +
continue; "Skip signature of " + Long.toHexString(keyId));
return null;
} }
PGPPublicKey missingPublicKey = missingPublicKeyCallback.onMissingPublicKeyEncountered(keyId); PGPPublicKey missingPublicKey = missingPublicKeyCallback.onMissingPublicKeyEncountered(keyId);
if (missingPublicKey == null) { if (missingPublicKey == null) {
LOGGER.log(Level.FINER, "Skip signature of " + Long.toHexString(keyId)); LOGGER.log(Level.FINER, "MissingPublicKeyCallback did not provider key. " +
continue; "Skip signature of " + Long.toHexString(keyId));
return null;
} }
if (missingPublicKey.getKeyID() != keyId) { if (missingPublicKey.getKeyID() != keyId) {
@ -239,11 +272,6 @@ public final class DecryptionStreamFactory {
Long.toHexString(missingPublicKey.getKeyID())); Long.toHexString(missingPublicKey.getKeyID()));
} }
verificationKey = missingPublicKey; return missingPublicKey;
}
signature.init(verifierBuilderProvider, verificationKey);
verifiableOnePassSignatures.put(new OpenPgpV4Fingerprint(verificationKey), signature);
}
} }
} }