Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / Security / November 2005

Tip: Looking for answers? Try searching our database.

Getting Private Key from Certificate

Thread view: 
headware - 14 Nov 2005 19:23 GMT
I'm trying to do something that seems like it shoud be very simple, but
am having trouble finding a solution.

I need to extract the private key from a certificate in PKCS 12 format
and use it to decrypt some RSA encrypted data found in a comma
separated value file.

I've seen posts regarding keytool, JSSE, and JCE, but haven't found
much that seems to do what I want. This seems like this would be a
pretty common thing to do, so I'm not sure why I'm not finding much on
the subject.

I don't have really any experience with the Java's cryptography classes
or much time to learn about them, so I apologize for being "one of
those" posters, but if anyone could point me in the right direction I'd
really appreciate it.
Brian McIlwrath - 14 Nov 2005 19:54 GMT
: I'm trying to do something that seems like it shoud be very simple, but
: am having trouble finding a solution.

: I need to extract the private key from a certificate in PKCS 12 format
: and use it to decrypt some RSA encrypted data found in a comma
: separated value file.

I posted a message last Friday which would take you as far as extracting
the RSA key from a PKCS keystore (note that a PKCS12 file can contain a
number of keys and associated "certificate chains" which sign the keys).
The problem I had was in getting the certificate chain! My earlier post
also included the type of output you can get from the Java "keytool"
utility which is supplied as part of the JDK.

My simple test code folows - the RSA key with alias "brian" is extracted
to the variable "key" :-

import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Enumeration;
import java.security.cert.Certificate;
import java.security.Key;

public class PKCS12 {

  public static void main(String[] args) {

     KeyStore keyStore;

     try {
        String home = System.getProperty("user.home");
        FileInputStream file_inputstream =
           new FileInputStream(home + "/brian.p12");
        keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(file_inputstream, null);
        System.out.println("Keystore size " + keyStore.size());
        Enumeration aliases = keyStore.aliases();
        while(aliases.hasMoreElements()) {
           System.out.println(aliases.nextElement());
        }
       // Certificate cert= keyStore.getCertificate("brian");
        Key key=keyStore.getKey("brian","password".toCharArray());
        System.out.println("Key information " + key.getAlgorithm() +
                           " " + key.getFormat());
        Certificate[] certChain = keyStore.getCertificateChain("brian");
//        System.out.println(certChain[0]);
        System.out.println(certChain.length);
     } catch (Exception e) {
        System.err.println("Exception:- " + e);
     }
  }
}
headware - 15 Nov 2005 06:03 GMT
> : I'm trying to do something that seems like it shoud be very simple, but
> : am having trouble finding a solution.
[quoted text clipped - 48 lines]
>    }
> }

Brian,

Thanks for the help. This got me half of the way there. If I use code
similar to what you posted, I can get the private key out of the
certificate. It looks like this

String home = System.getProperty("user.home") + "/Desktop";
FileInputStream file_inputstream = new FileInputStream(home +
"/test.pfx");
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(file_inputstream, null);

Enumeration aliases = keyStore.aliases();
while(aliases.hasMoreElements())
{
   String a = (String)aliases.nextElement();
   Key key = keyStore.getKey(a, "x".toCharArray());
}

However, to test it, I'd need to be able to get the public key out of
the certificate so I can encrypt something and let my routine decrypt
it. I'm having trouble doing this. I can't seem to use the
getCertificate() method of the KeyStore class in the above scenario
with any luck. I tried doing this

while(aliases.hasMoreElements())
{
   String a = (String)aliases.nextElement();
   Certificate cert = keyStore.getCertificate(a);
}

but getCertificate() always returns null. So instead I tried the
following code:

InputStream inStream = new FileInputStream("test.pfx");
X509Certificate cert = X509Certificate.getInstance(inStream);
inStream.close();

but I keep getting this exception:

x.security.cert.CertificateException: signed fields invalid
       at javax.security.cert.X509Certificate.getInst(Unknown Source)
       at javax.security.cert.X509Certificate.getInstance(Unknown
Source)

I'm not sure what the "signed fields" it refers to are, but I'm
wondering if the PFX file I'm using doesn't contain the data I think it
does or is in a format that I don't understand. I generated it using
the Windows makecert utility.

Any other pointers anyone can give me would be greatly appreciated.
Brian McIlwrath - 15 Nov 2005 16:53 GMT
: Thanks for the help. This got me half of the way there. If I use code
: similar to what you posted, I can get the private key out of the
: certificate. It looks like this

: Any other pointers anyone can give me would be greatly appreciated.

I have sorted it!!!...and also solved my own problem from last Friday at the
same time ...the "keystore" has a password and so does the private key entry.
I really don't think I could have solved this without a book - "Professional
Java Security" by Garms&Somerfield, ISBN 1-861004-25-7

