javascript中的RSA不再支持ASCII /字节数组

时间:2016-05-12 01:29:44

标签: javascript encryption cryptography public-key-encryption jsbn

我使用http://www-cs-students.stanford.edu/~tjw/jsbn/中的rsa.js v1.0来加密浏览器中的ASCII字符串。该字符串实际上是一个16字节的数组,包含一个双倍长度的TripleDes键。使用rsa v1.0,这是有效的。字节数组在服务器上正确解密(使用Bouncy Castle或Thales HSM)作为16字节数组。

e.g。

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时,这不再起作用。 Bouncy castle解密数据,但它不是一个16字节的数组,而是一个25字节的数组。

我在rsa.js库中看到的关键区别在于v1.1发行说明:

在PKCS1编码和解码JavaScript字符串时,添加了对非ASCII字符的utf-8编码的支持。

v1.0中的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) {
        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。
  4. 想法?

1 个答案:

答案 0 :(得分:3)

  1. 此代码在两种情况下都实现了PKCS#1 v1.5填充,唯一的区别是utf-8支持。要使其与收件人库一起使用,该库需要以与编码它相同的方式解码内容。祝你好运,我不认为你会找到任何能做到这一点。

  2. 由于Daniel Bleichenbacher在1999年左右的攻击,PKCS#1 v1.5填充为insecure。现在建议使用PKCS#1 v2.x.吴的代码不支持这一点。

  3. 如果您真的想使用这个库(我建议不要使用它),可能最干净的方法是在加密之前发送密钥十六进制编码(&#34; E0F8AD4092F81FC401E60ECB7F5B8F1A&#34;)并确保收件人十六进制解密后对其进行解码:这可以解决吴的UTF-8调整问题。您也可以使用base64编码/解码。

  4. SJCL是一个更好的JavaScript加密库,你不会遇到像这样的问题。据我所知,吴的代码被设计为他精彩的身份验证协议的PoC,而SJCL是为更广泛的用途而设计的,并且由社区维护。