我正在使用私有 RSA 密钥使用默认的 Java RSA 实现来加密随机 AES 密钥:
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] cipherBytes = cipher.doFinal(plainText.getBytes());
由于无论如何我们都需要一个公钥,这是一种伪装密钥并确保它已用我们的私钥加密的便捷方法。解密方法类似:
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] plainBytes = cipher.doFinal(cipherBytes);
这适用于 Oracle 的 JDK,但对于 IBM 的则失败,因为 IBM 认为使用私钥进行加密不是一个有效的用例。不幸的是,我必须同时支持这两个 JDK,所以我正在尝试自己重新实现 RSA 解密。
这是我到目前为止的代码:
BigInteger big = new BigInteger(cipherBytes);
big = big.modPow(pub.getPublicExponent(), pub.getModulus());
System.out.println(new String(big.toByteArray()));
它几乎可以工作,但似乎存在填充问题。大多数时候,我得到的原始文本前面有一串点状符号,但有时它只是随机字节。
不幸的是,我无法弄清楚默认使用哪种填充方案。有谁知道我的代码中缺少什么,或者至少可以提示使用哪种算法处理填充?
这是一个输入和输出值的示例,根据要求。我使用 512 位密钥来避免数字太大。
Public modulus : 8117919732251191237549784557538073836207094968952416063837701691514861428726690140363567956265691836505266266364256892197254736023284927189008247933889303
Public exponent: 65537
Plaintext: teststring
Plaintext as BN: 549665952565679142563431
Ciphertext as BN: 6304229782339071167863563708554898540621778162930150363326921290545577949349781053660336996882823758722402137580193903457839924005473545992074817339077456
"Decrypted" BN: 409173825987017733751648712103449894027080255755383098685411421012016724550584319360408761540738019643860835515945008876151848132891805352276483731047
Resultstring: ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇteststring
为了解决我为什么要这样做的讨论:
公钥被硬编码到我的软件中。我使用私钥为 AES 加密另一个密钥。因此,要使用 AES 实际解码任何内容,您首先需要 AES 密钥。要获取此密钥,您必须先使用公钥对其进行解密。由于公钥不能在未经严重操纵的情况下被修改,因此只有用私钥加密的 AES 密钥才能工作。您可以以某种方式提取公钥并解密 AES 密钥,但这很复杂,只能让您获得 AES 密钥来解密受保护的内容。还有一个用私钥计算的签名,也用公钥验证。所以操纵是不可能的。
所以是的,从技术上讲,签名就足够了,因为有阅读内容的方法。但这些都是精心设计的,我不介意是否有人真的费尽心思,但我不想让事情变得简单。