当前位置: 首页 > 知识库问答 >
问题:

Java和JavaScript之间使用OAEP的RSA加密

尉迟正平
2023-03-14

我试图用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进程,并将其转换为ArrayBuffer,变量名为publicKey。我已经验证了JavaScript端的密钥与Java端的密钥相匹配(通过使用crypto.minute.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端import Key加密的参数。是否有任何设置可以使用内置类在Java和JavaScript之间工作?或者我应该查看第三方库(例如,Bouncy Castle)?

共有3个答案

习和通
2023-03-14

看起来JavaScript和Java中的内置加密/解密没有与RSA加密兼容的设置。一个可行的解决方案似乎是github的forge库(github上的forge)。github页面上的密钥设置描述如下(RSA示例):

// 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()
  }
});
袁鸿达
2023-03-14

除了@Chip的答案(这真的很有帮助)之外,我想补充以下情况:

假设您希望在Javascript(webcrypto)中使用以下内容进行解密:

window.crypto.subtle.decrypt(
        {
            name: "RSA-OAEP",
            hash: { name: "SHA-512" }
            //label: Uint8Array([...]) //optional
        },
        privateRsaKey, //CryptoKey object containing private RSA key
        encdata //ArrayBuffer containing to be decrypted data
    )
    .catch(function(err){
        console.error(err);
    })

然后您必须在Java中使用以下OAEPParameterSpec进行加密(反之亦然,但我没有尝试):

OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-512", "MGF1", 
        new MGF1ParameterSpec("SHA-512"), PSource.PSpecified.DEFAULT);

由于@Chip只提到了MGF1填充I,所以我假设必须使用

OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-512", "MGF1", 
        new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);

但显然必须将两个哈希函数都更改为SHA-512,如我的第一个OAEPParameterSpec代码块所示。

梁丘俊人
2023-03-14

这很古老,但如果您想在javascript中使用微妙的加密,并控制java解密,这里有一个替代解决方案。

以下是您如何在Java中解密,假设您使用问题中的原始JS代码进行加密

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的问题是,默认情况下,它将SHA-1用于MGF1填充。Javascript使用SHA-256,这会导致不匹配。通过指定mgf1parameterspec,我们可以强制Java使用与Javascript默认值相同的哈希算法。

 类似资料:
  • 我使用的是Web加密,更具体地说,这些示例是:https://github.com/diafygi/webcrypto-examples/#rsa-oaep 更新

  • 我目前正在Javascript上实现RSA-OAEP加密,并在Java上实现解密。 我的javascript代码有以下内容 我还有一个Java函数来解密文本。假设“rsoaepciphertext”是字符串文本。 然而,我在Java上不断遇到解密错误,目前仍停留在这一部分,我在Javascript上的加密是否有任何错误?

  • 一个多星期以来,我一直在使用它与我的python服务器实现RSA安全通信。 然而,我不能为我的生活找出适当的进口所有的罐子。 我已经包括了在bouncy castles网站上找到的所有罐子,但仍然没有骰子! 我读到他们到处搬家。如果这段代码很旧或已损坏,那么还有什么其他带有pkcs1填充的RSA实现? 编辑: pub key位于名为key的文件中。酒吧如何读入该文件以用作密钥 编辑2:根据答案添加

  • 我有一条在java上使用以下代码加密的kafka消息: 现在我正在尝试在我已经知道私钥的解码消息上使用python对其进行解码。我尝试使用(因为我使用的是python3和仅适用于2. x)像在他们的文档中一样使用此代码,但它不起作用: 我得到了这个错误代码:我试图寻找一种方法使私钥成为JWK对象,但找不到。 我知道我的消息是JWE,因为它被4个点分割,当我对第一部分进行base64解码时,我得到了

  • 首先,为我将要发布的代码量道歉。我试图使用Java应用程序中的RSA公钥对Android应用程序中的消息进行加密,然后将密文发送回Java环境进行解密,但在尝试解密时,我总是会遇到以下错误: 密文确实包含正确的字节数(512),因此看到“错误填充”异常会让人困惑。SO上的其他类似帖子建议使用“RSA/ECB/PKCS1Padding”作为算法,但这不起作用。 令人烦恼的是,Android环境中的加

  • 在Android中生成RSA密钥对。Android中包含了Bouncy castle的删减版本: Python中的加密: Android解密。android中包含了Bouncy castle的删减版本: 测试密钥: