我有一个 C# Web api,它将公钥传递给 React 应用程序。我需要使用该公钥来加密有效负载/消息,然后将其发送回我的 api。但是,我在前端重建公钥时遇到了麻烦。让我解释一下。
该应用程序不使用 https,仅使用 http。鉴于这种情况,我继续在 C# 中生成公钥和私钥,如下所示:
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters publicKey = rsa.ExportParameters(false);
RSAParameters privateKey = rsa.ExportParameters(true);
}
公钥生成模数(n)和指数(e)参数的字节数组,可用于重建公钥(我已经在后端测试过)。因此,我然后将 n 和 e 转换为 Base64 字符串并将它们发送给客户端。
现在,在我的 React 应用程序中,我使用 JSEncrypt 库使用后端的公钥对有效负载进行加密(此处为示例)。但它正在失败。这是我的js:
const encryptMessage = (messageToEncrypt) => {
if (publicKeyParts?.length === 2) {
const encrypt = new JSEncrypt();
// publicKeyParts is a string[] with the exponent stored in index 0
// and the modulus stored in index 1
encrypt.setPublicKey(`${publicKeyParts[1]}${publicKeyParts[0]}`);
let data = {
payload: messageToEncrypt
}
let encryptedPayload = encrypt.encrypt(JSON.stringify(data));
return encryptedPayload;
}
}
加密消息是假的,不起作用。我认为这与我的公钥的格式有关。这是我从 C# 生成的公钥(并转换为 Base64):
8NHGP6WqPGgHa5Q+15V5z+SI7XAvIgMVjbNuGdmlvHoLY2kutP5u+m1lcJpcj49aVMFnoo0eJ5nBIMXVMw1Qz0EpR3BreHp0X0Yfavf2E1lyIl5oyQFTpuzvMu0U3DebLvRezICn66CmFJxnsuERTM5 NQ+vE5/3WUx4uMI8jKLE=
当我将其与其他公钥进行比较时,我注意到我的密钥具有在其他工作公钥中看不到的字符(如我上面链接的示例中的字符)。
我是否缺少转换?我已经搜索过网站,但无法看出问题所在。
我已经查看了您在问题中链接的示例。在示例中,他们使用 PEM RSA 密钥,包括公共密钥和私有密钥。他们正在使用的公钥
const pub_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeoeE0ytVpM2uDidhMFilE13nXHfEIQqfMJ1TUqGotm6HI72h6ZEqf2PhZEcZkyV34u1d822dqoJMs00IlQiNsshdzU2cIrDYhqPNRfkcHQXCzZoep/BAUvUQrDouhSl89BQXzxK45CLdoy2kcvqqXb2U+GK9LmSqxJSWPEZDYZQIDAQAB'
可以写成
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeoeE0ytVpM2uDidhMFilE
13nXHfEIQqfMJ1TUqGotm6HI72h6ZEqf2PhZEcZkyV34u1d822dqoJMs00IlQiNss
hdzU2cIrDYhqPNRfkcHQXCzZoep/BAUvUQrDouhSl89BQXzxK45CLdoy2kcvqqX
b2U+GK9LmSqxJSWPEZDYZQIDAQAB
-----END PUBLIC KEY-----
意味着他们使用 X.509 格式的公钥,模数为
dea1e134cad569336b8389d84c162944d779d71df10842a7cc2754d4a86a2d9ba1c8ef687a644a9fd8f85911c664c95df8bb577cdb676aa0932cd3422542236cb21773536708ac3621a8f3517e47074170b36687a9fc1014bd442b0e8ba14a5f3d0505f3c4ae3908b768cb691cbeaa976f653e18af4b992ab125258f1190d865
,公共指数为 10001
。
如果您查看库 JSEncrypt code,您会发现方法
setPublicKey
需要字符串格式的密钥。它没有指定格式,但从您提供的示例和我发现的其他一些在线示例来看,此方法需要 PEM 格式的公共 RSA 密钥。 这就是您的代码无法工作的原因。您将向此方法发送一个密钥,该密钥由连接的、base64 编码的公钥参数、指数和模数组成。这里你有两个选择:
如果您查看库存储库,就会发现有一个关于从其参数创建公钥的开放“问题”。以下是上述问题中有关如何从其参数创建密钥的代码副本:
import JSEncrypt from 'jsencrypt';
import { parseBigInt } from 'jsencrypt/lib/lib/jsbn/jsbn';
const nStr = 'BB6FE79432CC6EA2D8F970675A5A87BFBE1AFF0BE63E879F2AFFB93644D4D2C6D000430DEC66ABF47829E74B8C5108623A1C0EE8BE217B3AD8D36D5EB4FCA1D9';
const eStr = '010001';
const n = parseBigInt(nStr, 16);
const e = parseInt(eStr, 16);
const encrypt = new JSEncrypt();
const key = encrypt.getKey();
key.parsePropertiesFrom({ n, e });
最后,请注意加密数据时使用的填充方案:OAEP