I want to encrypt a small string in javascript using RSA with public keys and then decrypt that string in java server side code using private keys.
I am using this code in javascript:
http://www-cs-students.stanford.edu/~tjw/jsbn/
Example at:
http://www-cs-students.stanford.edu/~tjw/jsbn/rsa2.html
and this code on java side:
Encrypting string in javascript and decryption in java
Both of codes work good independently but they do not understand each other. Need to solve this today or I am open to accept any other asymmetrical algorithm that works this way.
You are using raw encryption on the Java side and RSA encryption using PKCS#1 v1.5 padding on the Java Card side. You should try and use Java RSA through the javax.crypto.Cipher.getInstance("RSA/None/PKCS1Padding")
. Don't forget to remove any base 64 encoding if that is present.
wanna leave the example for further generations :)
First, we need to generate key pair in java code
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
yourVariablePublic = kp.getPublic();
yourVariablePublic = kp.getPrivate();
} catch(NoSuchAlgorithmException e) {
}
Now let`s move to java code of our current page:
// receiving public key from where you store it
Key publicKey = YourCarrierClass.getYourVariablePublic();
KeyFactory fact;
// initializing public key variable
RSAPublicKeySpec pub = new RSAPublicKeySpec(BigInteger.ZERO, BigInteger.ZERO);
try {
fact = KeyFactory.getInstance("RSA");
pub = fact.getKeySpec(publicKey, RSAPublicKeySpec.class);
} catch(NoSuchAlgorithmException e1) {
} catch(InvalidKeySpecException e) {
}
// now you should pass Modulus string onto your html(jsp) in such way
String htmlUsedModulus = pub.getModulus().toString(16);
// send somehow this String to page, so javascript can use it
Now for javascript side:
function sendPassword() {
var password = $('#passwordField').val();
var rsa = new RSAKey();
rsa.setPublic($('#keyModulus').text(), '10001');
var res = rsa.encrypt(password);
$('#ajaxSentPassword').val(res);
}
And to decrypt it in java code:
Key privateKey = YourCarrierClass.getYourVariablePrivate();
Cipher cipher;
BigInteger passwordInt = new BigInteger(ajaxSentPassword, 16);
byte[] dectyptedText = new byte[1];
try {
cipher = javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding");
byte[] passwordBytes = passwordInt.toByteArray();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
dectyptedText = cipher.doFinal(passwordBytes);
} catch(NoSuchAlgorithmException e) {
} catch(NoSuchPaddingException e) {
} catch(InvalidKeyException e) {
} catch(IllegalBlockSizeException e) {
} catch(BadPaddingException e) {
}
String passwordNew = new String(dectyptedText);
System.out.println("Password new " + passwordNew);
Here you go, sorry, I`m not good in handling these catch clauses.
====================================================================
Upd:
Here I found out some issues, regarding this code.
First of all, you can change algorithm of
javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding");
to:
javax.crypto.Cipher.getInstance("RSA");
But this is not essential, it works with both.
Now the real problem is regarding this line
byte[] passwordBytes = passwordInt.toByteArray();
here when you generate byte array from BigInteger, it sometimes adds [0] in front as signum (Sometimes NOT! so algorithm can decipher that array), so byte array size can be 65/129/257, which cannot be deciphered by algorithm, it throws IllegalBlockSizeException. This problem is discussed in Getting 1 byte extra in the modulus RSA Key and sometimes for exponents also question.
The simplest solution is just throw away that zero from array:
byte[] byteArray = new byte[256];
BigInteger passwordInt = new BigInteger(password, 16);
if (passwordInt.toByteArray().length > 256) {
for (int i=1; i<257; i++) {
byteArray[i-1] = passwordInt.toByteArray()[i];
}
} else {
byteArray = passwordInt.toByteArray();
}