2013-05-21 55 views
2

我使用JSBN来使用公钥/私钥对来加密/解密数据。它适用于文本数据,包括十六进制字符串。如何使用JSBN加密Crypto-JS密钥?

我的问题是现在我有二进制数据,特别是Crypto-JS字数组,我需要用公钥加密并发送到另一个平台。

所以,可以这样考虑:

var key = CryptoJS.lib.WordArray.random(256/8); 
var rsa = new RSAKey(); 
rsa.setPublic(modulus, exponent); 
var encrypted_key = rsa.encrypt(key.toString()); 

这工作,但它的意思是“encrypted_key”是一个已经加密,而不是实际的密钥INFACT一个十六进制字符串。我需要加密实际的密钥。

所以我在这里看到了两个挑战:

1)我不是100%确定如何获取实际字节出CryptoJS.lib.WordArray的 - 尽管这似乎并没有完全克服。

2)我不知道是否甚至有可能使用JSBN加密二进制数据。我很乐意指出如何去做。

有什么想法?

回答

2

JSBN库包含一个函数,即pkcs1pad2(),其中它使用JavaScript的charCodeAt()函数将文本转换为数值。你会看到在第一,而()循环转换代码:

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); 
} 

如果你愿意的话把它转换你想要的方式输入到加密二进制数据,那么你就可能要修改该功能。

下面是pkcs1pad2()修改为以十六进制字符串形式接受二进制数据的示例。如果您使用此版本的pkcs1pad2(),则可以将CryptoJS.lib.WordArray转换为十六进制,并将该十六进制字符串传递给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); 
} 

或者,你可以修改它直接采取WordArray,转换至所使用JSBN阵列格式,但我会离开,作为一个练习留给读者。

+0

业务收益指数lliant!当然,另一端 - pkcs1unpad2 - 将需要进行类似的修改(或扩展)。 –

0

从JavaScript转换为Java的pkcs1pad2功能:

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); 
} 

的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"); 
} 

和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; 
}