use of org.bouncycastle.openpgp.PGPEncryptedData in project pgpainless by pgpainless.
the class DecryptionStreamFactory method decryptWithProvidedSessionKey.
private IntegrityProtectedInputStream decryptWithProvidedSessionKey(PGPEncryptedDataList pgpEncryptedDataList, SessionKey sessionKey) throws PGPException {
PGPSessionKey pgpSessionKey = new PGPSessionKey(sessionKey.getAlgorithm().getAlgorithmId(), sessionKey.getKey());
SessionKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance().provideSessionKeyDataDecryptorFactory(pgpSessionKey);
InputStream decryptedDataStream = null;
PGPEncryptedData encryptedData = null;
for (PGPEncryptedData pgpEncryptedData : pgpEncryptedDataList) {
encryptedData = pgpEncryptedData;
if (!options.isIgnoreMDCErrors() && !encryptedData.isIntegrityProtected()) {
throw new MessageNotIntegrityProtectedException();
}
if (encryptedData instanceof PGPPBEEncryptedData) {
PGPPBEEncryptedData pbeEncrypted = (PGPPBEEncryptedData) encryptedData;
decryptedDataStream = pbeEncrypted.getDataStream(decryptorFactory);
break;
} else if (encryptedData instanceof PGPPublicKeyEncryptedData) {
PGPPublicKeyEncryptedData pkEncrypted = (PGPPublicKeyEncryptedData) encryptedData;
decryptedDataStream = pkEncrypted.getDataStream(decryptorFactory);
break;
}
}
if (decryptedDataStream == null) {
throw new PGPException("No valid PGP data encountered.");
}
resultBuilder.setSessionKey(sessionKey);
throwIfAlgorithmIsRejected(sessionKey.getAlgorithm());
integrityProtectedEncryptedInputStream = new IntegrityProtectedInputStream(decryptedDataStream, encryptedData, options);
return integrityProtectedEncryptedInputStream;
}
use of org.bouncycastle.openpgp.PGPEncryptedData in project pgpainless by pgpainless.
the class OnePassSignatureBracketingTest method onePassSignaturePacketsAndSignaturesAreBracketedTest.
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void onePassSignaturePacketsAndSignaturesAreBracketedTest() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
PGPSecretKeyRing key1 = PGPainless.generateKeyRing().modernKeyRing("Alice", null);
PGPSecretKeyRing key2 = PGPainless.generateKeyRing().modernKeyRing("Bob", null);
PGPPublicKeyRing cert1 = PGPainless.extractCertificate(key1);
ByteArrayOutputStream out = new ByteArrayOutputStream();
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign().onOutputStream(out).withOptions(ProducerOptions.signAndEncrypt(EncryptionOptions.encryptCommunications().addRecipient(cert1), SigningOptions.get().addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), key1, DocumentSignatureType.BINARY_DOCUMENT).addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), key2, DocumentSignatureType.BINARY_DOCUMENT)).setAsciiArmor(true));
ByteArrayInputStream data = new ByteArrayInputStream("Hello, World!".getBytes(StandardCharsets.UTF_8));
Streams.pipeAll(data, encryptionStream);
encryptionStream.close();
ByteArrayInputStream ciphertextIn = new ByteArrayInputStream(out.toByteArray());
InputStream inputStream = PGPUtil.getDecoderStream(ciphertextIn);
PGPObjectFactory objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(inputStream);
PGPOnePassSignatureList onePassSignatures = null;
PGPSignatureList signatures = null;
outerloop: while (true) {
Object next = objectFactory.nextObject();
if (next == null) {
break;
}
if (next instanceof PGPEncryptedDataList) {
PGPEncryptedDataList encryptedDataList = (PGPEncryptedDataList) next;
for (PGPEncryptedData encryptedData : encryptedDataList) {
if (encryptedData instanceof PGPPublicKeyEncryptedData) {
PGPPublicKeyEncryptedData publicKeyEncryptedData = (PGPPublicKeyEncryptedData) encryptedData;
PGPSecretKey secretKey = key1.getSecretKey(publicKeyEncryptedData.getKeyID());
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKey, SecretKeyRingProtector.unprotectedKeys());
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance().getPublicKeyDataDecryptorFactory(privateKey);
InputStream decryptionStream = publicKeyEncryptedData.getDataStream(decryptorFactory);
objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(decryptionStream);
continue outerloop;
}
}
} else if (next instanceof PGPOnePassSignatureList) {
onePassSignatures = (PGPOnePassSignatureList) next;
continue outerloop;
} else if (next instanceof PGPCompressedData) {
PGPCompressedData compressed = (PGPCompressedData) next;
InputStream decompressor = compressed.getDataStream();
objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(decompressor);
continue outerloop;
} else if (next instanceof PGPLiteralData) {
continue outerloop;
} else if (next instanceof PGPSignatureList) {
signatures = (PGPSignatureList) next;
continue outerloop;
}
}
assertNotNull(onePassSignatures);
assertNotNull(signatures);
assertEquals(signatures.size(), onePassSignatures.size());
assertEquals(2, signatures.size());
for (int i = 0; i < signatures.size(); i++) {
// CHECK BRACKETING
// OnePassSignatures and Signatures are bracketed
// eg. (OPS1, OPS2, LiteralData, Sig2, Sig1)
PGPOnePassSignature onePassSignature = onePassSignatures.get(i);
PGPSignature signature = signatures.get(signatures.size() - 1 - i);
assertEquals(onePassSignature.getKeyID(), signature.getKeyID());
byte[] encoded = onePassSignature.getEncoded();
// CHECK NESTED-NESS
// 0,1 are header
// 2 is version number
assertEquals(3, encoded[2]);
// 3 is sig type
assertEquals(SignatureType.BINARY_DOCUMENT.getCode(), encoded[3]);
// 4 is hash algo
assertEquals(HashAlgorithm.SHA512.getAlgorithmId(), encoded[4]);
// 5 is public key algo
assertEquals(PublicKeyAlgorithm.EDDSA.getAlgorithmId(), encoded[5]);
// [6,7,8,9,10,11,12,13] are key-id
boolean last = i == signatures.size() - 1;
// 14 is nested
assertEquals(last ? 1 : 0, encoded[14]);
}
}
use of org.bouncycastle.openpgp.PGPEncryptedData in project pgpainless by pgpainless.
the class DecryptionStreamFactory method decryptSessionKey.
private InputStream decryptSessionKey(@Nonnull PGPEncryptedDataList encryptedDataList) throws PGPException {
Iterator<PGPEncryptedData> encryptedDataIterator = encryptedDataList.getEncryptedDataObjects();
if (!encryptedDataIterator.hasNext()) {
throw new PGPException("Decryption failed - EncryptedDataList has no items");
}
PGPPrivateKey decryptionKey = null;
PGPPublicKeyEncryptedData encryptedSessionKey = null;
List<PGPPBEEncryptedData> passphraseProtected = new ArrayList<>();
List<PGPPublicKeyEncryptedData> publicKeyProtected = new ArrayList<>();
List<Tuple<SubkeyIdentifier, PGPPublicKeyEncryptedData>> postponedDueToMissingPassphrase = new ArrayList<>();
// Sort PKESK and SKESK packets
while (encryptedDataIterator.hasNext()) {
PGPEncryptedData encryptedData = encryptedDataIterator.next();
if (!encryptedData.isIntegrityProtected() && !options.isIgnoreMDCErrors()) {
throw new MessageNotIntegrityProtectedException();
}
// SKESK
if (encryptedData instanceof PGPPBEEncryptedData) {
passphraseProtected.add((PGPPBEEncryptedData) encryptedData);
} else // PKESK
if (encryptedData instanceof PGPPublicKeyEncryptedData) {
publicKeyProtected.add((PGPPublicKeyEncryptedData) encryptedData);
}
}
// Try decryption with passphrases first
for (PGPPBEEncryptedData pbeEncryptedData : passphraseProtected) {
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
PBEDataDecryptorFactory passphraseDecryptor = ImplementationFactory.getInstance().getPBEDataDecryptorFactory(passphrase);
try {
InputStream decryptedDataStream = pbeEncryptedData.getDataStream(passphraseDecryptor);
PGPSessionKey pgpSessionKey = pbeEncryptedData.getSessionKey(passphraseDecryptor);
SessionKey sessionKey = new SessionKey(pgpSessionKey);
resultBuilder.setSessionKey(sessionKey);
throwIfAlgorithmIsRejected(sessionKey.getAlgorithm());
integrityProtectedEncryptedInputStream = new IntegrityProtectedInputStream(decryptedDataStream, pbeEncryptedData, options);
return integrityProtectedEncryptedInputStream;
} catch (PGPException e) {
LOGGER.debug("Probable passphrase mismatch, skip PBE encrypted data block", e);
}
}
}
// Then try decryption with public key encryption
for (PGPPublicKeyEncryptedData publicKeyEncryptedData : publicKeyProtected) {
PGPPrivateKey privateKey = null;
if (options.getDecryptionKeys().isEmpty()) {
break;
}
long keyId = publicKeyEncryptedData.getKeyID();
// Wildcard KeyID
if (keyId == 0L) {
LOGGER.debug("Hidden recipient detected. Try to decrypt with all available secret keys.");
for (PGPSecretKeyRing secretKeys : options.getDecryptionKeys()) {
if (privateKey != null) {
break;
}
KeyRingInfo info = new KeyRingInfo(secretKeys);
List<PGPPublicKey> encryptionSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.ANY);
for (PGPPublicKey pubkey : encryptionSubkeys) {
PGPSecretKey secretKey = secretKeys.getSecretKey(pubkey.getKeyID());
// Skip missing secret key
if (secretKey == null) {
continue;
}
privateKey = tryPublicKeyDecryption(secretKeys, secretKey, publicKeyEncryptedData, postponedDueToMissingPassphrase, true);
}
}
} else // Non-wildcard key-id
{
LOGGER.debug("PGPEncryptedData is encrypted for key {}", Long.toHexString(keyId));
resultBuilder.addRecipientKeyId(keyId);
PGPSecretKeyRing secretKeys = findDecryptionKeyRing(keyId);
if (secretKeys == null) {
LOGGER.debug("Missing certificate of {}. Skip.", Long.toHexString(keyId));
continue;
}
// Make sure that the recipient key is encryption capable and non-expired
KeyRingInfo info = new KeyRingInfo(secretKeys);
List<PGPPublicKey> encryptionSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.ANY);
PGPSecretKey secretKey = null;
for (PGPPublicKey pubkey : encryptionSubkeys) {
if (pubkey.getKeyID() == keyId) {
secretKey = secretKeys.getSecretKey(keyId);
break;
}
}
if (secretKey == null) {
LOGGER.debug("Key " + Long.toHexString(keyId) + " is not valid or not capable for decryption.");
} else {
privateKey = tryPublicKeyDecryption(secretKeys, secretKey, publicKeyEncryptedData, postponedDueToMissingPassphrase, true);
}
}
if (privateKey == null) {
continue;
}
decryptionKey = privateKey;
encryptedSessionKey = publicKeyEncryptedData;
break;
}
// Try postponed keys with missing passphrases (will cause missing passphrase callbacks to fire)
if (encryptedSessionKey == null) {
if (options.getMissingKeyPassphraseStrategy() == MissingKeyPassphraseStrategy.THROW_EXCEPTION) {
// Non-interactive mode: Throw an exception with all locked decryption keys
Set<SubkeyIdentifier> keyIds = new HashSet<>();
for (Tuple<SubkeyIdentifier, ?> k : postponedDueToMissingPassphrase) {
keyIds.add(k.getA());
}
if (!keyIds.isEmpty()) {
throw new MissingPassphraseException(keyIds);
}
} else if (options.getMissingKeyPassphraseStrategy() == MissingKeyPassphraseStrategy.INTERACTIVE) {
// Interactive mode: Fire protector callbacks to get passphrases interactively
for (Tuple<SubkeyIdentifier, PGPPublicKeyEncryptedData> missingPassphrases : postponedDueToMissingPassphrase) {
SubkeyIdentifier keyId = missingPassphrases.getA();
PGPPublicKeyEncryptedData publicKeyEncryptedData = missingPassphrases.getB();
PGPSecretKeyRing secretKeys = findDecryptionKeyRing(keyId.getKeyId());
PGPSecretKey secretKey = secretKeys.getSecretKey(keyId.getSubkeyId());
PGPPrivateKey privateKey = tryPublicKeyDecryption(secretKeys, secretKey, publicKeyEncryptedData, postponedDueToMissingPassphrase, false);
if (privateKey == null) {
continue;
}
decryptionKey = privateKey;
encryptedSessionKey = publicKeyEncryptedData;
break;
}
} else {
throw new IllegalStateException("Invalid PostponedKeysStrategy set in consumer options.");
}
}
return decryptWith(encryptedSessionKey, decryptionKey);
}
use of org.bouncycastle.openpgp.PGPEncryptedData in project pgpainless by pgpainless.
the class MessageInspector method processMessage.
private static void processMessage(InputStream dataIn, EncryptionInfo info) throws PGPException, IOException {
PGPObjectFactory objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(dataIn);
Object next;
while ((next = objectFactory.nextObject()) != null) {
if (next instanceof PGPOnePassSignatureList) {
PGPOnePassSignatureList signatures = (PGPOnePassSignatureList) next;
if (!signatures.isEmpty()) {
info.isSignedOnly = true;
return;
}
}
if (next instanceof PGPEncryptedDataList) {
PGPEncryptedDataList encryptedDataList = (PGPEncryptedDataList) next;
for (PGPEncryptedData encryptedData : encryptedDataList) {
if (encryptedData instanceof PGPPublicKeyEncryptedData) {
PGPPublicKeyEncryptedData pubKeyEncryptedData = (PGPPublicKeyEncryptedData) encryptedData;
info.keyIds.add(pubKeyEncryptedData.getKeyID());
} else if (encryptedData instanceof PGPPBEEncryptedData) {
info.isPassphraseEncrypted = true;
}
}
// Data is encrypted, we cannot go deeper
return;
}
if (next instanceof PGPCompressedData) {
PGPCompressedData compressed = (PGPCompressedData) next;
InputStream decompressed = compressed.getDataStream();
InputStream decoded = PGPUtil.getDecoderStream(decompressed);
objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(decoded);
}
if (next instanceof PGPLiteralData) {
return;
}
}
}
Aggregations