当前位置: 首页 > 知识库问答 >
问题:

如何使用带有RSA私钥的RS256对JWT进行签名

太叔志文
2023-03-14

我正在使用jose-jwt库,并希望使用RS256加密算法在C#中创建一个有签名的JWT。我对密码学没有经验,所以请原谅我的无知。我在文档中看到以下示例:

var payload = new Dictionary<string, object>()
{
    { "sub", "mr.x@contoso.com" },
    { "exp", 1300819380 }
};

var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;

string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);

它显示了p12文件的使用,但是如何使用下面表单的RSA密钥文件呢?我正在查看X509Certificate2的文档,但我看不到RSA私钥的选项。它似乎只接受PKCS7,我认为这是公钥。

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp
wmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5
1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh
3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2
pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX
GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il
AkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF
L0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k
X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
-----END RSA PRIVATE KEY-----

最后,文档中列出的两个选项之间的区别是什么?我如何在这两个选项之间进行选择?

CLR:

RS256、RS384、RS512和PS256、PS384、PS512签名需要相应长度的RSACryptoServiceProvider(通常是私有)密钥。CSP需要强制使用Microsoft增强的RSA和AES加密提供程序。通常可以重新导入rsaparameters。详情见http://clrsecurity.codeplex.com/discussions/243156。

-----------------------------------------------------------------------------------------------------------

共有1个答案

郁景龙
2023-03-14

我知道这个帖子很旧,但我花了很长时间才明白这一点,所以我想我会分享。

为了测试,我使用OpenSSL创建了RSA密钥:

openssl genrsa -out privateKey.pem 512
openssl rsa -in privateKey.pem -pubout -out publicKey.pem

您将需要以下2个nuget包:

    null
public static void Test()
{
        string publicKey = File.ReadAllText(@"W:\Dev\Temp\rsa_keys\publicKey.pem");
        string privateKey = File.ReadAllText(@"W:\Dev\Temp\rsa_keys\privateKey.pem");
        
        var claims = new List<Claim>();
        claims.Add(new Claim("claim1", "value1"));
        claims.Add(new Claim("claim2", "value2"));
        claims.Add(new Claim("claim3", "value3"));

        var token = CreateToken(claims, privateKey);
        var payload = DecodeToken(token, publicKey);
}
public static string CreateToken(List<Claim> claims, string privateRsaKey)
{
     RSAParameters rsaParams;
     using (var tr = new StringReader(privateRsaKey))
     {
          var pemReader = new PemReader(tr);
          var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
          if (keyPair == null)
          {
               throw new Exception("Could not read RSA private key");
          } 
          var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters;
          rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams);
     }
     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
     {
          rsa.ImportParameters(rsaParams);
          Dictionary<string, object> payload = claims.ToDictionary(k => k.Type, v => (object)v.Value);
          return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
     }
}
public static string DecodeToken(string token, string publicRsaKey)
{
     RSAParameters rsaParams;

     using (var tr = new StringReader(publicRsaKey))
     {
          var pemReader = new PemReader(tr);
          var publicKeyParams = pemReader.ReadObject() as RsaKeyParameters;
          if (publicKeyParams == null)
          {
               throw new Exception("Could not read RSA public key");
          }
          rsaParams = DotNetUtilities.ToRSAParameters(publicKeyParams);
     }
     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
     {
          rsa.ImportParameters(rsaParams);
          // This will throw if the signature is invalid
          return Jose.JWT.Decode(token, rsa, Jose.JwsAlgorithm.RS256);  
     }
}
 类似资料:
  • 我需要与GitHub集成API进行交互,但具体是从。NET 4.0,所以我不能使用Octokit。 基本上,我得到了一个格式化的私有rsa密钥(标准不支持。NET API),并且必须发送RS256 jwt令牌才能获得与API交互的身份验证令牌。 提供了以下ruby示例代码: 使用下面的curl示例 以及以下Result示例:

  • 是否可以使用pycryptodome或任何其他库在python中使用私钥加密消息?我知道你不应该用私钥加密而用公钥解密,但我的目的是用私钥加密,这样接收者就可以确定消息是由真正的作者发送的。除了安全加密之外,我还在寻找某种模糊处理。我想做一个应用程序,其中的消息是公开的,但它只能看到,如果你有公钥。我尝试过这样做: 但它会引发下一个错误:TypeError:这不是私钥。

  • 对示例代码中应用的概念“带RSA加密的JSON Web令牌(JWT)”有疑问 参见:http://connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-rsa-encryption 我的问题:为什么客户端使用私钥?为什么不在加密器上使用私钥,在解密器类上使用公钥呢? 欢迎对此RSA示例代码的概念方面进行澄清。

  • 我试图在VBA中生成JSON Web令牌(JWT)。我需要用RS256签名。到目前为止,我成功地创建了base64编码的报头和有效负载。他们两人都工作得很好。 现在我被困在用RS256签署JWT报头有效载荷上了。我找不到默认的VBA类或函数,它提供RSA-SHA256使用私钥进行加密。在官方的微软留档中,我只找到了使用公钥加密的方法:https://docs.microsoft.com/en-us

  • 我想知道是否有一个示例C代码或库可以使用RSA公钥验证我的JWT令牌签名。我找不到任何涉及C的示例 openssl for C没有任何与RSA相关的示例。 谢谢