我正在try 使用我用OpenSSL生成的密钥.以下是我用来创建它们的命令:

openssl genrsa -out keypair-2023.pem 4096
openssl rsa -in keypair-2023.pem -pubout -out pub-2023.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair-2023.pem -out priv-2023-v8.key

文件的格式是这样的……

-----BEGIN PUBLIC KEY-----
{{ public key contents }}
-----END PUBLIC KEY-----

-----BEGIN PRIVATE KEY-----
{{ private key contents }}
-----END PRIVATE KEY-----

下面是我try 过的几个代码片段,目的是让它们正常工作(以及结果)

var rsaKey = RSA.Create();

rsaKey.ImportFromPem(privateKeyStr);
rsaKey.ImportFromPem(publicKeyStr);

var rsaParams = rsaKey.ExportParameters(true);

var securityKey = new RsaSecurityKey(rsaParams);

结果:"ExportParameters"行中的System.Security.Cryptography.CryptographicException: 'Key does not exist.'

var privateKeyBuffer = new Span<byte>(new byte[privateKeyStr.Length]);
Convert.TryFromBase64String(privateKeyStr, privateKeyBuffer, out _);

var rsaKey = RSA.Create();
rsaKey.ImportRSAPrivateKey(privateKeyBuffer, out _);
rsaKey.ImportFromPem(publicKeyStr);

var rsaParams = rsaKey.ExportParameters(true);

结果:"ImportRSAPrivateKey"行为AsnContentException: The provided data is tagged with 'Universal' class value '0', but it should have been 'Universal' class value '16'.

将"ImportRSAPrivateKey"方法替换为"ImportPkcs8PrivateKey"会引发相同的异常.

现在,这些密钥的用途是对JWT令牌进行签名和验证.如果我使用第一个代码片段,但使用"rsaKey"对象创建了"securityKey",则代码如下:

var rsaKey = RSA.Create();

rsaKey.ImportFromPem(privateKeyStr);
rsaKey.ImportFromPem(publicKeyStr);


var securityKey = new RsaSecurityKey(rsaKey);
_signingCredentials = new SigningCredentials(securityKey, Security算法rithms.RsaSha512);
_securityTokenHandler = new JwtSecurityTokenHandler();

应用程序启动,但是当我找到在创建JWT令牌时使用"_signingCredentials"的代码时,我得到了这个异常:System.Security.Cryptography.CryptographicException: 'Key does not exist.'

有没有一种方法可以正确使用密钥,以便我可以创建JWT令牌?(我怀疑,如果我可以超过var rsaParams = rsaKey.ExportParameters(true)行,那么JWT令牌签名应该可以工作).

推荐答案

First you import the private key, then you import the public key and thereby overwrite the private key, i.e. in the end only the public key is imported.
Since the private key is needed for ExportParameters(true) and when signing, but this is missing, the CryptographicException' 'Key does not exist' is thrown.

FIX:为了不覆盖私钥,必须删除第rsaKey.ImportFromPem(publicKeyStr)行.有了这一更改,就可以完成签名并成功创建令牌.

下面的代码执行您想要的操作:

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
...
var rsaKey = RSA.Create();
rsaKey.ImportFromPem(privateKeyStr);
//rsaKey.ImportFromPem(publicKeyStr);                       // Fix: remove line
var rsaParams = rsaKey.ExportParameters(true);              // succeeds now...
var securityKey = new RsaSecurityKey(rsaKey);
var _signingCredentials = new SigningCredentials(securityKey, Security算法rithms.RsaSha512);
var jwt = new JwtSecurityToken(new JwtHeader(_signingCredentials),new JwtPayload("issuer", "audience", new List<Claim>(), DateTime.UtcNow, DateTime.UtcNow.AddHours(3)));
var token = new JwtSecurityTokenHandler().WriteToken(jwt);  // succeeds now...

The second code snippet would fail for the same reason, but throws an exception even before that, since the format of the posted private key is PKCS#8, while ImportRSAPrivateKey() requires a private key in PKCS#1 format.
Furthermore, ImportRSAPrivateKey() expects a DER encoded key, while the posted keys are PEM encoded (the DER encoded key can be derived from the PEM encoded one by removing header, footer and line breaks and Base64 decoding the remainder).

Csharp相关问答推荐

有没有方法让ASP.NET Core模型绑定器使用私有设置器来设置属性?

HttpContext. RequestAborted当Android APP失go 连接时未取消

==和Tuple对象的相等<>

MAUI查询参数单一字符串项将不起作用

返回TyedResults.BadRequest<;字符串>;时问题详细信息不起作用

TeamsBot SendActivityActivityTypes与ActivityTypes同步.键入不再起作用

当我没有此令牌时,为什么语法报告EOF错误?

ASP.NET Core MVC将值从视图传递到控制器时出现问题

链接到字典字符串.拆分为(.Key,.Value)

如何在microsoft.clearscript.v8的jsondata中使用Linq

当try 测试具有协变返回类型的抽象属性时,类似功能引发System.ArgumentException

为什么ReadOnlySpan;T&>没有Slice(...)的重载接受Range实例的?

JsonPath在Newtonsoft.Json';S实现中的赋值

在C#中,当输入一个方法/局部函数时,我的IEnumerator被重置/重新创建.为什么?

Blazor服务器项目中的Blazor/.NET 8/Web API不工作

如何在Polly重试策略成功之前将HttpClient请求排队?

未显示详细信息的弹出对话框

.NET8支持Vector512,但为什么向量不能达到512位?

使用Try-Catch-Finally为API端点处理代码--有什么缺点?

根据运行时值获取泛型类型的字典