在JS/TS中构造RSA公钥

问题描述 投票:0回答:1

我有一个 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=

当我将其与其他公钥进行比较时,我注意到我的密钥具有在其他工作公钥中看不到的字符(如我上面链接的示例中的字符)。

我是否缺少转换?我已经搜索过网站,但无法看出问题所在。

javascript c# reactjs typescript rsa
1个回答
0
投票

我已经查看了您在问题中链接的示例。在示例中,他们使用 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 编码的公钥参数、指数和模数组成。这里你有两个选择:

  1. 在后端创建完整的 RSA PEM 公钥并将其发送到前端。
  2. 根据公钥参数在前端代码中生成公钥。

如果您查看库存储库,就会发现有一个关于从其参数创建公钥的开放“问题”。以下是上述问题中有关如何从其参数创建密钥的代码副本: 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

PKCS#1。另外,不要忘记在创建密钥时使用适当的密钥长度(您可能会发现this有用)。

© www.soinside.com 2019 - 2024. All rights reserved.