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