我有一个c#Web API,它将公钥传递给Reaction应用程序.我需要使用该公钥来加密有效负载/消息,然后将其发送回我的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库使用来自后端的公钥加密有效负载(example here).但它正在失败.以下是我的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+m1lcJpcj49aVMFnoo0eJ5nBIMXVô1Qz0EpR3BreHp0X0Yfavf2E1lyIl5oyQFTpuzvMu0U3DebLvRezICn66CmFJxnsuERTM5NN

当我将其与其他公钥进行比较时,我注意到我的公钥具有在其他正常工作的公钥中看不到的字符(就像我上面链接的例子中的那个).

有没有我错过的转换?我已经搜索了网站,但看不到可能是什么问题.

推荐答案

我已经看了你在问题中链接的例子.在本例中,他们使用了PEM个RSA密钥,包括公钥和私钥.他们正在使用的公钥

const pub_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeoeE0ytVpM2uDidhMFilE13nXHfEIQqfMJ1TUqGotm6HI72h6ZEqf2PhZEcZkyV34u1d822dqoJMs00IlQiNsshdzU2cIrDYhqPNRfkcHQXCzZoep/BAUvUQrDouhSl89BQXzxK45CLdoy2kcvqqXb2U+GK9LmSqxJSWPEZDYZQIDAQAB'

可以写成

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeoeE0ytVpM2uDidhMFilE
13nXHfEIQqfMJ1TUqGotm6HI72h6ZEqf2PhZEcZkyV34u1d822dqoJMs00IlQiNss
hdzU2cIrDYhqPNRfkcHQXCzZoep/BAUvUQrDouhSl89BQXzxK45CLdoy2kcvqqX
b2U+GK9LmSqxJSWPEZDYZQIDAQAB
-----END PUBLIC KEY-----

这意味着他们使用的是模数为dea1e134cad569336b8389d84c162944d779d71df10842a7cc2754d4a86a2d9ba1c8ef687a644a9fd8f85911c664c95df8bb577cdb676aa0932cd3422542236cb21773536708ac3621a8f3517e47074170b36687a9fc100014bd442b0e8ba14a5f3d0505f3c4ae3908b768cb691cbeaa976f653e18af4b992ab125258f1190d865、公共指数为10001的X.509格式的公钥.

如果您查看JSEncryptcode库,您会发现方法setPublicKey需要一个字符串格式的密钥.它没有在方法注释中指定格式,但从您提供的示例和我找到的一些其他在线示例来看,此方法需要PEM格式的公共RSA密钥.更重要的是,在README中,他们已经声明他们的库使用PEM格式.This is the reason your code isn't working.您正在向该方法发送一个密钥,该密钥由串联的Base64编码的公钥参数、指数和模数组成.这里有两个选项:

  1. 在后台创建一个完整的公有RSA PEM密钥,并将其发送到前端.
  2. 从您的公钥参数在您的前端代码中生成公钥.

如果你看一下库仓库,有一个关于从它的参数创建公钥的开放issue.下面是上述问题中关于如何从其参数创建密钥的代码的副本:

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很有用).

Javascript相关问答推荐

可以的.是否可以在不预编译的情况下使用嵌套 Select 器?

使用AJX发送表单后,$_Post看起来为空

我开始使用/url?q=使用Cheerio

Rehype将hashtag呈现为URL

google docs boldText直到按行执行应用脚本错误

如何根据当前打开的BottomTab Screeb动态加载React组件?

rxjs插入延迟数据

在SHINY R中的嵌套模块中,不能使用Java代码

如何根据输入数量正确显示alert ?

Socket.IO在刷新页面时执行函数两次

Reaction useState和useLoaderData的组合使用引发无限循环错误

react 路由如何使用从加载器返回的数据

如果对象中的字段等于某个值,则从数组列表中删除对象

调用特定数组索引时,为什么类型脚本不判断未定义

我们是否可以在reactjs中创建多个同名的路由

Played link-Initialize.js永远显示加载符号

JSX/React -如何在组件props 中循环遍历数组

REACT-本机错误:错误类型错误:无法读取未定义的容器的属性

通过ng-绑定-html使用插入的HTML中的函数

观察子组件中的@Output事件emits 器?