Example usage for org.bouncycastle.openpgp PGPPublicKeyEncryptedData getKeyID

List of usage examples for org.bouncycastle.openpgp PGPPublicKeyEncryptedData getKeyID

Introduction

In this page you can find the example usage for org.bouncycastle.openpgp PGPPublicKeyEncryptedData getKeyID.

Prototype

public long getKeyID() 

Source Link

Document

Return the keyID for the key used to encrypt the data.

Usage

From source file:google.registry.rde.BouncyCastleTest.java

License:Open Source License

@Test
public void testEncryptDecrypt_KeyRingStyle() throws Exception {
    int bufferSize = 64 * 1024;

    // Alice loads Bob's "publicKey" into memory from her public key ring.
    PGPPublicKeyRingCollection publicKeyRings = new BcPGPPublicKeyRingCollection(
            PGPUtil.getDecoderStream(new ByteArrayInputStream(PUBLIC_KEY)));
    PGPPublicKeyRing publicKeyRing = publicKeyRings.getKeyRings("eric@bouncycastle.org", true, true).next();
    PGPPublicKey publicKey = publicKeyRing.getPublicKey();

    // Alice encrypts the secret message for Bob using his "publicKey".
    PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(AES_128));
    encryptor.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey));
    byte[] encryptedData;
    try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
        try (OutputStream output2 = encryptor.open(output, new byte[bufferSize])) {
            output2.write(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8));
        }/*from   w  ww.  j av  a2  s. c  o  m*/
        encryptedData = output.toByteArray();
    }
    logger.info("Encrypted data: " + dumpHex(encryptedData));

    // Bob loads his chain of private keys into memory.
    PGPSecretKeyRingCollection privateKeyRings = new BcPGPSecretKeyRingCollection(
            PGPUtil.getDecoderStream(new ByteArrayInputStream(PRIVATE_KEY)));

    // Bob decrypt's the OpenPGP message (w/ ciphertext) using his "privateKey".
    try (ByteArrayInputStream input = new ByteArrayInputStream(encryptedData)) {
        PGPObjectFactory pgpFact = new BcPGPObjectFactory(input);
        PGPEncryptedDataList encDataList = (PGPEncryptedDataList) pgpFact.nextObject();
        assertThat(encDataList.size()).isEqualTo(1);
        PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0);
        // Bob loads the private key to which the message is addressed.
        PGPPrivateKey privateKey = extractPrivateKey(privateKeyRings.getSecretKey(encData.getKeyID()));
        try (InputStream original = encData.getDataStream(new BcPublicKeyDataDecryptorFactory(privateKey))) {
            assertThat(CharStreams.toString(new InputStreamReader(original, UTF_8)))
                    .isEqualTo(FALL_OF_HYPERION_A_DREAM);
        }
    }
}

From source file:google.registry.rde.BouncyCastleTest.java

License:Open Source License

@Test
public void testCompressEncryptDecryptDecompress_KeyRingStyle() throws Exception {
    int bufsz = 64 * 1024;

    // Alice loads Bob's "publicKey" into memory from her public key ring.
    PGPPublicKeyRingCollection publicKeyRings = new BcPGPPublicKeyRingCollection(
            PGPUtil.getDecoderStream(new ByteArrayInputStream(PUBLIC_KEY)));
    PGPPublicKeyRing publicKeyRing = publicKeyRings.getKeyRings("eric@bouncycastle.org", true, true).next();
    PGPPublicKey publicKey = publicKeyRing.getPublicKey();

    // Alice encrypts the secret message for Bob using his "publicKey".
    PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(AES_128));
    encryptor.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey));
    byte[] encryptedData;
    try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
        try (OutputStream output2 = encryptor.open(output, new byte[bufsz])) {
            PGPCompressedDataGenerator kompressor = new PGPCompressedDataGenerator(ZIP);
            try (OutputStream output3 = kompressor.open(output2, new byte[bufsz])) {
                output3.write(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8));
            }/*from ww  w.j  a  va  2s.c  o m*/
        }
        encryptedData = output.toByteArray();
    }
    logger.info("Encrypted data: " + dumpHex(encryptedData));

    // Bob loads his chain of private keys into memory.
    PGPSecretKeyRingCollection privateKeyRings = new BcPGPSecretKeyRingCollection(
            PGPUtil.getDecoderStream(new ByteArrayInputStream(PRIVATE_KEY)));

    // Bob decrypt's the OpenPGP message (w/ ciphertext) using his "privateKey".
    try (ByteArrayInputStream input = new ByteArrayInputStream(encryptedData)) {
        PGPObjectFactory pgpFact = new BcPGPObjectFactory(input);
        PGPEncryptedDataList encDataList = (PGPEncryptedDataList) pgpFact.nextObject();
        assertThat(encDataList.size()).isEqualTo(1);
        PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0);
        // Bob loads the private key to which the message is addressed.
        PGPPrivateKey privateKey = extractPrivateKey(privateKeyRings.getSecretKey(encData.getKeyID()));
        try (InputStream original = encData.getDataStream(new BcPublicKeyDataDecryptorFactory(privateKey))) {
            pgpFact = new BcPGPObjectFactory(original);
            PGPCompressedData kompressedData = (PGPCompressedData) pgpFact.nextObject();
            try (InputStream orig2 = kompressedData.getDataStream()) {
                assertThat(CharStreams.toString(new InputStreamReader(orig2, UTF_8)))
                        .isEqualTo(FALL_OF_HYPERION_A_DREAM);
            }
        }
    }
}

