Search in sources :

Example 1 with PGPEncryptedData

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;
}
Also used : PGPException(org.bouncycastle.openpgp.PGPException) PGPEncryptedData(org.bouncycastle.openpgp.PGPEncryptedData) SessionKeyDataDecryptorFactory(org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory) BufferedInputStream(java.io.BufferedInputStream) ArmoredInputStream(org.bouncycastle.bcpg.ArmoredInputStream) InputStream(java.io.InputStream) PGPPBEEncryptedData(org.bouncycastle.openpgp.PGPPBEEncryptedData) PGPPublicKeyEncryptedData(org.bouncycastle.openpgp.PGPPublicKeyEncryptedData) PGPSessionKey(org.bouncycastle.openpgp.PGPSessionKey) MessageNotIntegrityProtectedException(org.pgpainless.exception.MessageNotIntegrityProtectedException)

Example 2 with PGPEncryptedData

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]);
    }
}
Also used : PGPPublicKeyRing(org.bouncycastle.openpgp.PGPPublicKeyRing) PGPEncryptedData(org.bouncycastle.openpgp.PGPEncryptedData) PGPOnePassSignatureList(org.bouncycastle.openpgp.PGPOnePassSignatureList) PGPLiteralData(org.bouncycastle.openpgp.PGPLiteralData) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) PGPEncryptedDataList(org.bouncycastle.openpgp.PGPEncryptedDataList) PGPSignatureList(org.bouncycastle.openpgp.PGPSignatureList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) PGPSignature(org.bouncycastle.openpgp.PGPSignature) PGPObjectFactory(org.bouncycastle.openpgp.PGPObjectFactory) PGPCompressedData(org.bouncycastle.openpgp.PGPCompressedData) PublicKeyDataDecryptorFactory(org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory) ByteArrayInputStream(java.io.ByteArrayInputStream) PGPSecretKey(org.bouncycastle.openpgp.PGPSecretKey) PGPPublicKeyEncryptedData(org.bouncycastle.openpgp.PGPPublicKeyEncryptedData) PGPOnePassSignature(org.bouncycastle.openpgp.PGPOnePassSignature) PGPPrivateKey(org.bouncycastle.openpgp.PGPPrivateKey) PGPSecretKeyRing(org.bouncycastle.openpgp.PGPSecretKeyRing) EncryptionStream(org.pgpainless.encryption_signing.EncryptionStream) TestTemplate(org.junit.jupiter.api.TestTemplate) ExtendWith(org.junit.jupiter.api.extension.ExtendWith)

Example 3 with PGPEncryptedData

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);
}
Also used : ArrayList(java.util.ArrayList) PGPSessionKey(org.bouncycastle.openpgp.PGPSessionKey) SubkeyIdentifier(org.pgpainless.key.SubkeyIdentifier) MissingPassphraseException(org.pgpainless.exception.MissingPassphraseException) SessionKey(org.pgpainless.util.SessionKey) PGPSessionKey(org.bouncycastle.openpgp.PGPSessionKey) PGPSecretKey(org.bouncycastle.openpgp.PGPSecretKey) PGPPBEEncryptedData(org.bouncycastle.openpgp.PGPPBEEncryptedData) PGPPrivateKey(org.bouncycastle.openpgp.PGPPrivateKey) HashSet(java.util.HashSet) PGPEncryptedData(org.bouncycastle.openpgp.PGPEncryptedData) BufferedInputStream(java.io.BufferedInputStream) ArmoredInputStream(org.bouncycastle.bcpg.ArmoredInputStream) InputStream(java.io.InputStream) Passphrase(org.pgpainless.util.Passphrase) PGPPublicKey(org.bouncycastle.openpgp.PGPPublicKey) PGPException(org.bouncycastle.openpgp.PGPException) PBEDataDecryptorFactory(org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory) KeyRingInfo(org.pgpainless.key.info.KeyRingInfo) PGPPublicKeyEncryptedData(org.bouncycastle.openpgp.PGPPublicKeyEncryptedData) PGPSecretKeyRing(org.bouncycastle.openpgp.PGPSecretKeyRing) MessageNotIntegrityProtectedException(org.pgpainless.exception.MessageNotIntegrityProtectedException) Tuple(org.pgpainless.util.Tuple)

Example 4 with PGPEncryptedData

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;
        }
    }
}
Also used : PGPEncryptedData(org.bouncycastle.openpgp.PGPEncryptedData) PGPOnePassSignatureList(org.bouncycastle.openpgp.PGPOnePassSignatureList) PGPLiteralData(org.bouncycastle.openpgp.PGPLiteralData) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) PGPEncryptedDataList(org.bouncycastle.openpgp.PGPEncryptedDataList) PGPPBEEncryptedData(org.bouncycastle.openpgp.PGPPBEEncryptedData) PGPPublicKeyEncryptedData(org.bouncycastle.openpgp.PGPPublicKeyEncryptedData) PGPObjectFactory(org.bouncycastle.openpgp.PGPObjectFactory) PGPCompressedData(org.bouncycastle.openpgp.PGPCompressedData)

Aggregations

InputStream (java.io.InputStream)4 PGPEncryptedData (org.bouncycastle.openpgp.PGPEncryptedData)4 PGPPublicKeyEncryptedData (org.bouncycastle.openpgp.PGPPublicKeyEncryptedData)4 PGPPBEEncryptedData (org.bouncycastle.openpgp.PGPPBEEncryptedData)3 BufferedInputStream (java.io.BufferedInputStream)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 ArmoredInputStream (org.bouncycastle.bcpg.ArmoredInputStream)2 PGPCompressedData (org.bouncycastle.openpgp.PGPCompressedData)2 PGPEncryptedDataList (org.bouncycastle.openpgp.PGPEncryptedDataList)2 PGPException (org.bouncycastle.openpgp.PGPException)2 PGPLiteralData (org.bouncycastle.openpgp.PGPLiteralData)2 PGPObjectFactory (org.bouncycastle.openpgp.PGPObjectFactory)2 PGPOnePassSignatureList (org.bouncycastle.openpgp.PGPOnePassSignatureList)2 PGPPrivateKey (org.bouncycastle.openpgp.PGPPrivateKey)2 PGPSecretKey (org.bouncycastle.openpgp.PGPSecretKey)2 PGPSecretKeyRing (org.bouncycastle.openpgp.PGPSecretKeyRing)2 PGPSessionKey (org.bouncycastle.openpgp.PGPSessionKey)2 MessageNotIntegrityProtectedException (org.pgpainless.exception.MessageNotIntegrityProtectedException)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 ArrayList (java.util.ArrayList)1