Skip to content Skip to sidebar Skip to footer

How Do I Encrypt Crypto-JS Keys With JSBN?

I'm using JSBN to encrypt/decrypt data using public/private keypairs. It works great for text data, including hex strings. My problem is now I have binary data, specifically Crypt

Solution 1:

The JSBN library contains a function, namely pkcs1pad2(), wherein it converts the text to numeric values using JavaScript's charCodeAt() function. You'll see that conversion code in the first while() loop:

function pkcs1pad2(s,n) {
  if(n < s.length + 11) { // TODO: fix for utf-8
    alert("Message too long for RSA");
    return null;
  }
  var ba = new Array();
  var i = s.length - 1;
  while(i >= 0 && n > 0) {
    var c = s.charCodeAt(i--);
    if(c < 128) { // encode using utf-8
      ba[--n] = c;
    }
    else if((c > 127) && (c < 2048)) {
      ba[--n] = (c & 63) | 128;
      ba[--n] = (c >> 6) | 192;
    }
    else {
      ba[--n] = (c & 63) | 128;
      ba[--n] = ((c >> 6) & 63) | 128;
      ba[--n] = (c >> 12) | 224;
    }
  }
  ba[--n] = 0;
  var rng = new SecureRandom();
  var x = new Array();
  while(n > 2) { // random non-zero pad
    x[0] = 0;
    while(x[0] == 0) rng.nextBytes(x);
    ba[--n] = x[0];
  }
  ba[--n] = 2;
  ba[--n] = 0;
  return new BigInteger(ba);
}

If you wish to encrypt binary data then you'll likely have to modify this function so it converts the input in the way you want it.

Below is an example of pkcs1pad2() modified to accept binary data in the form of a hex string. If you use this version of pkcs1pad2() then you can convert your CryptoJS.lib.WordArray into hex and pass that hex string to rsa.encrypt().

function pkcs1pad2(hexPlaintext,n) {
  if(n < hexPlaintext.length/2 + 11) {
    alert("Message too long for RSA");
    return null;
  }
  var ba = new Array();
  var i = hexPlaintext.length;
  while(i >= 2 && n > 0) {
    ba[--n] = parseInt(hexPlaintext.slice(i-2,i),16);
    i-=2;
  }
  ba[--n] = 0;
  var rng = new SecureRandom();
  var x = new Array();
  while(n > 2) { // random non-zero pad
    x[0] = 0;
    while(x[0] == 0) rng.nextBytes(x);
    ba[--n] = x[0];
  }
  ba[--n] = 2;
  ba[--n] = 0;
  return new BigInteger(ba);
}

Alternatively, you could modify it to take the WordArray directly and convert that to the array format that is used by JSBN, but I'll leave that as an exercise for the reader.


Solution 2:

the pkcs1pad2 function converted from javascript to java:

public BigInteger pkcs1pad2(String data,int keysize){
    byte[] buffer=new byte[keysize];
    Random rg=new Random();

    if(keysize < data.length()+11)
        return null;

    int i = data.length() - 1;
    while(i >= 0 && keysize > 0){
        --keysize;
        buffer[keysize] = (byte) data.charAt(i);
        i--;
    }
    --keysize;
    buffer[keysize] = 0;
    while(keysize > 2){
        --keysize;
        buffer[keysize] = (byte) (rg.nextInt(254)+1);
    }
    --keysize;
    buffer[keysize] = 2;
    --keysize;
    buffer[keysize] = 0;

    return new BigInteger(buffer);
}

the rsa encription:

http://hc.apache.org/downloads.cgi

//you need httpcomponents-client-4.3.1-bin.zip from apache.org
//this contains working Base64 encoder!
import org.apache.commons.codec.binary.Base64;
public String encrypt(String data,String modulus,String exponent) throws UnsupportedEncodingException{
    byte[] exp=Helper.hexToBytes(exponent.toCharArray());
    byte[] mod=Helper.hexToBytes(modulus.toCharArray());

    BigInteger expB=new BigInteger(exp);
    BigInteger modB=new BigInteger(mod);

    BigInteger data2=this.pkcs1pad2(data, (modB.bitLength()+7)>>3);
    BigInteger data3=data2.modPow(expB, modB);

    byte[] encoding = (new Base64()).encode(Helper.hexToBytes(data3.toString(16).toCharArray()));
    return new String(encoding, "US-ASCII");
}

and the Helper.HexToBytes:

 public static byte[] hexToBytes(char[] hex)throws IllegalArgumentException{
     byte[] data = new byte[hex.length / 2];
     for (int i = 0, j = 0; j < data.length; ++j){
         int hi = Character.digit(hex[i++], 16);
         int lo = Character.digit(hex[i++], 16);
         if ((hi < 0) || (lo < 0))
             throw new IllegalArgumentException();
         data[j] = (byte) (hi << 4 | lo);
     }
     return data;
 }

Post a Comment for "How Do I Encrypt Crypto-JS Keys With JSBN?"