From source file:google.registry.rde.Ghostryde.java

License:Open Source License

/**
 * Opens a new {@link Decryptor} (Reading Step 1/3)
 *
 * <p>This is the first step in opening a ghostryde file. After this method, you'll want to
 * call {@link #openDecompressor(Decryptor)}.
 *
 * @param input is an {@link InputStream} of the ghostryde file data.
 * @param privateKey is the private encryption key of the recipient (which is us!)
 * @throws IOException/*from ww  w .  j av a2 s  . com*/
 * @throws PGPException
 */
@CheckReturnValue
public Decryptor openDecryptor(@WillNotClose InputStream input, PGPPrivateKey privateKey)
        throws IOException, PGPException {
    checkNotNull(privateKey, "privateKey");
    PGPObjectFactory fact = new BcPGPObjectFactory(checkNotNull(input, "input"));
    PGPEncryptedDataList crypts = pgpCast(fact.nextObject(), PGPEncryptedDataList.class);
    checkState(crypts.size() > 0);
    if (crypts.size() > 1) {
        logger.warningfmt("crypts.size() is %d (should be 1)", crypts.size());
    }
    PGPPublicKeyEncryptedData crypt = pgpCast(crypts.get(0), PGPPublicKeyEncryptedData.class);
    if (crypt.getKeyID() != privateKey.getKeyID()) {
        throw new PGPException(String.format("Message was encrypted for keyid %x but ours is %x",
                crypt.getKeyID(), privateKey.getKeyID()));
    }
    return new Decryptor(crypt.getDataStream(new BcPublicKeyDataDecryptorFactory(privateKey)), crypt);
}

From source file:gr.abiss.calipso.util.PgpUtils.java

License:Open Source License

/**
 * decrypt the passed in message stream// w w w .j  a  v  a2  s  .  co  m
 */
