如何使用rs256算法使用我自己的rsa私钥对字节进行签名

本文关键字:字节 私钥 rsa 自己的 rs256 何使用 算法 我自己 | 更新日期: 2023-09-27 18:22:15

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

-----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);

现在我需要用我的私钥对这些字节进行签名,正如我上面提到的那样,使用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时,它不起作用,并抛出一个错误。

如何使用rs256算法使用我自己的rsa私钥对字节进行签名

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

  1. 用于编码和解码JWT令牌的JWT
  2. Bouncy Castle支持加密和解密,尤其是RS256,请点击此处

首先,您需要将私钥转换为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私钥-----

我将在步骤中列出我的答案

  1. 为此,您需要安装一个包来获得一个名为Josejwt的库。这代表JavaScript对象签名和加密。从NuGet包管理器Install-package Jose-jwt安装包
  2. 使用OpenSSL,将您的私钥以PKCS12文件(*.p12)的形式打包,在此过程中您将为该文件设置密码。

    openssl pkcs12 -export -nocerts -in ./myKey.key -out my-Key.p12
    
  3. 如Library的自述文件中所列,您需要从该文件生成一个RSACryptoServiceProvider,如下所示:

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

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

我最近不得不实现类似的目标,在签署我的有效负载时遇到了一个错误"指定的算法无效",所以解决了我的特定问题,我想我应该共享代码。我认为这可能对你也有用。

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

请告诉我你进展如何。

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

它解决了我的要求。