6

我使用http://www-cs-students.stanford.edu/~tjw/jsbn/中的rsa.js v1.0來加密瀏覽器中的ASCII字符串。該字符串實際上是一個包含雙倍長度TripleDes鍵的16字節數組。隨着rsa v1.0這個工程。字節數組在服務器(使用Bouncy Castle或Thales HSM)上正確解密爲16字節數組。JavaScript中的RSA不再支持ASCII /字節數組

例如

var zpk = hex2a("E0F8AD4092F81FC401E60ECB7F5B8F1A"); 
var rsa = new RSAKey(); 
rsa.setPublic(modulus, exponent); 
var res = rsa.encrypt(zpk); 
if (res) { 
    document.rsatest.zpkrsa.value = hex2b64(res); 
} 

移動rsa.js v1.4時不再有效。充氣城堡解密數據,但不是16字節的數組,而是現在的25字節數組。

關鍵的區別我可以在rsa.js圖書館看到的是在V1.1版本說明:

對於非ASCII字符的UTF-8編碼增加的支持時PKCS1編碼和解碼的JavaScript字符串。

的PKCS#1填充在v1.0是:

// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint 
function pkcs1pad2(s, n) { 
    if (n < s.length + 11) { 
     alert("Message too long for RSA"); 
     return null; 
    } 
    var ba = new Array(); 
    var i = s.length - 1; 
    while (i >= 0 && n > 0) ba[--n] = s.charCodeAt(i--); 
    ba[--n] = 0; 
    var rng = new SecureRandom(); 
    ... 
    return new BigInteger(ba); 
} 

中V1.1 PKCS#1填充功能和更高:

// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint 
function pkcs1pad2(s,n) { 
    if(n < s.length + 11) { // TODO: fix for utf-8 
    console.error("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; 
    ... 
    return new BigInteger(ba); 
} 

rsa.js V1.0將每個字符視爲1字節字符。由於v1.1字符經過測試可以看出它們是否是多字節的utf-8。

看來我唯一的選擇,其一是:

  1. 棒與rsa.js V1.0
  2. 創建rsa.js(和rsa2.js),允許我以禁用的修改版本utf-8字符檢測。
  3. (修改)修改使用支持PKCS#1 v2(oaep)的defensivejs.com的代碼。

想法?

+0

有趣的是,PKCS的版本可能會有所不同,這可能會導致很多頭痛。實際上,我強烈建議嘗試使用[Stanford JavaScript Crypto Library](https://github.com/bitwiseshiftleft/sjcl),而不是使用這個庫,這是因爲我知道SJCL被更廣泛地使用和測試。 – TheGreatContini

+0

是的,很確定吳的圖書館正在實施[PCKS#1 v1.5](https://tools.ietf.org/html/rfc2313),它可能會受到Bleichenbacher攻擊。作爲密碼學家,我建議不要使用此代碼!改用SJCL! – TheGreatContini

回答

3
  1. 該代碼在兩種情況下都實現了PKCS#1 v1.5填充,唯一的區別是utf-8支持。爲了與收件人庫一起工作,該庫需要以與編碼內容相同的方式對內容進行解碼。祝你好運,我不認爲你會找到任何這樣做。

  2. 由於Daniel Bleichenbacher在1999年左右發生的攻擊,PKCS#1 v1.5填充爲insecure。現在推薦使用PKCS#1 v2.x.吳的代碼不支持這一點。

  3. 如果你真的想使用這個庫(我建議反對),可能是最乾淨的方法是在你對它進行加密(「E0F8AD4092F81FC401E60ECB7F5B8F1A」)之前編碼的16進制發送,並確保收件人六角解密後對其進行解碼:這會繞吳的UTF-8調整。你也可以使用base64編碼/解碼。

  4. SJCL是一個更好的JavaScript加密庫,你不會遇到這樣的問題。據我所知,吳的代碼被設計成他的精彩認證協議的PoC,而SJCL則是爲了更廣泛的用途而設計的,並且由社區維護。

+0

不幸的是,看起來像SJCL庫不支持RSA。由於解密設備是Thales HSM Payshield 9000(https://en.wikipedia.org/wiki/Hardware_security_module),因此需要RSA。 HSM支持PKCS#1 v2(OEAP) – andyvan

+0

當前實現僅使用公鑰/私鑰對。一旦服務器收到請求,信息就會被處理(成功或失敗),然後這些密鑰被刪除並且不被重新使用。根據這個用例,我會推測Bleichenbacher的CCA攻擊不適用於攻擊者沒有機會用隨機數據重試請求。 – andyvan

+0

@andyvan聖便船蝙蝠俠,你是對的!令人失望!您也可以考慮谷歌的圖書館,但不知道它是多麼困難,或者它有多成熟,請參閱:https://github.com/google/end-to-end/blob/master/src/javascript /crypto/e2e/asymmetric/rsa.js。如果密鑰在失敗時被刪除,那麼。你是對的,攻擊不適用。 – TheGreatContini