Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I have my pair of Public and Private keys and my certificate. Those where created in OpenSSL (why? because I was asked to do it in OpenSSL). Now I want to use those things to make a Java app that uses digital signatures. How can I use my private and public keys to encrypt/decrypt info (and use the certificate to see if data is valid? What are the classes in java that allow me to do that?

My keys are in plain text something like this:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDuyg3h0VbP9iZ6RCxSU6x4WX4
anAwedMVUTqF0WHlvHl1Kiqa6N6TiUk23uXAVUX8RwLFjXWHlG0xwW7mGByA2mX9
5oPQpQFu8C70aMuUotGv87iiLi0UKCZV+9wS9rMdg5LHu1mMPilwgOO6MlyTxKem
-----END PUBLIC KEY-----

UPDATE

I made this code but still can't use the private key to sign a string.

public void encryptHash(String hashToEncrypt, String pathOfKey, String Algorithm) {
    FileInputStream fis = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int len;

        File f = new File(pathOfKey);

        fis = new FileInputStream(pathOfKey);
        len = 0;
        while((len = fis.read()) != -1){
            baos.write(len);
        }

        KeyFactory kf = KeyFactory.getInstance(Algorithm); //Algorithm = "RSA"
        KeySpec keySpec = new PKCS8EncodedKeySpec(baos.toByteArray());
        baos.close();
        PrivateKey privateKey = kf.generatePrivate(keySpec);  //Here's the exception thrown

        Signature rsaSigner = Signature.getInstance("SHA1withRSA");
        rsaSigner.initSign(privateKey);

        fis = new FileInputStream(hashToEncrypt);
        BufferedInputStream bis = new BufferedInputStream(fis);
        byte[] buffer = new byte[1024];
        len = 0;
        while((len = bis.read(buffer)) >= 0){
            try {
                rsaSigner.update(buffer, 0, len);
            } catch (SignatureException ex) {
                Logger.getLogger(DataEncryptor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        bis.close();

        byte[] signature = rsaSigner.sign();

        System.out.println(new String(signature));
}

the exception I'm gettin' is

dic 09, 2011 12:49:02 PM firmaelectronica.DataEncryptor encryptHash
Grave: null
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DER input, Integer tag error
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
    at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
    at firmaelectronica.DataEncryptor.encryptHash(DataEncryptor.java:40)
    at firmaelectronica.FirmaElectronica.main(FirmaElectronica.java:39)
Caused by: java.security.InvalidKeyException: IOException : DER input, Integer tag error
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:361)
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:367)
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91)
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)
    at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316)
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213)
    ... 3 more
share|improve this question
    
Is there a way to give you my key? It was generated just for test purposes so I don't care sharing it ! –  BRabbit27 Dec 9 '11 at 19:28
    
Doing some research. It seems that KeyFactory is the one responsible of this exception, 'cause in fact the key is PKCS#8. –  BRabbit27 Dec 9 '11 at 20:50
    
I have another question. My private key has a password, but nowhere in the code I put that password, could it be the problem of the exception? –  BRabbit27 Dec 9 '11 at 22:48
    
I had the same question. That was the inspiration for this: orbaker.com/java/sslcontext.html –  user9284 Apr 22 '12 at 23:49

1 Answer 1

up vote 5 down vote accepted

If you have a public key in this form (and not within a certificate), I'd recommend using BouncyCastle's PEMReader. Its readObject() method can read a lot for formats: public keys, certificates, private keys (although you may need to use the method with a password)...

If you don't want to use BouncyCastle, you can read certificates using a CertificateFactory (see examples). With a certificate in PEM format in an InputStream:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(inputStream);

For private keys, if your private key is a PKCS#8 structure in DER format, you can read it directly using PKCS8EncodedKeySpec. For example:

KeyFactory kf = KeyFactory.getInstance("RSA");
// Read privateKeyDerByteArray from DER file.
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyDerByteArray);
PrivateKey key = kf.generatePrivate(keySpec);

You can convert your private key into PKCS#8 using openssl pkcs8 -topk8 (remember -outform DER, you may also want to check the cipher suites as not all might be commonly supported by both Java and OpenSSL).

  • From a keystore usage point of view:

If you don't want to do much programming for handling the keys, to go between Java and OpenSSL, it's convenient to use the PKCS#12 format.

If the keys and certs you have produced with OpenSSL are not already in a p12 container:

openssl pkcs12 -export -in cert.pem -inkey key.pem -out store.p12

In general, you can make use of the directly, using Java's "PKCS12" keystore type (instead of "JKS" by default).

If needed, you can convert this PKCS12 keystore into another format (e.g. JKS) using keytool (Java 6+):

keytool -importkeystore -srckeystore store.p12 -srcstoretype PKCS12 \
     -destkeystore store.jks -deststoretype JKS

(Essentially, the opposite operation as the one described in this question.)

Either way, whether from using PEMReader or by loading your key/cert from a KeyStore, you should be able to get instances of PrivateKey and Certificate (or PublicKey directly).

You can verify the signature of a Certificate has been done using by the private key matching a given public key using its verify(PublicKey) method.

With them, you can also use the digital signature API. It's a more general API for any document signature, and I wouldn't necessarily verify a certificate signature with it (I'd rather use the certification path API for this, since it will also build the chain).

share|improve this answer
    
Yep thanks ! And If I don't want to use third party APIs? Is there a native Java API to use private/public RSA keys and certificates? Should I create new keys in PKCS#12 format? How can I check if my keys are in that format? –  BRabbit27 Dec 9 '11 at 0:16
    
I've edited my answer for direct usage of the API (but BC makes the whole process a bit easier). I gave you the openssl command to build a p12 file from a cert and key in PEM format (if you have those in .pem or .crt file for example). Extensions are just a convention, so it depends on how you actually created the key/cert. What you've pasted in your question looks like PEM (or a variant thereof), but that's just a public key, not a certificate. –  Bruno Dec 9 '11 at 0:45
    
Thanks. I've done a more deep research and actually the key and cert are in DER format, so they are in pkcs8 arent they? So if I understand well the info you gave me I can use PKCS8EncodedKeySpec, am I right? (The key I posted was actually a PEM one but the original file is in DER, and all the other keys and certs are in DER) Thanks I'll try this out ! thanks ! –  BRabbit27 Dec 9 '11 at 16:55
    
No, DER is essentially a binary version of PEM (which is base64-encoded of DER, within ---- separators). They're more different encodings of the same structures, rather than different data structures. Most OpenSSL commands allow you to choose between PEM and DER using -inform and -outform. DER doesn't imply PKCS#8 at all. One way of finding out which formats are used is to try to read your files using openssl x509 or openssl rsa (with -text option for example). Check their man-pages. –  Bruno Dec 9 '11 at 17:04
1  
@miho, no, I was just talking of ways to read them. PEMReader will try its best to read anything it can. A certificate has more information than just a public key (it binds a public key to an identity and other attributes). –  Bruno Mar 30 at 11:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.