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

C# 如何使用rs256算法使用我自己的rsa私钥对字节进行签名?,c#,cryptography,rsa,encode,jwt,C#,Cryptography,Rsa,Encode,Jwt,我有自己的私钥字符串,即 -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCSAYYgzvGTww.... .... .... ..... 3yUMYj9oYzqdrRHP0XgD0cEEvyqPBwLaNsRdFwy5qTiHjj0f+ZWHQWmqcoLmmpzyZEbIvQm/VhbjRF6iKG4WZ9Hfa7ntYRNGdWgD/KMIeZI= -----END RSA PRIVATE KEY----- 现在,我需要在C#中使用这个私钥

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

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

并生成JWT令牌。请让我知道我在哪里犯了一个错误,因为它是不正确的:当我将它传递给API时,它不工作并抛出一个错误。

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


它解决了我的需求。

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


它解决了我的需求。

我最近不得不实现类似的目标,在对有效负载进行签名时遇到了一个错误“指定的算法无效”,因此解决了我的具体问题,我想我应该共享代码。我想这可能对你也有用

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


请让我知道你的进展。

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

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


请让我知道你进展如何。

我会分步列出我的答案

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

    openssl pkcs12 -export -nocerts -in ./myKey.key -out my-Key.p12
    
  • 如上所列,您需要从该文件生成一个
    rsacyptoserviceprovider
    ,如下所示:

    var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
    
    string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
    
  • 使用带有PKCS12打包期间设置的密码的
    RSACryptoServiceProvider
    createdalong对有效负载进行如下编码:

    var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
    
    string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
    

  • 我会分步列出我的答案

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

    openssl pkcs12 -export -nocerts -in ./myKey.key -out my-Key.p12
    
  • 如上所列,您需要从该文件生成一个
    rsacyptoserviceprovider
    ,如下所示:

    var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
    
    string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
    
  • 使用带有PKCS12打包期间设置的密码的
    RSACryptoServiceProvider
    createdalong对有效负载进行如下编码:

    var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
    
    string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
    

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

  • 用于编码和解码JWT令牌
  • 支持加密和解密,尤其是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);
                }
            }
        }
    
    公共字符串GenerateJWTToken(字符串rsaPrivateKey)
    {
    var rsaparms=getrsaparmeters(rsaPrivateKey);
    var编码器=GetRS256JWTEncoder(rsaParams);
    //根据需要创建有效负载
    var payload=新字典
    {
    {“iss”,“},
    {“sub”,“”},
    //和其他关键值
    };
    var token=encoder.Encode(有效负载,新字节[0]);
    返回令牌;
    }
    专用静态IJwtEncoder GetRS256JWTEncoder(RSAParameters rsaParams)
    {
    var csp=新的RSACryptServiceProvider();
    csp.进口参数(rsaParams);
    var算法=新的RS256算法(csp,csp);
    var serializer=new JsonNetSerializer();
    var urlEncoder=new JwtBase64UrlEncoder();
    var编码器=新的JwtEncoder(算法、序列化程序、URLCoder);
    返回编码器;
    }
    私有静态RSAPERAMETERS GetRSAPERAMETERS(字符串rsaPrivateKey)
    {
    var byteArray=Encoding.ASCII.GetBytes(rsaPrivateKey);
    使用(var ms=新内存流(byteArray))
    {
    使用(var sr=新的StreamReader(ms))
    {
    //使用Bouncy Castle将私钥转换为RSA参数
    var pemReader=新pemReader(sr);
    var keyPair=pemReader.ReadObject()作为非对称密码密钥对;
    返回DotNetUtilities.ToRSAParameters(keyPair.Private作为rsaprovatecrtkeyparameters);
    }
    }
    }
    
    ps:RSA私钥应具有以下格式:

    -----开始RSA私钥-----

    {base64格式化值}


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

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

  • 用于编码和解码JWT令牌
  • 支持加密和解密,尤其是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);
                }
            }
        }
    
    公共字符串GenerateJWTToken(字符串rsaPrivateKey)
    {
    var rsaparms=getrsapameters(rsaPrivateKey)