private static void decryptFile(InputStream in, InputStream keyIn, char[] passwd, String defaultFileName)
        throws IOException, NoSuchProviderException {
    in = PGPUtil.getDecoderStream(in);

    try {
        PGPObjectFactory pgpF = new PGPObjectFactory(in);
        PGPEncryptedDataList enc;

        Object o = pgpF.nextObject();
        //
        // the first object might be a PGP marker packet.
        //
        if (o instanceof PGPEncryptedDataList) {
            enc = (PGPEncryptedDataList) o;
        } else {
            enc = (PGPEncryptedDataList) pgpF.nextObject();
        }

        //
        // find the secret key
        //
        Iterator it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));

        while (sKey == null && it.hasNext()) {
            pbe = (PGPPublicKeyEncryptedData) it.next();

            sKey = findSecretKey(pgpSec, pbe.getKeyID(), passwd);
        }

        if (sKey == null) {
            throw new IllegalArgumentException("secret key for message not found.");
        }

        InputStream clear = pbe.getDataStream(sKey, "BC");

        PGPObjectFactory plainFact = new PGPObjectFactory(clear);

        Object message = plainFact.nextObject();

        if (message instanceof PGPCompressedData) {
            PGPCompressedData cData = (PGPCompressedData) message;
            PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream());

            message = pgpFact.nextObject();
        }

        if (message instanceof PGPLiteralData) {
            PGPLiteralData ld = (PGPLiteralData) message;

            String outFileName = ld.getFileName();
            if (outFileName.length() == 0) {
                outFileName = defaultFileName;
            }

            InputStream unc = ld.getInputStream();
            OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));

            Streams.pipeAll(unc, fOut);

            fOut.close();
        } else if (message instanceof PGPOnePassSignatureList) {
            throw new PGPException("encrypted message contains a signed message - not literal data.");
        } else {
            throw new PGPException("message is not a simple encrypted file - type unknown.");
        }

        if (pbe.isIntegrityProtected()) {
            if (!pbe.verify()) {
                System.err.println("message failed integrity check");
            } else {
                System.err.println("message integrity check passed");
            }
        } else {
            System.err.println("no message integrity check");
        }
    } catch (PGPException e) {
        System.err.println(e);
        if (e.getUnderlyingException() != null) {
            e.getUnderlyingException().printStackTrace();
        }
    }
}

From source file:hh.learnj.test.license.test.lincense3j.KeyBasedFileProcessor.java

/**
 * decrypt the passed in message stream//from  w ww . j  a  v a2  s.co  m
 */
private static void decryptFile(InputStream in, InputStream keyIn, char[] passwd, String defaultFileName)
        throws IOException, NoSuchProviderException {
    in = PGPUtil.getDecoderStream(in);
    try {
        JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
        PGPEncryptedDataList enc;

        Object o = pgpF.nextObject();
        //
        // the first object might be a PGP marker packet.
        //
        if (o instanceof PGPEncryptedDataList) {
            enc = (PGPEncryptedDataList) o;
        } else {
            enc = (PGPEncryptedDataList) pgpF.nextObject();
        }
        //
        // find the secret key
        //
        Iterator it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn),
                new JcaKeyFingerprintCalculator());

        while (sKey == null && it.hasNext()) {
            pbe = (PGPPublicKeyEncryptedData) it.next();
            sKey = MyPGPUtil.findSecretKey(pgpSec, pbe.getKeyID(), passwd);
        }
        if (sKey == null) {
            throw new IllegalArgumentException("secret key for message not found.");
        }
        InputStream clear = pbe
                .getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));
        JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);
        Object message = plainFact.nextObject();
        if (message instanceof PGPCompressedData) {
            PGPCompressedData cData = (PGPCompressedData) message;
            JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(cData.getDataStream());
            message = pgpFact.nextObject();
        }
        if (message instanceof PGPLiteralData) {
            PGPLiteralData ld = (PGPLiteralData) message;

            String outFileName = ld.getFileName();
            if (outFileName.length() == 0) {
                outFileName = defaultFileName;
            } else {
                /**
                 * modify 20160520 set fileName ????????
                 */
                String separator = "";
                if (outFileName.contains("/")) {
                    separator = "/";
                } else if (outFileName.contains("\\")) {
                    separator = "\\";

                }
                String fileName = outFileName.substring(outFileName.lastIndexOf(separator) + 1);
                //
                String defseparator = "";
                if (defaultFileName.contains("/")) {
                    defseparator = "/";
                } else if (defaultFileName.contains("\\")) {
                    defseparator = "\\";
                }

                defaultFileName = defaultFileName.substring(0, defaultFileName.lastIndexOf(defseparator));

                outFileName = defaultFileName + File.separator + fileName;

            }

            InputStream unc = ld.getInputStream();
            OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));

            Streams.pipeAll(unc, fOut);

            fOut.close();
        } else if (message instanceof PGPOnePassSignatureList) {
            throw new PGPException("encrypted message contains a signed message - not literal data.");
        } else {
            throw new PGPException("message is not a simple encrypted file - type unknown.");
        }

        if (pbe.isIntegrityProtected()) {
            if (!pbe.verify()) {
                System.err.println("message failed integrity check");
            } else {
                System.err.println("message integrity check passed");
            }
        } else {
            System.err.println("no message integrity check");
        }
    } catch (PGPException e) {
        System.err.println(e);
        if (e.getUnderlyingException() != null) {
            e.getUnderlyingException().printStackTrace();
        }
    }
}

