2013-05-21 48 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; 
}