Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decrypt a signed pgp encrypted file?

How can I decrypt and verify a file encrypted with PGP with the BouncyCastle Java API?

like image 407
Shane Avatar asked Jul 26 '11 09:07

Shane


People also ask

How do I unencrypt an encrypted file?

Decrypt Files From PropertiesRight-click on the encrypted file and select Properties. In the General tab, select Advanced. Now, uncheck the Encrypt contents to secure data radio box and click on OK.

Can you crack PGP encryption?

Can I decrypt PGP with GPG? GPG can be used to decrypt PGP files because it conforms to the OpenPGP standard. Any message that is encrypted in the OpenPGP format can be decrypted by GPG or any other standard conforming PGP encryption tool.

Can you decrypt your own PGP message?

The encrypted document can only be decrypted by someone with a private key that complements one of the recipients' public keys. In particular, you cannot decrypt a document encrypted by you unless you included your own public key in the recipient list. To decrypt a message the option --decrypt is used.


1 Answers

Encryption Code:

private static void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, PGPSecretKey pgpSec, boolean armor, boolean withIntegrityCheck, char[] pass) throws IOException, NoSuchProviderException {
    if (armor) {
        out = new ArmoredOutputStream(out);
    }

    try {
        PGPEncryptedDataGenerator encGen =
                new PGPEncryptedDataGenerator(
                new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(
                new SecureRandom())
                .setProvider("BC"));
        encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));
        OutputStream encryptedOut = encGen.open(out, new byte[BUFFER_SIZE]);

        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
        OutputStream compressedData = comData.open(encryptedOut);

        //OutputStream compressedData = encryptedOut;

        PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(
                new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
        PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(
                pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));
        sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
        Iterator it = pgpSec.getPublicKey().getUserIDs();
        if (it.hasNext()) {
            PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
            spGen.setSignerUserID(false, (String) it.next());
            sGen.setHashedSubpackets(spGen.generate());
        }
        //BCPGOutputStream bOut = new BCPGOutputStream(compressedData);
        sGen.generateOnePassVersion(false).encode(compressedData); // bOut

        File file = new File(fileName);
        PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
        OutputStream lOut = lGen.open(compressedData, PGPLiteralData.BINARY, file.getName(), new Date(),
                                      new byte[BUFFER_SIZE]); //bOut
        FileInputStream fIn = new FileInputStream(file);
        int ch;

        while ((ch = fIn.read()) >= 0) {
            lOut.write(ch);
            sGen.update((byte) ch);
        }

        fIn.close();
        lOut.close();
        lGen.close();

        sGen.generate().encode(compressedData);

        //bOut.close();

        comData.close();
        compressedData.close();

        encryptedOut.close();
        encGen.close();

        if (armor) {
            out.close();
        }
    } catch (PGPException e) {
        System.err.println(e);
        if (e.getUnderlyingException() != null) {
            e.getUnderlyingException().printStackTrace();
        }
    } catch (SignatureException e) {
        System.err.println(e);
    }
}

Decryption Code:

public static void decryptFile(InputStream in, InputStream keyIn, char[] passwd, OutputStream fOut, InputStream publicKeyIn) throws IOException, NoSuchProviderException, SignatureException,
        PGPException {
    in = PGPUtil.getDecoderStream(in);

    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 = PGPTools.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));

    PGPObjectFactory plainFact = new PGPObjectFactory(clear);

    Object message = null;

    PGPOnePassSignatureList onePassSignatureList = null;
    PGPSignatureList signatureList = null;
    PGPCompressedData compressedData = null;

    message = plainFact.nextObject();
    ByteArrayOutputStream actualOutput = new ByteArrayOutputStream();

    while (message != null) {
        log.trace(message.toString());
        if (message instanceof PGPCompressedData) {
            compressedData = (PGPCompressedData) message;
            plainFact = new PGPObjectFactory(compressedData.getDataStream());
            message = plainFact.nextObject();
        }

        if (message instanceof PGPLiteralData) {
            // have to read it and keep it somewhere.
            Streams.pipeAll(((PGPLiteralData) message).getInputStream(), actualOutput);
        } else if (message instanceof PGPOnePassSignatureList) {
            onePassSignatureList = (PGPOnePassSignatureList) message;
        } else if (message instanceof PGPSignatureList) {
            signatureList = (PGPSignatureList) message;
        } else {
            throw new PGPException("message unknown message type.");
        }
        message = plainFact.nextObject();
    }
    actualOutput.close();
    PGPPublicKey publicKey = null;
    byte[] output = actualOutput.toByteArray();
    if (onePassSignatureList == null || signatureList == null) {
        throw new PGPException("Poor PGP. Signatures not found.");
    } else {

        for (int i = 0; i < onePassSignatureList.size(); i++) {
            PGPOnePassSignature ops = onePassSignatureList.get(0);
            log.trace("verifier : " + ops.getKeyID());
            PGPPublicKeyRingCollection pgpRing = new PGPPublicKeyRingCollection(
                    PGPUtil.getDecoderStream(publicKeyIn));
            publicKey = pgpRing.getPublicKey(ops.getKeyID());
            if (publicKey != null) {
                ops.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey);
                ops.update(output);
                PGPSignature signature = signatureList.get(i);
                if (ops.verify(signature)) {
                    Iterator<?> userIds = publicKey.getUserIDs();
                    while (userIds.hasNext()) {
                        String userId = (String) userIds.next();
                        log.trace("Signed by {}", userId);
                    }
                    log.trace("Signature verified");
                } else {
                    throw new SignatureException("Signature verification failed");
                }
            }
        }

    }

    if (pbe.isIntegrityProtected() && !pbe.verify()) {
        throw new PGPException("Data is integrity protected but integrity is lost.");
    } else if (publicKey == null) {
        throw new SignatureException("Signature not found");
    } else {
        fOut.write(output);
        fOut.flush();
        fOut.close();
    }
}

For reference, this is what PGPTools.findSecretKey does:

public static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass)
        throws IOException, PGPException {
    PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
    PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
    if (pgpSecKey == null) return null;

    PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass);
    return pgpSecKey.extractPrivateKey(decryptor);
}
like image 57
Vishal Dhawani Avatar answered Sep 28 '22 03:09

Vishal Dhawani