From source file:org.apache.camel.converter.crypto.PGPDataFormat.java

License:Apache License

@SuppressWarnings("resource")
public Object unmarshal(Exchange exchange, InputStream encryptedStream) throws Exception {
    if (encryptedStream == null) {
        return null;
    }/*w  w w  .  ja v  a2 s  . c om*/
    InputStream in = PGPUtil.getDecoderStream(encryptedStream);
    PGPObjectFactory pgpFactory = new PGPObjectFactory(in);
    Object o = pgpFactory.nextObject();
    // the first object might be a PGP marker packet 
    PGPEncryptedDataList enc;
    if (o instanceof PGPEncryptedDataList) {
        enc = (PGPEncryptedDataList) o;
    } else {
        enc = (PGPEncryptedDataList) pgpFactory.nextObject();
    }

    PGPPublicKeyEncryptedData pbe = null;
    PGPPrivateKey key = null;
    // find encrypted data for which a private key exists in the secret key ring
    for (int i = 0; i < enc.size() && key == null; i++) {
        pbe = (PGPPublicKeyEncryptedData) enc.get(i);
        key = PGPDataFormatUtil.findPrivateKeyWithKeyId(exchange.getContext(), findKeyFileName(exchange),
                findEncryptionKeyRing(exchange), pbe.getKeyID(), findKeyPassword(exchange),
                getPassphraseAccessor(), getProvider());
    }
    if (key == null) {
        throw new PGPException("Provided input is encrypted with unknown pair of keys.");
    }

    InputStream encData = pbe
            .getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider(getProvider()).build(key));
    pgpFactory = new PGPObjectFactory(encData);
    PGPCompressedData comData = (PGPCompressedData) pgpFactory.nextObject();
    pgpFactory = new PGPObjectFactory(comData.getDataStream());
    Object object = pgpFactory.nextObject();

    PGPOnePassSignature signature;
    if (object instanceof PGPOnePassSignatureList) {
        signature = getSignature(exchange, (PGPOnePassSignatureList) object);
        object = pgpFactory.nextObject();
    } else {
        signature = null;
    }

    PGPLiteralData ld = (PGPLiteralData) object;
    InputStream litData = ld.getInputStream();

    // enable streaming via OutputStreamCache
    CachedOutputStream cos;
    ByteArrayOutputStream bos;
    OutputStream os;
    if (exchange.getContext().getStreamCachingStrategy().isEnabled()) {
        cos = new CachedOutputStream(exchange);
        bos = null;
        os = cos;
    } else {
        cos = null;
        bos = new ByteArrayOutputStream();
        os = bos;
    }

    try {
        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead;
        while ((bytesRead = litData.read(buffer)) != -1) {
            os.write(buffer, 0, bytesRead);
            if (signature != null) {
                signature.update(buffer, 0, bytesRead);
            }
            os.flush();
        }
    } finally {
        IOHelper.close(os, litData, encData, in);
    }

    if (signature != null) {
        PGPSignatureList sigList = (PGPSignatureList) pgpFactory.nextObject();
        if (!signature.verify(getSignatureWithKeyId(signature.getKeyID(), sigList))) {
            throw new SignatureException("Cannot verify PGP signature");
        }
    }

    if (cos != null) {
        return cos.newStreamCache();
    } else {
        return bos.toByteArray();
    }
}

From source file:org.apache.camel.converter.crypto.PGPDataFormatUtil.java

License:Apache License

