我使用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。
看来我唯一的选择,其一是:
- 棒与rsa.js V1.0
- 创建rsa.js(和rsa2.js),允许我以禁用的修改版本utf-8字符检测。
- (修改)修改使用支持PKCS#1 v2(oaep)的defensivejs.com的代码。
想法?
有趣的是,PKCS的版本可能会有所不同,这可能会导致很多头痛。实际上,我强烈建议尝试使用[Stanford JavaScript Crypto Library](https://github.com/bitwiseshiftleft/sjcl),而不是使用这个库,这是因为我知道SJCL被更广泛地使用和测试。 – TheGreatContini
是的,很确定吴的图书馆正在实施[PCKS#1 v1.5](https://tools.ietf.org/html/rfc2313),它可能会受到Bleichenbacher攻击。作为密码学家,我建议不要使用此代码!改用SJCL! – TheGreatContini