Quote from book "Public keys are encoded using X.509... Private keys are
encoded using PKCS#8 which is standard simply for encoding private keys"

My complete code (including RSA encryption and decryption!!) is now:-

import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Enumeration;
import java.security.cert.Certificate;
import java.security.Key;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;

public class PKCS12 {

  public static void main(String[] args) {

     KeyStore keyStore;
     KeyFactory keyFactory = null;

     try {
        String home = System.getProperty("user.home");
        FileInputStream file_inputstream = new
           FileInputStream(home + "/brian.p12");
        keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(file_inputstream, "keystorepassword".toCharArray());
        System.out.println("Keystore size " + keyStore.size());
        Enumeration aliases = keyStore.aliases();
        while(aliases.hasMoreElements()) {
           System.out.println(aliases.nextElement());
        }
        Key key=keyStore.getKey("brian", "privatekeypass".toCharArray());
        System.out.println("Key information " + key.getAlgorithm() + " "
                           + key.getFormat());
        PKCS8EncodedKeySpec keySpec = new
             PKCS8EncodedKeySpec(key.getEncoded());
        keyFactory = keyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        Certificate cert = keyStore.getCertificate("brian");
        X509EncodedKeySpec keySpec1 = new
            X509EncodedKeySpec(cert.getPublicKey().getEncoded());
        PublicKey publicKey = keyFactory.generatePublic(keySpec1);

        String testString = "A string to be encoded";
       
        Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        rsaCipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] encodedBytes = rsaCipher.doFinal(testString.getBytes());
        System.out.println("Encoded byte array length = " +
            encodedBytes.length + "\nFirst 20 bytes = ");
        for(int i=0; i<20; i++) {
           System.out.print(encodedBytes[i] + " ");
        }
        System.out.println();

        rsaCipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] decodedBytes = rsaCipher.doFinal(encodedBytes);
        String output = new String(decodedBytes);
        System.out.println("String after RSA encryption and decryption = "
           + output);

     } catch (Exception e) {
        System.err.println("Exception:- " + e);
     }
  }
}

Output (for me) is:-

Keystore size 1
brian
Key information RSA PKCS#8
Encoded byte array length = 128
First 20 bytes =
-63 20 -54 -7 90 40 -91 55 -37 -49 -38 97 28 89 72 20 -114 -113 -110 100
String after RSA encryption and decryption = A string to be encoded
headware - 15 Nov 2005 20:03 GMT
> : Thanks for the help. This got me half of the way there. If I use code
> : similar to what you posted, I can get the private key out of the
[quoted text clipped - 88 lines]
> -63 20 -54 -7 90 40 -91 55 -37 -49 -38 97 28 89 72 20 -114 -113 -110 100
> String after RSA encryption and decryption = A string to be encoded

Brian,

I'm glad you got it working. I have one question for you. What is the
"brian.p12" file? I'm guessing this is a keystore, but where did it
come from? Did you create it yourself (maybe using keytool)? In my
scenario I won't have a keystore file. I'll only have the .pfx file.
What I've been doing is creating an empty key store and adding exported
certificates (in PKCS 12 format) to it. I think that's what I've been
doing anyway. I find the keystore concept and interface somewhat
confusing. It's call "keystore" but it stores keys and certificates?
Doesn't seem right.
Brian McIlwrath - 15 Nov 2005 21:42 GMT
: I'm glad you got it working. I have one question for you. What is the
: "brian.p12" file? I'm guessing this is a keystore, but where did it
[quoted text clipped - 5 lines]
: confusing. It's call "keystore" but it stores keys and certificates?
: Doesn't seem right.

I am somewhat new to this area. An application package I am using
(http://ebxmlrr.sourceforge.net) created me the "brian.p12" file and
described it as a "PKCS12 keystore", I was interested in finding out
what this meant in reality!

From the book "Java in Nutshell" from O'Reilly - "a KeyStore may contain
both public and private key entries. A public key is represented by a
Certificate object. A private key entry in the KeyStore contains *BOTH*
a password protected Key *AND* an array of Certificate objects that
represent the Certificate chain for the public key that corresponds to
the private key"

So it would seem to be impossible to have a valid keystore storing an
RSA private key without the corresponding X.509 certificate chain.

Thus my code is correct. It pulls out the private key and uses it to
form the RSA "private key" and also obtains the public RSA key from the
X.509 certificate in the keystore as, by definition, it has to be there!).

I can also dump the contents of "brian.p12" using the JDK tool "keytool".

The command to do this was, I think,
keytool -storetype pkcs12 -file brian.p12 -list -v


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.