@Deprecated
private static PGPPrivateKey findPrivateKey(InputStream keyringInput, InputStream encryptedInput,
        String passphrase, PGPPassphraseAccessor passphraseAccessor, String provider)
        throws IOException, PGPException, NoSuchProviderException {
    PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyringInput));
    PGPObjectFactory factory = new PGPObjectFactory(PGPUtil.getDecoderStream(encryptedInput));
    PGPEncryptedDataList enc;/*from   w w  w  .j av  a2s . com*/
    Object o = factory.nextObject();
    if (o == null) {
        throw new PGPException("Provided input is not encrypted.");
    }
    if (o instanceof PGPEncryptedDataList) {
        enc = (PGPEncryptedDataList) o;
    } else {
        enc = (PGPEncryptedDataList) factory.nextObject();
    }
    encryptedInput.reset(); // nextObject() method reads from the InputStream, so rewind it!
    Iterator<?> encryptedDataObjects = enc.getEncryptedDataObjects();
    PGPPrivateKey privateKey = null;
    PGPPublicKeyEncryptedData encryptedData = null;
    while (privateKey == null && encryptedDataObjects.hasNext()) {
        encryptedData = (PGPPublicKeyEncryptedData) encryptedDataObjects.next();
        PGPSecretKey pgpSecKey = pgpSec.getSecretKey(encryptedData.getKeyID());
        if (pgpSecKey != null) {
            if (passphrase == null && passphraseAccessor != null) {
                // get passphrase from accessor
                @SuppressWarnings("unchecked")
                Iterator<String> userIDs = pgpSecKey.getUserIDs();
                while (passphrase == null && userIDs.hasNext()) {
                    passphrase = passphraseAccessor.getPassphrase(userIDs.next());
                }
            }
            privateKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider)
                    .build(passphrase.toCharArray()));
        }
    }
    if (privateKey == null && pgpSec.size() > 0 && encryptedData != null) {
        throw new PGPException("Provided input is encrypted with unknown pair of keys.");
    }
    return privateKey;
}

From source file:org.apache.camel.converter.crypto.PGPKeyAccessDataFormat.java

License:Apache License

private InputStream getDecryptedData(Exchange exchange, InputStream encryptedStream)
        throws Exception, PGPException {
    PGPObjectFactory pgpFactory = new PGPObjectFactory(encryptedStream);
    Object firstObject = pgpFactory.nextObject();
    // the first object might be a PGP marker packet 
    PGPEncryptedDataList enc = getEcryptedDataList(pgpFactory, firstObject);

    if (enc == null) {
        throw getFormatException();
    }/*from   w  ww.  j a  v  a 2 s .  c om*/
    PGPPublicKeyEncryptedData pbe = null;
    PGPPrivateKey key = null;
    // find encrypted data for which a private key exists in the secret key ring
    for (int i = 0; i < enc.size() && key == null; i++) {
        Object encryptedData = enc.get(i);
        if (!(encryptedData instanceof PGPPublicKeyEncryptedData)) {
            throw getFormatException();
        }
        pbe = (PGPPublicKeyEncryptedData) encryptedData;
        key = secretKeyAccessor.getPrivateKey(exchange, pbe.getKeyID());
        if (key != null) {
            // take the first key
            break;
        }
    }
    if (key == null) {
        throw new PGPException(
                "PGP message is encrypted with a key which could not be found in the Secret Keyring.");
    }

    InputStream encData = pbe
            .getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider(getProvider()).build(key));
    return encData;
}

From source file:org.apache.gobblin.crypto.GPGFileDecryptor.java

License:Apache License

/**
 * Taking in a file inputstream, keyring inputstream and a passPhrase, generate a decrypted file inputstream.
 * @param inputStream file inputstream/*  ww  w.  ja v  a2  s. c o  m*/
 * @param keyIn keyring inputstream. This InputStream is owned by the caller.
 * @param passPhrase passPhrase
 * @return an {@link InputStream} for the decrypted content
 * @throws IOException
 */
public InputStream decryptFile(InputStream inputStream, InputStream keyIn, String passPhrase)
        throws IOException {
    try {
        PGPEncryptedDataList enc = getPGPEncryptedDataList(inputStream);
        Iterator it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn),
                new BcKeyFingerprintCalculator());

        while (sKey == null && it.hasNext()) {
            pbe = (PGPPublicKeyEncryptedData) it.next();
            sKey = findSecretKey(pgpSec, pbe.getKeyID(), passPhrase);
        }

        if (sKey == null) {
            throw new IllegalArgumentException("secret key for message not found.");
        }

        InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder()
                .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(sKey));
        JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(clear);

        return new LazyMaterializeDecryptorInputStream(pgpFact);
    } catch (PGPException e) {
        throw new IOException(e);
    }
}

