Sunday, November 29, 2009

How to convert PublicKey as a String and How to decode it.

I was suffered with a big trouble when I am going to develop a simple secure chat application. I have to convert it as a String and send to third party. Public Key can not send through socket because of that is in as a object. Then I'm surf the Internet and their are no proper answer to send it as a String. Finally I found a method that can can Convert it.


I've used two steps to Encode Public key to String.
1. Convert it to Byte array.
byte array = publicKey.getEncoded();
2. Convert Byte array to String.
BASE64Encoder encoder = new BASE64Encoder();
string = encoder.encode(byte array);
In this step I used BASE64Encoder to encode byte stream to String. BASE64Encoder is a proprietary software of Sun. you can see that while compile source file ;)


Then we can distribute a public key to the third party.

Decode:

This can do as two steps.

1. Decode to byte stream using BASE64Decoder
BASE64Decoder decoder = new BASE64Decoder();
= decoder.decodeBuffer();
2. Convert is to Public Key using X509EncodedKeySpec
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(sigBytes2);
KeyFactory keyFact = KeyFactory.getInstance("RSA", "BC");
pubKey2 = keyFact.generatePublic(x509KeySpec);




Here is the Program.


import java.security.*;
import java.security.spec.*;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class RSAEncryption {
public static void main(String[] args) throws Exception {
RSAEncryption en = new RSAEncryption();
en.DistributePubKey();
}

Key pubKey2;

public void DistributePubKey() throws Exception {
Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding", "BC");
//SecureRandom random = Utils.createFixedRandom();

// create the keys
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
generator.initialize(256, new SecureRandom());

KeyPair pair = generator.generateKeyPair();
Key pubKey = pair.getPublic();
Key privKey = pair.getPrivate();


// Send the public key bytes to the other party...
byte[] publicKeyBytes = pubKey.getEncoded();

//Convert Public key to String
BASE64Encoder encoder = new BASE64Encoder();
String pubKeyStr = encoder.encode(publicKeyBytes);




//Convert PublicKeyString to Byte Stream
BASE64Decoder decoder = new BASE64Decoder();
byte[] sigBytes2 = decoder.decodeBuffer(pubKeyStr);



// Convert the public key bytes into a PublicKey object
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(sigBytes2);
KeyFactory keyFact = KeyFactory.getInstance("RSA", "BC");
pubKey2 = keyFact.generatePublic(x509KeySpec);




// encryption step
cipher.init(Cipher.ENCRYPT_MODE, pubKey2, new SecureRandom());
byte[] cipherText = cipher.doFinal(input.getBytes());
System.out.println("cipher: " + Utils.toHex(cipherText));

// decryption step
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] plainText = cipher.doFinal(cipherText);
System.out.println("plain : " +new String(plainText));
}
}


Encryption code by Dr. Nandika kasun.

6 comments:

  1. what is the difference between Base64 and Base64Encoder
    what about this new String(Base64.encode(publicKey.getEncoded()))

    ReplyDelete
  2. I assume you are using bouncycastle as your security provider.

    If you are using this,
    import org.bouncycastle.util.encoders.Base64;

    Both are same algorithms. but Base64Encoder is developed by Sun Microsystems but Base64 is bouncycastle's product.

    ReplyDelete
  3. Thank you so much for your post I'm going crazy with this problem too and the I met your post.

    It help me so much. Thanks again! :)

    ReplyDelete
  4. Dude my Eclipse didn't allow me to use the "import sun.misc.BASE64Decoder;" thingy, what should I do?

    ReplyDelete
    Replies
    1. thats a library. u can find it here: http://www.java2s.com/Code/Jar/s/DownloadsunmiscBASE64Decoderjar.htm

      Delete
  5. Also BIG BIG BIG BIG thanks from me for this post!!!

    ReplyDelete