Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Decrypt pgp file using bouncycastle api

Posted on 2009-04-22
14
Medium Priority
?
9,641 Views
Last Modified: 2012-05-06
Hello, I am trying to decrypt PGP encrypted file. The file was encrypted using my public key that I generated. I could encrypt and decrypt the files that I created locally using bouncycastle API, but when my client encrypts the file on his side I am not able to decrypt it using bouncycastle API but could decrypt it manually using gnupg on command prompt.

When run decryption in my class I am not able to find secret key to decrypt the file. And I am not sure how my client decrypts it.

Please let me know if you have any suggestions.

import org.bouncycastle.openpgp.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 
 
import java.io.*;
import java.util.Iterator;
import java.security.NoSuchProviderException;
import java.security.Security;
 
 
 
public class PGPSecurityService {
    public PGPSecurityService(){}
 
    public static  void main(String[] args){
        try{
            Security.addProvider(new BouncyCastleProvider());
            FileInputStream privKey = new FileInputStream("C:\\apps\\private\\secring.gpg");
            InputStream file = new BufferedInputStream (new FileInputStream("C:\\apps\\private\\encrypted.pgp"));
            System.out.println(decryptFile(file, privKey, "mykey".toCharArray()));
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
 
 
    private static String decryptFile(InputStream in, InputStream keyIn, char[] passwd) throws Exception {
        try {
            PGPObjectFactory pgpF = new PGPObjectFactory(PGPUtil.getDecoderStream(in));
            Object o = pgpF.nextObject();
            PGPEncryptedDataList enc = o instanceof  PGPEncryptedDataList ? (PGPEncryptedDataList) o :(PGPEncryptedDataList) pgpF.nextObject();
            Iterator it = enc.getEncryptedDataObjects();
            PGPPrivateKey sKey = null;
            PGPPublicKeyEncryptedData pbe = null;
 
            while (sKey == null && it.hasNext()) {
                pbe = (PGPPublicKeyEncryptedData) it.next();
                sKey =findSecretKey(keyIn, 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();
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            if (message instanceof PGPLiteralData) {
                PGPLiteralData ld = (PGPLiteralData) message;
                InputStream unc = ld.getInputStream();
                int ch;
                while ((ch = unc.read()) >= 0) {
                    baos.write(ch);
                }
            } 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("no message integrity check");
            }
            return baos.toString();
        } catch (PGPException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    private static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) throws IOException, PGPException, NoSuchProviderException {
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
        System.out.println("pgpSec size="+pgpSec);
        System.out.println(keyID);
        PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
        return pgpSecKey != null? pgpSecKey.extractPrivateKey(pass, "BC"): null;
    }
    /*
    public static String decrypt(byte[] encdata, String keyLocation, String phrase) {
            try {
                ByteArrayInputStream bais = new ByteArrayInputStream(encdata);
                FileInputStream privKey = new FileInputStream(keyLocation);
                return decryptFile(bais, privKey, phrase.toCharArray());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        */
  
 
}

Open in new window

0
Comment
Question by:alexk23
  • 8
  • 5
14 Comments
 
LVL 12

Expert Comment

by:Gibu George
ID: 24206406
What is the error/exception thrown  when you try to decrypt?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24206437
>>but when my client encrypts the file on his side I am not able to decrypt it using bouncycastle API

You are, i assume, attempting to decrypt it using his *public* key are you? That's what you must do
0
 

Author Comment

by:alexk23
ID: 24206536
The error is throwing by my null check when I am checking if the key is null
throw new IllegalArgumentException("secret key for message not found.");
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:alexk23
ID: 24206569
CEHJ, I am trying to decrypt the file by my secret key that I used to generate the public key for my client. Are you saying I should use public key to decrypt the file as well?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24206690
You decrypt messages *he* sends using *his* public key. He encrypts his own messages using his private key
0
 

Author Comment

by:alexk23
ID: 24206858
CEHJ, no the message is being encrypted using public key that I sent to them. And I am able to decrypt the message on command prompt using GnuPG. I checked the path to the secret key and the file I am trying to decrypt all looks good just can't find the key to decrypt encrypted file using my implementation of bouncy castle api
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24206911
Sorry alexk23, what i just said was wrong.

He encrypts messages he sends to you using *your* public key. Is that what's happening?
0
 

Author Comment

by:alexk23
ID: 24206942
Yes. let me know if you would like to see the encrypted file.
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 1500 total points
ID: 24207119
0
 

Author Comment

by:alexk23
ID: 24207306
Thaks CEHJ, let me look at it and will let you know!
0
 

Author Comment

by:alexk23
ID: 24208959
The example does almost the same thing in comparing the keys, but the problem is that when I compare the public vs. private keys I am getting following results:

Data was encrypted using public key:  -4270675083819455261
Data was encrypted using public key:  5471684833902076854

Got secret key: -7878772790183064541 mask=true SigningKey = true
Got secret key: 5471684833902076854 mask=false SigningKey= false

But it still puzzles me how I was able to decrypt same file in command prompt I got couple messages but was able to decrypt it.

gpg: Signature made 04/21/09 03:41:20  using DSA key ID 2BD4FDE5
gpg: Can't check signature: public key not found
gpg: WARNING: message was not integrity protected
0
 

Author Comment

by:alexk23
ID: 24247415
I figured it out the problem was with the message was encrypted and signed so I had to check the message signature first. Although example wasnt clear and had some issues but gave me an idea, thanks CEHJ
import org.bouncycastle.openpgp.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 
import java.io.*;
import java.util.Iterator;
 
 
import java.security.NoSuchProviderException;
import java.security.Security;
 
 
 
public class PGPSecurityService {
 
 
    public static  void main(String[] args){
        try{
            Security.addProvider(new BouncyCastleProvider());
 
            /**
             * decrypt file
             **/
            // my private key
            InputStream privKey = new BufferedInputStream (new FileInputStream("C:\\apps\\private\\secring.gpg"));
            // file to decrypt
            InputStream file = new BufferedInputStream (new FileInputStream("C:\\apps\\encrypted.pgp"));
 
            decryptFile(file, privKey,"mykey".toCharArray());
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
 
    private static PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection  pgpSec, long keyID, char[] pass)
        throws PGPException, NoSuchProviderException{
        PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
        if (pgpSecKey == null){
            return null;
        } else {
            return pgpSecKey.extractPrivateKey(pass, "BC");
        }
    }
 
    private static PGPPublicKey readPublicKeyFromCol(InputStream in)throws Exception {
        PGPPublicKeyRing pkRing = null;
        PGPPublicKeyRingCollection pkCol = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(in));
        //System.out.println("key ring size=" + pkCol.size());
        Iterator it = pkCol.getKeyRings();
        while (it.hasNext()) {
            pkRing = (PGPPublicKeyRing) it.next();
            Iterator pkIt = pkRing.getPublicKeys();
            while (pkIt.hasNext()) {
                PGPPublicKey key = (PGPPublicKey) pkIt.next();
                //System.out.println("Encryption key = " + key.isEncryptionKey() + ", Master key = " +key.isMasterKey());
                if (key.isMasterKey())
                    return key;
            }
        }
        return null;
    }
 
    private static void decryptFile( InputStream in, InputStream keyIn, char[] passwd)throws Exception{
        in = PGPUtil.getDecoderStream(in);
        try{
            PGPObjectFactory pgpF = new PGPObjectFactory(in);
            Object o = pgpF.nextObject();
            PGPEncryptedDataList enc = o instanceof PGPEncryptedDataList?(PGPEncryptedDataList)o : (PGPEncryptedDataList)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;
                    FileOutputStream    fOut = new FileOutputStream("C:\\apps\\private\\outputsigned.txt");
                    InputStream    unc = ld.getInputStream();
                    int    ch;
                    while ((ch = unc.read()) >= 0){
                        fOut.write(ch);
                    }
                }else if (message instanceof PGPOnePassSignatureList) {
 
                    PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) message;
                    InputStream pubKey = new BufferedInputStream (new FileInputStream("C:\\apps\\private\\pubring.gpg"));
                    PGPPublicKey key =readPublicKeyFromCol(pubKey);
                    if(key!=null){
                        PGPOnePassSignature ops = p1.get(0);
                        System.out.println("ops.getKeyID()="+ops.getKeyID());
                        ops.initVerify(key, "BC");
                        // file output dirctory
                        FileOutputStream out = new FileOutputStream("C:\\apps\\private\\outputsigned.txt");
                        PGPLiteralData  p2 = (PGPLiteralData) pgpFact.nextObject();
                        int ch;
                        InputStream  dIn = p2.getInputStream();
                        while ((ch = dIn.read()) >= 0) {
                            ops.update((byte)ch);
                            out.write(ch);
                        }
                        out.close();
                    } else {
                        throw new PGPException ("unable to find public key for signed file");
                    }
                } 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");
                }
            } else {
                System.out.println("unable to verify message");
            }
        }catch (PGPException e){
            System.err.println(e);
            if (e.getUnderlyingException() != null){
                e.getUnderlyingException().printStackTrace();
            }
        }
    }
 
 
}

Open in new window

0
 

Author Closing Comment

by:alexk23
ID: 31573353
Although example wasnt clear and had some issues but gave me an idea, thanks CEHJ
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24248276
Good :-)
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will learn different types of Android Layout and some basics of an Android App.
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
Suggested Courses
Course of the Month14 days, 21 hours left to enroll

577 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question