From source file:org.kontalk.crypto.Coder.java

License:Open Source License

private static DecryptionResult decryptAndVerify(InputStream encryptedStream, PersonalKey myKey,
        PGPPublicKey senderKey) {//from  w  w  w .j  a  v a2  s.  com
    // note: the signature is inside the encrypted data

    DecryptionResult result = new DecryptionResult();

    PGPObjectFactory pgpFactory = new PGPObjectFactory(encryptedStream);

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

    try { // catch all IO and PGP exceptions

        // the first object might be a PGP marker packet
        Object o = pgpFactory.nextObject(); // nullable
        if (!(o instanceof PGPEncryptedDataList)) {
            o = pgpFactory.nextObject(); // nullable
        }

        if (!(o instanceof PGPEncryptedDataList)) {
            LOGGER.warning("can't find encrypted data list in data");
            result.errors.add(Error.INVALID_DATA);
            return result;
        }
        PGPEncryptedDataList encDataList = (PGPEncryptedDataList) o;

        // check if secret key matches our encryption keyID
        Iterator<?> it = encDataList.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        long myKeyID = myKey.getPrivateEncryptionKey().getKeyID();
        while (sKey == null && it.hasNext()) {
            Object i = it.next();
            if (!(i instanceof PGPPublicKeyEncryptedData))
                continue;
            pbe = (PGPPublicKeyEncryptedData) i;
            if (pbe.getKeyID() == myKeyID)
                sKey = myKey.getPrivateEncryptionKey();
        }
        if (sKey == null || pbe == null) {
            LOGGER.warning("private key for message not found");
            result.errors.add(Error.INVALID_PRIVATE_KEY);
            return result;
        }

        InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));

        PGPObjectFactory plainFactory = new PGPObjectFactory(clear);

        Object object = plainFactory.nextObject(); // nullable

        if (!(object instanceof PGPCompressedData)) {
            LOGGER.warning("data packet not compressed");
            result.errors.add(Error.INVALID_DATA);
            return result;
        }

        PGPCompressedData cData = (PGPCompressedData) object;
        PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream());

        object = pgpFact.nextObject(); // nullable

        // the first object could be the signature list
        // get signature from it
        PGPOnePassSignature ops = null;
        if (object instanceof PGPOnePassSignatureList) {
            PGPOnePassSignatureList signatureList = (PGPOnePassSignatureList) object;
            // there is a signature list, so we assume the message is signed
            // (makes sense)
            result.signing = Signing.SIGNED;

            if (signatureList.isEmpty()) {
                LOGGER.warning("signature list is empty");
                result.errors.add(Error.INVALID_SIGNATURE_DATA);
            } else {
                ops = signatureList.get(0);
                ops.init(new BcPGPContentVerifierBuilderProvider(), senderKey);
            }
            object = pgpFact.nextObject(); // nullable
        } else {
            LOGGER.warning("signature list not found");
            result.signing = Signing.NOT;
        }

        if (!(object instanceof PGPLiteralData)) {
            LOGGER.warning("unknown packet type: " + object.getClass().getName());
            result.errors.add(Error.INVALID_DATA);
            return result;
        }

        PGPLiteralData ld = (PGPLiteralData) object;
        InputStream unc = ld.getInputStream();
        int ch;
        while ((ch = unc.read()) >= 0) {
            outputStream.write(ch);
            if (ops != null)
                try {
                    ops.update((byte) ch);
                } catch (SignatureException ex) {
                    LOGGER.log(Level.WARNING, "can't read signature", ex);
                }
        }

        result.decryptedStream = Optional.of(outputStream);

        if (ops != null) {
            result = verifySignature(result, pgpFact, ops);
        }

        // verify message integrity
        if (pbe.isIntegrityProtected()) {
            if (!pbe.verify()) {
                LOGGER.warning("message integrity check failed");
                result.errors.add(Error.INVALID_INTEGRITY);
            }
        } else {
            LOGGER.warning("message is not integrity protected");
            result.errors.add(Error.NO_INTEGRITY);
        }

    } catch (IOException | PGPException ex) {
        LOGGER.log(Level.WARNING, "can't decrypt message", ex);
        result.errors.add(Error.UNKNOWN_ERROR);
    }

    return result;
}