我有自己的私钥字符串,即
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCSAYYgzvGTww....
....
....
.....
3yUMYj9oYzqdrRHP0XgD0cEEvyqPBwLaNsRdFwy5qTiHjj0f+ZWHQWmqcoLmmpzyZEbIvQm/VhbjRF6iKG4WZ9Hfa7ntYRNGdWgD/KMIeZI=
-----END RSA PRIVATE KEY-----
现在,我需要在C#中使用此私钥签署我的声明集,以生成JWT有效负载。
我编写了以下代码:
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var issueTime = DateTime.Now;
var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds;
var payload = new
{
iss = email,
prn = prn,
scope = "scope",
aud = "https://example.com",
exp = exp,
iat = iat
};
var segments = new List<string>();
var header = new { typ = "JWT", alg = "RS256" };
byte[] headerBytes = Encoding.UTF8.GetBytes(jsonSerializer.Serialize(header));
byte[] payloadBytes = Encoding.UTF8.GetBytes(jsonSerializer.Serialize(payload));
segments.Add(Base64UrlEncode(headerBytes));
segments.Add(Base64UrlEncode(payloadBytes));
var stringToSign = string.Join(".", segments.ToArray());
var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
现在我需要这些bytesToSign由我的私钥签名,正如我上面提到的使用rs256算法。有人能帮忙吗?
我已按照以下方式更新了我的代码:
var pemprivatekey = OpenSSLKey.DecodeOpenSSLPrivateKey(privateKey);
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
if (pemprivatekey != null)
{
rsaProvider = OpenSSLKey.DecodeRSAPrivateKey(pemprivatekey);
}
byte[] signature = rsaProvider.SignData(bytesToSign, "SHA256");
segments.Add(Base64UrlEncode(signature));
return string.Join(".", segments.ToArray());
并生成JWT令牌。请让我知道我在哪里犯了错误,因为它不正确:当我把它传递给API时,它不起作用并抛出错误。
这个问题的关键是使用JWT和Bouncy城堡库分别对令牌进行编码和签名。
首先,您需要将私钥转换为RSA参数的形式。然后您需要将RSA参数作为私钥传递给RSA算法。最后,您使用JWT库对令牌进行编码和签名。
public string GenerateJWTToken(string rsaPrivateKey)
{
var rsaParams = GetRsaParameters(rsaPrivateKey);
var encoder = GetRS256JWTEncoder(rsaParams);
// create the payload according to your need
var payload = new Dictionary<string, object>
{
{ "iss", ""},
{ "sub", "" },
// and other key-values
};
var token = encoder.Encode(payload, new byte[0]);
return token;
}
private static IJwtEncoder GetRS256JWTEncoder(RSAParameters rsaParams)
{
var csp = new RSACryptoServiceProvider();
csp.ImportParameters(rsaParams);
var algorithm = new RS256Algorithm(csp, csp);
var serializer = new JsonNetSerializer();
var urlEncoder = new JwtBase64UrlEncoder();
var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
return encoder;
}
private static RSAParameters GetRsaParameters(string rsaPrivateKey)
{
var byteArray = Encoding.ASCII.GetBytes(rsaPrivateKey);
using (var ms = new MemoryStream(byteArray))
{
using (var sr = new StreamReader(ms))
{
// use Bouncy Castle to convert the private key to RSA parameters
var pemReader = new PemReader(sr);
var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
return DotNetUtilities.ToRSAParameters(keyPair.Private as RsaPrivateCrtKeyParameters);
}
}
}
ps:RSA私钥应具有以下格式:
开始RSA私钥
{base64格式化值}
RSA私钥
我会按步骤列出我的答案
>
Install-pack Joes-jwt
使用OpenSSL,以PKCS12文件(*. p12)的形式打包您的私钥,您将在此过程中为文件设置密码。
openssl pkcs12 -export -nocerts -in ./myKey.key -out my-Key.p12
如库的自述文件所列,您需要从该文件生成一个RSACryptoServiceProvider
,如下所示:
var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
使用创建的RSACryptoServiceProvider
以及在PKCS12打包期间设置的密码对您的有效负载进行编码,如下所示:
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
我最近不得不实现类似的东西,在签署我的有效负载时遇到了一个错误“指定的无效算法”,所以已经解决了我的具体问题,我想我会分享代码。我想这对你也可能有用。
你可以在Karama. Jwt.Public找到完整的解释[ReadME][2]和源代码。我碰巧使用了一个不同的库来生成我的JWT,即JOSE,但我认为这是偶然的,为了完整起见,有一个项目不使用第三方库来实现相同的目的。
请让我知道你过得怎么样。