Javascript RSA-OAEP 不适用于任意输入长度
Javascript RSA-OAEP does not work on arbitrary input lengths
我正在尝试使用 SubtleCrypto 加密 javascript (firefox) 中的字符串。问题在于,加密仅适用于短输入。一旦字符串 (testdata) 超过 190 个字符,它将因 OperationError 而失败。
为什么 SubtleCrypto 会这样,我该如何解决?
代码:
function str2ab(str) {
var encoder = new TextEncoder('utf-8');
return encoder.encode(str);
}
function ab2str(buf) {
var decoder = new TextDecoder('utf-8');
return decoder.decode(buf);
}
var keypair;
var algorithmKeyGen = {
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([1,
0,
1
]), // Equivalent to 65537
hash: {
name: 'SHA-256'
}
};
var crypter = window.crypto.subtle;
function encrypt(buffer) {
return crypter.encrypt(algorithmKeyGen, keypair.publicKey, buffer).then(
function(data) {
alert(ab2str(data));
},
function(error) {
alert(error);
}
);
}
var testdata = "aasasadasdaasasadasdaasazzzzzzzzzzzzzzzzzzzzuuuuuuuuuuuuuuuuuuuuuuuzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzuuuuudddsdfssssssssssdddddddddddzzzzzzzzzzzzzzzzzzzzzzzzzzzzzppppppggppppppppppppppppssssstt"
crypter.generateKey(algorithmKeyGen, true, [
'sign',
'encrypt',
'decrypt',
'verify',
'deriveKey'
]).then(function(res) {
keypair = res;
encrypt(str2ab(testdata));
}, console.error.bind(console, 'Unable to generate a key'));
经过一番研究,我发现您的问题可能有以下原因:
浏览器特定:
- 错误的 Firefox 版本。该库支持 v34,并且兼容性级别可能取决于您使用的浏览器版本。确保你有正确的版本:
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt
加密数据时:
- 您的 normalizedAlgorithm 计数器成员的长度不是 16 字节
- normalizedAlgorithm 的长度成员为零或大于 128
- 密钥生成失败
https://www.w3.org/TR/WebCryptoAPI/
考虑到这一点,我相信问题不在于您要加密的文本,而在于您如何调用该函数。
另一个可能的原因(虽然,我不会把钱花在上面)是加密一个很长的字符串会生成一个对浏览器来说太长的变量。查看此讨论:
- Javascript maximum size for types?
RSA 不适用于批量加密。可以使用 RSA 加密的具体数据量取决于密钥大小和您使用的填充。
一个 2048 位密钥 允许 256 字节,其中 OAEP 填充 采用 42 字节,剩下大约 214 字节 用于加密数据。
通常您会使用 RSA 来加密对称密钥,然后使用该对称密钥来加密实际数据。通常称为 hybrid encryption.
我正在尝试使用 SubtleCrypto 加密 javascript (firefox) 中的字符串。问题在于,加密仅适用于短输入。一旦字符串 (testdata) 超过 190 个字符,它将因 OperationError 而失败。 为什么 SubtleCrypto 会这样,我该如何解决?
代码:
function str2ab(str) {
var encoder = new TextEncoder('utf-8');
return encoder.encode(str);
}
function ab2str(buf) {
var decoder = new TextDecoder('utf-8');
return decoder.decode(buf);
}
var keypair;
var algorithmKeyGen = {
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([1,
0,
1
]), // Equivalent to 65537
hash: {
name: 'SHA-256'
}
};
var crypter = window.crypto.subtle;
function encrypt(buffer) {
return crypter.encrypt(algorithmKeyGen, keypair.publicKey, buffer).then(
function(data) {
alert(ab2str(data));
},
function(error) {
alert(error);
}
);
}
var testdata = "aasasadasdaasasadasdaasazzzzzzzzzzzzzzzzzzzzuuuuuuuuuuuuuuuuuuuuuuuzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzuuuuudddsdfssssssssssdddddddddddzzzzzzzzzzzzzzzzzzzzzzzzzzzzzppppppggppppppppppppppppssssstt"
crypter.generateKey(algorithmKeyGen, true, [
'sign',
'encrypt',
'decrypt',
'verify',
'deriveKey'
]).then(function(res) {
keypair = res;
encrypt(str2ab(testdata));
}, console.error.bind(console, 'Unable to generate a key'));
经过一番研究,我发现您的问题可能有以下原因:
浏览器特定:
- 错误的 Firefox 版本。该库支持 v34,并且兼容性级别可能取决于您使用的浏览器版本。确保你有正确的版本:
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt
加密数据时:
- 您的 normalizedAlgorithm 计数器成员的长度不是 16 字节
- normalizedAlgorithm 的长度成员为零或大于 128
- 密钥生成失败
https://www.w3.org/TR/WebCryptoAPI/
考虑到这一点,我相信问题不在于您要加密的文本,而在于您如何调用该函数。
另一个可能的原因(虽然,我不会把钱花在上面)是加密一个很长的字符串会生成一个对浏览器来说太长的变量。查看此讨论:
- Javascript maximum size for types?
RSA 不适用于批量加密。可以使用 RSA 加密的具体数据量取决于密钥大小和您使用的填充。
一个 2048 位密钥 允许 256 字节,其中 OAEP 填充 采用 42 字节,剩下大约 214 字节 用于加密数据。
通常您会使用 RSA 来加密对称密钥,然后使用该对称密钥来加密实际数据。通常称为 hybrid encryption.