Search code examples
javapgp

How to Extract PGP public key and PGP Private key from JKS File and to Decrypt a pgp Encrypted Message?


I have the following code for decrypting a PGP encrypted Private Key Message.

    KeyStore ks = KeyStore.getInstance("JKS");
    File file = new file("abc.txt");
    ks.load(new FileInputStream("abc.jks"), "******".toCharArray());
    KeyStore.PrivateKeyEntry keyEntry =(KeyStore.PrivateKeyEntry) ks.getEntry("abcd", new KeyStore.PasswordProtection("******".toCharArray()));
    PrivateKey k = keyEntry.getPrivateKey();
    CertificateFactory fact = CertificateFactory.getInstance("X.509");
    FileInputStream is = new FileInputStream ("ght.cer");
    X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
    PublicKey NPCIPubKey = cer.getPublicKey();

    byte[] bt = new byte[(int)file.length()];
    FileInputStream fis = new FileInputStream(file);
    fis.read(bt);
    PGPPublicKey pk1 = new JcaPGPKeyConverter().getPGPPublicKey(PGPPublicKey.RSA_GENERAL, NPCIPubKey, new Date());
    PGPPrivateKey prik = new JcaPGPKeyConverter().getPGPPrivateKey(pk1, k);
    DecClass dec = new DecClass();
    dec.rsaDecryptFile(fis,prik);'

Decryption Class :

public class DecClass {

    public void rsaDecryptFile(InputStream in,  PGPPrivateKey priK)  {
        try {
            Security.addProvider(new BouncyCastleProvider());
            
            in = org.bouncycastle.openpgp.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();
            }                        

                        Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
            PGPPrivateKey sKey = null;
            PGPPublicKeyEncryptedData pbe = null;

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

            if (sKey == null) {
                throw new IllegalArgumentException("Secret key for message not found.");
            }
            
            PublicKeyDataDecryptorFactory b = new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC")
                    .setContentProvider("BC").build(sKey);

            InputStream clear = pbe.getDataStream(b);
            PGPObjectFactory plainFact = new PGPObjectFactory(clear,new BcKeyFingerprintCalculator());

            Object message = plainFact.nextObject();
            System.out.println("Secret key info 3:: " + pbe.getKeyID() + new Date());
            if (message instanceof PGPCompressedData) {
                PGPCompressedData cData = (PGPCompressedData) message;
                PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream(),new BcKeyFingerprintCalculator());
                message = pgpFact.nextObject();
            }           
            if (message instanceof PGPLiteralData) {
                PGPLiteralData ld = (PGPLiteralData) message;
                InputStream unc = ld.getInputStream();
                int ch;             
                FileUtils.copyInputStreamToFile(unc, new File("D:\\Development_Docs\\PGP\\Bulk\\target.txt"));
                
            } 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()) {
                    throw new PGPException("Message failed integrity check");
                }
            }           
        }catch (PGPException e) {
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }   
    }
}

But am getting null pointer exception in Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects(); line in DecClass rsaDecryptFile Method.While debugging value of PGPEncryptedDataList enc is coming null. Am not able to trace the source of the exception. Please advise on how can i resolve this exception and get the code to work. Please find below snippet of my input encrypted message

-----BEGIN PGP MESSAGE-----
Version: BCPG v1.47

hQEMAxVcH36ac1ahAQf/UMvfmBxIEtGOcIzovhcQ8WTojB06oF8/8i5lv6iz3EEj
vIceEWSHdeCJuYSemPaiIrccOOfGFqZodg6a7IQhjG0WcuSg5F4a/Pn/7KxKqB9n
OoHwmpX0+Pbm1Y2mNAj3LN9KtK3
-----END PGP MESSAGE-----

Solution

  • I'm able to decrypt the file by modifing the following code.Hope it'll work for you.

            @SuppressWarnings({ "unchecked", "unused" })
            public static void rsaDecryptFile(InputStream in, OutputStream out, 
            PGPPrivateKey priK)  {
        try {
            Security.addProvider(new BouncyCastleProvider());
            
            in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
            PGPObjectFactory pgpF = new PGPObjectFactory(in,new 
            JcaKeyFingerprintCalculator());
            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<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
            PGPPrivateKey sKey = null;
            PGPPublicKeyEncryptedData pbe = null;
    
            while (sKey == null /*&& it.hasNext()*/) {
                //pbe = it.next();
                pbe = (PGPPublicKeyEncryptedData)enc.getEncryptedDataObjects().next();
                //sKey = findSecretKey(pubK, pbe.getKeyID(), priK);
                sKey = priK;
                
    
            }
    
            if (sKey == null) throw new IllegalArgumentException("Secret key for message not found.");
            
            PublicKeyDataDecryptorFactory b = new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC")
                    .setContentProvider("BC").build(sKey);
    
            InputStream clear = pbe.getDataStream(b);
            PGPObjectFactory plainFact = new PGPObjectFactory(clear,new JcaKeyFingerprintCalculator());
    
            Object message = plainFact.nextObject();
            System.out.println("Secret key info 3:: " + pbe.getKeyID() + new Date());
            if (message instanceof PGPCompressedData) {
                PGPCompressedData cData = (PGPCompressedData) message;
                PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream(),new JcaKeyFingerprintCalculator());
    
                message = pgpFact.nextObject();
            }
            
            if (message instanceof PGPLiteralData) {
                PGPLiteralData ld = (PGPLiteralData) message;
                InputStream unc = ld.getInputStream();
                System.out.println("Unc d " + unc.read());
                int ch;
                
                while ((ch = unc.read()) >= 0) { 
                    out.write(ch); 
                    }
                 
                 
    
                //FileUtils.copyInputStreamToFile(unc, new File("D:\\Development_Docs\\PGP\\Bulk\\target.txt"));
    
                
            } 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()) {
                    throw new PGPException("Message failed integrity check");
                }
            }
            
            
        }catch (PGPException e) {
            // TODO: handle exception
            e.printStackTrace();
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        
        
    }