如何使用rs256算法使用我自己的rsa私钥来签名字节?

时间:2014-09-18 09:32:19

标签: c# cryptography rsa encode jwt

我有自己的私钥字符串,即

-----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时,它不起作用并抛出错误。

4 个答案:

答案 0 :(得分:0)

我最近不得不实现类似的功能并遇到错误&#34;指定的无效算法&#34;在签署我的有效负载时,已经解决了我认为我分享代码的具体问题。我认为这对你也很有用。

您可以在Karama.Jwt.Public找到完整的解释[ReadME] [2]和源代码。我碰巧使用不同的库来生成我的JWT,即JOSE,但我认为这是偶然的,并且为了完整性,有一个项目使用没有第三方库实现相同目的。

请告诉我你是怎么过的。

答案 1 :(得分:0)

我将按步骤

列出我的答案
  1. 为此,您需要安装一个软件包才能获得名为Jose-jwt的库。这代表JavaScript Object Signing and Encrypting。从NuGet包管理器Install-package Jose-jwt
  2. 安装包
  3. 使用OpenSSL,以PKCS12文件(* .p12)的形式打包您的私钥,您将在此过程中为该文件设置密码。

    openssl pkcs12 -export -nocerts -in ./myKey.key -out my-Key.p12
    
  4. Library's readme所列,您需要从该文件中生成RSACryptoServiceProvider,如下所示:

    var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
    
  5. 使用RSACryptoServiceProvider createdalong和PKCS12打包期间设置的密码对您的有效负载进行编码,如下所示:

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

答案 2 :(得分:0)

这个问题的关键是使用JWT和Bouncy城​​堡库分别对令牌进行编码和签名。

  1. continuation-passing style用于编码和解码JWT令牌
  2. JWT支持加密和解密,尤其是RS256 Bouncy Castle

首先,您需要将私钥转换为RSA参数的形式。然后,您需要将RSA参数作为私钥传递给RSA算法。最后,您使用JWT库对令牌进行编码和签名。

N

ps:RSA私钥应具有以下格式:

-----开始使用RSA私钥-----

{base64格式的值}

-----结束RSA私钥-----

答案 3 :(得分:-3)

我发现了一些纯粹的基于Javascript的解决方案,如果它对任何人都有用。你可以找到JS Libraries here

它已经解决了我的要求。