Java和JavaScript之间使用OAEP进行RSA加密

时间:2019-04-04 22:09:02

标签: javascript java encryption rsa

我正在尝试用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方面的importKeyencrypt参数。使用内置类,在Java和JavaScript之间是否有任何设置可以使用?还是应该看看第三方图书馆(例如Bouncy Castle)?

3 个答案:

答案 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()
  }
});