我正在尝试用JavaScript加密短字符串,并用Java解密它。解密失败,我认为这是由于两个平台之间的块模式和/或填充不同。我尝试用Java和JavaScript加密相同的字符串,但结果不同,这表明确实存在差异。这是创建密钥的Java代码:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
这是我用来测试加密的Java代码:
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] bytes = cipher.doFinal("asdf".getBytes());
我将公共密钥发送到JavaScript进程,并将其转换为具有变量名称publicKey
的ArrayBuffer。我已经验证了JavaScript端的键是否与Java端的键匹配(通过使用crypto.subtle.exportKey
导出并检查字节)。这是我用来测试加密的JavaScript代码:
crypto.subtle.importKey('spki', publicKey,
{hash: 'SHA-256', name: 'RSA-OAEP'}, true,
['encrypt'])
.then((key) => {
crypto.subtle.encrypt({name: 'RSA-OAEP'}, key,
new TextEncoder().encode('asdf'))
.then((buffer) => {
});
});
Java中字节数组的内容与JavaScript中数组缓冲区的内容不同。我不确定的设置是Java方面的Cipher#getInstance
参数和JavaScript方面的importKey
和encrypt
参数。使用内置类,在Java和JavaScript之间是否有任何设置可以使用?还是应该看看第三方图书馆(例如Bouncy Castle)?
答案 0 :(得分:4)
这很老了,但是如果您想在javascript中使用微妙的加密,并且可以控制Java解密,则可以使用另一种解决方案。
这是假设您使用问题中的原始JS代码进行加密的Java解密方法:
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, privKey, oaepParams);
byte[] decrypted = cipher.doFinal(encryptedBytes)
密码RSA/ECB/OAEPWithSHA-256AndMGF1Padding
的问题在于,默认情况下,它对MGF1填充使用SHA-1。 Javascript使用SHA-256,这会导致不匹配。通过指定MGF1ParamterSpec,我们可以强制Java使用与Javascript默认值相同的哈希算法。
答案 1 :(得分:2)
除了@Chip的答案(这确实有帮助)之外,我还要添加以下情况:
假设您要使用以下内容进行Java解密(webcrypto):
td
然后,您必须使用以下OAEPParameterSpec在Java中进行加密(反之亦然,但我没有尝试过):
th
由于@Chip仅指MGF1填充I,因此我认为必须使用
th {
background-color: #1DA6C0;
text-align: left;
font-weight: normal;
}
但显然必须将两个哈希函数都更改为SHA-512,如我的第一个OAEPParameterSpec代码块所示。
答案 2 :(得分:0)
似乎JavaScript和Java中的内置加密/解密没有RSA加密的兼容设置。可行的解决方案似乎是来自github(forge on github)的伪造库。密钥设置在github页上的描述如下(RSA examples):
// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
});