Encrypt a small string with RSA in javascript then decrypt in java on server

一笑奈何 提交于 2019-11-30 10:30:30

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.

Gytis

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();
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!