Setelah sebelumnya saya tulis sedikit tentang mudahnya melakukan enkripsi, sekarang saya tertarik untuk mencoba enkripsi yang lain lagi karena saya juga penasaran. Jatuhlah pilihan saya di RSA…. kenapa RSA? Selain bisa untuk enkripsi, RSA juga bisa digunakan untuk digital signature.. Koq bisa ya? ya iyalah, masa ya iya dong. Alasan lainnya sih beberapa waktu yang lalu ada mahasiswa yang coba berkonsultasi tentang koding RSA di J2ME. Mau ngak mau saya coba cari tahu tentang RSA itu…
Keamanan RSA terletak pada sulitnya memfaktorkan bilangan yang besar menjadi faktor-faktor prima. Selama belum ditemukan algoritma pemfaktoran yang efektif, selama itu pula keamanan RSA tetap terjamin. Kalo pingin lebih jelas secara matematis teorinya, temen-temen bisa unduh disini atau bisa liat di http://en.wikipedia.org/wiki/RSA.
Masih dalam platform J2ME, dan masih menggunakan library Bouncy Castle saya coba membangkitan pasangan kunci RSA dan melakukan enkripsi dan dekripsi.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import javax.microedition.midlet.*;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.signers.PSSSigner;
/**
* @author Lenovo
*/
public class RSAMidlet extends MIDlet {
public void startApp() {
try {
System.out.println(“generator on”);
// plain message yang akan diproses
byte[] plain = “makhluk paling seksi”.getBytes();
byte[] keypair = generator();
// input stream pasangan kunci
ByteArrayInputStream bais = new ByteArrayInputStream(keypair);
DataInputStream dis = new DataInputStream(bais);
int modLen = dis.readInt();
int pubLen = dis.readInt();
int privLen = dis.readInt();
int pLen = dis.readInt();
int qLen = dis.readInt();
int dPLen = dis.readInt();
int dQLen = dis.readInt();
int qInvLen = dis.readInt();
byte[] modulo = new byte[modLen];
bais.read(modulo, 0, modLen);
byte[] pubExp = new byte[pubLen];
bais.read(pubExp, 0, pubLen);
byte[] privExp = new byte[privLen];
bais.read(privExp, 0, privLen);
byte[] p = new byte[pLen];
bais.read(p, 0, pLen);
byte[] q = new byte[qLen];
bais.read(q, 0, qLen);
byte[] dP = new byte[dPLen];
bais.read(dP, 0, dPLen);
byte[] dQ = new byte[dQLen];
bais.read(dQ, 0, dQLen);
byte[] qInv = new byte[qInvLen];
bais.read(qInv, 0, qInvLen);
dis.close();
bais.close();
// construct private key
RSAPrivateCrtKeyParameters privKey = constructPrivateKey(modulo, pubExp, privExp, p, q, dP, dQ, qInv);
// construct public key
RSAKeyParameters pubKey = constructPublicKey(modulo, pubExp);
byte[] cipher = rsaEncrypt(plain, pubKey);
System.out.println(“cipher: “+new String(cipher));
byte[] recovery = rsaDecrypt(cipher, privKey);
System.out.println(“recovery: “+new String(recovery));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public RSAKeyParameters constructPublicKey(
byte[] modulo,
byte[] pubExp)
{
BigInteger n = new BigInteger(modulo);
BigInteger e = new BigInteger(pubExp);
return (new RSAKeyParameters(false, n, e));
}
public RSAPrivateCrtKeyParameters constructPrivateKey(
byte[] modulo,
byte[] pubExp,
byte[] privExp,
byte[] pByte,
byte[] qByte,
byte[] dPByte,
byte[] dQByte,
byte[] qInvByte)
{
BigInteger n = new BigInteger(modulo);
BigInteger e = new BigInteger(pubExp);
BigInteger d = new BigInteger(privExp);
BigInteger p = new BigInteger(pByte);
BigInteger q = new BigInteger(qByte);
BigInteger dP = new BigInteger(dPByte);
BigInteger dQ = new BigInteger(dQByte);
BigInteger qInv = new BigInteger(qInvByte);
return (new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
}
public byte[] rsaEncrypt(
byte[] inputByte,
RSAKeyParameters publicKey)
{
byte[] sesKeyCipher = null;
try {
AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSAEngine());
rsaEngine.init(true, publicKey);
System.out.println(“enkripsi berjalan…”);
System.out.println(“input encrypt length: “+inputByte.length);
sesKeyCipher = rsaEngine.processBlock(inputByte, 0, inputByte.length);
} catch (InvalidCipherTextException ex) {
ex.printStackTrace();
}
return sesKeyCipher;
}
public byte[] rsaDecrypt(
byte[] inputByte,
RSAPrivateCrtKeyParameters privateKey)
{
byte[] sesKeyPlain = null;
try {
AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSAEngine());
rsaEngine.init(false, privateKey);
System.out.println(“dekripsi berjalan…”);
System.out.println(“input decrypt length: “+inputByte.length);
sesKeyPlain = rsaEngine.processBlock(inputByte, 0, inputByte.length);
} catch (InvalidCipherTextException ex) {
ex.printStackTrace();
}
return sesKeyPlain;
}
public byte[] getSignature(
byte[] inputByte,
RSAPrivateCrtKeyParameters privateKey)
{
byte[] signatureByte = null;
try {
MD5Digest md5Engine = new MD5Digest();
RSAEngine rsaEngine = new RSAEngine();
PSSSigner signer = new PSSSigner(rsaEngine, md5Engine, 64);
signer.init(true, privateKey);
signer.update(inputByte, 0, inputByte.length);
signatureByte = signer.generateSignature();
} catch (DataLengthException ex) {
ex.printStackTrace();
} catch (CryptoException ex) {
ex.printStackTrace();
}
return signatureByte;
}
public boolean verifySignature(
byte[] inputByte,
byte[] signature,
RSAKeyParameters publicKey)
{
MD5Digest md5Engine = new MD5Digest();
RSAEngine rsaEngine = new RSAEngine();
PSSSigner signer = new PSSSigner(rsaEngine, md5Engine, 64);
signer.init(false, publicKey);
signer.update(inputByte, 0, inputByte.length);
return signer.verifySignature(signature);
}
public byte[] generator() {
BigInteger exp = new BigInteger(“11″, 16);
SecureRandom srand = new SecureRandom();
RSAKeyGenerationParameters params = new RSAKeyGenerationParameters(exp, srand, 1024, 80);
RSAKeyPairGenerator rsaKeyPairGen = new RSAKeyPairGenerator();
rsaKeyPairGen.init(params);
AsymmetricCipherKeyPair keyPair = rsaKeyPairGen.generateKeyPair();
// tampung hasil generate
RSAPrivateCrtKeyParameters rsaPrivateKey = (RSAPrivateCrtKeyParameters) keyPair.getPrivate();
// private key
byte[] modulo = rsaPrivateKey.getModulus().toByteArray();
byte[] pubExp = rsaPrivateKey.getPublicExponent().toByteArray();
byte[] privExp = rsaPrivateKey.getExponent().toByteArray();
byte[] p = rsaPrivateKey.getP().toByteArray();
byte[] q = rsaPrivateKey.getQ().toByteArray();
byte[] dP = rsaPrivateKey.getDP().toByteArray();
byte[] dQ = rsaPrivateKey.getDQ().toByteArray();
byte[] qInv = rsaPrivateKey.getQInv().toByteArray();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeInt(modulo.length);
dos.writeInt(pubExp.length);
dos.writeInt(privExp.length);
dos.writeInt(p.length);
dos.writeInt(q.length);
dos.writeInt(dP.length);
dos.writeInt(dQ.length);
dos.writeInt(qInv.length);
baos.write(modulo, 0, modulo.length);
baos.write(pubExp, 0, pubExp.length);
baos.write(privExp, 0, privExp.length);
baos.write(p, 0, p.length);
baos.write(q, 0, q.length);
baos.write(dP, 0, dP.length);
baos.write(dQ, 0, dQ.length);
baos.write(qInv, 0, qInv.length);
dos.close();
baos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return baos.toByteArray();
}
}
Karena platform yang dipake adalah J2ME, maka jangan heran kalo proses pembangkitan kuncinya makan waktu lama. Dengan begitu tidak direkomendasikan melakukan pembangkitan di ponsel…
Dalam source code saya sertakan method untuk signature dan verifikasi. Mungkin temen-temen pembaca penasaran seperti apa bentuknya signature dan verifikasi itu sih… ya silahkan dicoba saja, ngak sulit koq.