3

I wanted to implement some VERY basic security in my Java application, but I'm getting stuck at the very beginning.

What I want to do is this: 1-Generate a RSA keypair 2-Store those keys in my DB in serialized form, so I can re-create them on the next run of the application 3-De-serialize them so I can get them back into object form and can use them to encrypt/decrypt stuff.

The problem is, I can't find a straightforward explanation on how to do this anywhere. I tried the standard Java serialization/deserialization methods, but they don't work. My code is as follows:

    public static KeyPair Bin2KeyPair(byte[] data){
    try{
        ByteArrayInputStream b = new ByteArrayInputStream(data);
        ObjectInputStream o = new ObjectInputStream(b);
        Object obj =o.readObject();
        return((KeyPair)obj);
    }catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public static byte[] KeyPair2Bin(KeyPair kp){

    ByteArrayOutputStream b = new ByteArrayOutputStream();
    ObjectOutputStream o;
    try {
        o = new ObjectOutputStream(b);
        o.writeObject(kp);
        return b.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }   
    return  null;
}

The problem I'm having is that the second method works fine (serializes the key to a byte array) but the first one fails, throwing a ClassCastException, telling me I can't cast the object to "KeyPair".

Any tips on how to do this properly?

EDIT: here's the exception (it gets thrown at "return((KeyPair)obj);" in the first method):

java.lang.ClassCastException: [B cannot be cast to java.security.KeyPair
at DARCOServer.security.SecurityManager.String2KeyPair(SecurityManager.java:34)
at DARCOServer.security.SecurityManager.GenerateServerKeys(SecurityManager.java:122)
at DARCOServer.MainClass.main(MainClass.java:13)
Master_T
  • 7,232
  • 11
  • 72
  • 144

2 Answers2

4

This works for me:

@Test
public void serializeTest() throws Exception {

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    KeyPair keyPair = kpg.generateKeyPair();
    ByteArrayOutputStream b = new ByteArrayOutputStream();
    ObjectOutputStream o =  new ObjectOutputStream(b);
    o.writeObject(keyPair);
    byte[] res = b.toByteArray();

    o.close();
    b.close(); 

    ByteArrayInputStream bi = new ByteArrayInputStream(res);
    ObjectInputStream oi = new ObjectInputStream(bi);
    Object obj = oi.readObject();
    assertTrue(obj instanceof KeyPair);

    oi.close();
    bi.close(); 
}
pd40
  • 3,187
  • 3
  • 20
  • 29
  • you forgot to close the [ObjectOutputStream()](http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html) @pd40 Actually, you need to close all of the *Stream objects. – Cacho Santa Apr 01 '14 at 06:25
  • 1
    For some reason, on Android(device with API Level 16, Jelly Bean 4.1) I get a "java.io.NotSerializableException: org.apache.harmony.xnet.provider.jsse.OpenSSLKey" when trying this exact code. I tested on emulator and your answer works on Android 6.0 but not on 4.1. (For anyone on Android trying to serialize and deserialize an RSA KeyPair in Java) – tuxayo May 08 '16 at 18:21
1

Answering myself, just in case someone has the same problem:

Don't know what it was, but using the BouncyCastle SPI instead of the default JDK one seems to solve the problem for me, it's working correctly now.

Master_T
  • 7,232
  • 11
  • 72
  • 144