C# 如何使用RS256和RSA私钥对JWT进行签名
我正在使用,希望使用RS256加密算法在C#中创建一个签名JWT。我没有密码学方面的经验,请原谅我的无知。我在文档中看到以下示例:C# 如何使用RS256和RSA私钥对JWT进行签名,c#,encryption,rsa,jwt,sha256,C#,Encryption,Rsa,Jwt,Sha256,我正在使用,希望使用RS256加密算法在C#中创建一个签名JWT。我没有密码学方面的经验,请原谅我的无知。我在文档中看到以下示例: var payload = new Dictionary<string, object>() { { "sub", "mr.x@contoso.com" }, { "exp", 1300819380 } }; var privateKey=new X509Certificate2("my-key.p12", "password", X5
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);
最后,中列出的两个选项之间有什么区别,我如何在这两个选项之间进行选择
--------------------------备选方案1------------------
RS-*和PS-*系列
CLR:
RS256、RS384、RS512和PS256、PS384、PS512签名需要
RSACryptServiceProvider(通常为私钥)对应的
长度。CSP需要强制使用Microsoft增强的RSA和AES
加密提供者。这通常可以通过重新导入来完成
RSA参数。看见
详情请参阅
--------------------------备选案文2------------------
CORECLR:RS256、RS384、RS512签名需要相应长度的RSA(通常是私钥)密钥
GetRSAPrivateKey仅在.NET 4.6中可用。请参阅下面的URL
我知道这篇文章很旧,但我花了很长时间才弄明白,所以我想我会与大家分享 要测试我使用OpenSSL创建的RSA密钥,请执行以下操作:
openssl genrsa -out privateKey.pem 512
openssl rsa -in privateKey.pem -pubout -out publicKey.pem
您将需要以下2个nuget软件包:
测试代码
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);
}
我发现了一个很好的资源来测试您的令牌如果您使用公共证书和.NET 4.6进行解码,您可以使用:
string token = "eyJhbGciOiJSUzI1NiIsInR....";
string certificate = "MIICnzCCAYcCBgFd2yEPx....";
var publicKey = new X509Certificate2(Convert.FromBase64String(certificate )).GetRSAPublicKey();
string decoded = JWT.Decode(token, publicKey, JwsAlgorithm.RS256);
var cert = new X509Certificate2(".\\key.cer");
var rsa = (RSACryptoServiceProvider) cert.PublicKey.Key;
var payload = new Dictionary<string, object>()
{
{"sub", "mr.x@contoso.com"},
{"exp", 1300819380}
};
var encryptedToken =
JWT.Encode(
payload,
rsa,
JweAlgorithm.RSA_OAEP,
JweEncryption.A256CBC_HS512,
null);
var cert=new X509Certificate2(“.\\key.cer”);
var rsa=(rsacyptoserviceprovider)cert.PublicKey.Key;
var payload=newdictionary()
{
{“sub”,“mr。x@contoso.com"},
{“exp”,1300819380}
};
var encryptedToken=
编码(
有效载荷,
rsa,
JweAlgorithm.RSA_OAEP,
JweEncryption.A256CBChs512,
无效);
如果要使用证书,可以使用此方法通过其指纹检索证书
private X509Certificate2 GetByThumbprint(string Thumbprint)
{
var localStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
localStore.Open(OpenFlags.ReadOnly);
return localStore.Certificates//.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, false)
.Find(X509FindType.FindByThumbprint, Thumbprint, false)
.OfType<X509Certificate2>().First();
}
这个问题的关键是使用JWT和Bouncy castle库分别对令牌进行编码和签名
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
};
// add headers. 'alg' and 'typ' key-values are added automatically.
var header = new Dictionary<string, object>
{
{ "{header_key}", "{your_private_key_id}" },
};
var token = encoder.Encode(header,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”,“”},
//和其他关键值
};
//添加标题。自动添加“alg”和“typ”键值。
var header=新字典
{
{{header\u key},{your\u private\u key\u id},
};
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私钥------使用和nuget包,下面的代码对我有用
public static string CreateToken(Dictionary<string, object> payload)
{
string jwt = string.Empty;
RsaPrivateCrtKeyParameters keyPair;
var cert = ConfigurationManager.AppSettings["cert"];
/// cert begins -----BEGIN PRIVATE KEY----- and ends with -END PRIVATE KEY-----";
using (var sr = new StringReader(cert))
{
PemReader pr = new PemReader(sr);
keyPair = (RsaPrivateCrtKeyParameters)pr.ReadObject();
}
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters(keyPair);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(rsaParams);
jwt = Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
}
return jwt;
}
公共静态字符串CreateToken(字典负载)
{
string jwt=string.Empty;
RsaPrivateCrtKeyParameters密钥对;
var cert=ConfigurationManager.AppSettings[“cert”];
///证书开始------开始私钥------结束于-结束私钥------”;
使用(var sr=新的StringReader(证书))
{
PemReader pr=新PemReader(sr);
keyPair=(RsaPrivateCrtKeyParameters)pr.ReadObject();
}
RSAParameters rsaParams=DotNetUtilities.ToRSAParameters(密钥对);
使用(rsacryptserviceprovider rsa=new rsacryptserviceprovider())
{
rsa.输入参数(rsaparms);
jwt=Jose.jwt.Encode(有效载荷,rsa,Jose.JwsAlgorithm.RS256);
}
返回jwt;
}
发布代码,使用服务帐户JSON键为GCP OAuth令牌API调用创建RS256 JWT令牌-:
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace GCP
{
class JWTTokenGenerationForGCPOAuthTokenAPI
{
public static string GenerateJWTToken()
{
var rsaParams = ReadAsymmetricKeyParameter();
var encoder = GetRS256JWTEncoder(rsaParams);
var iat = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var exp = DateTimeOffset.UtcNow.AddMinutes(60).ToUnixTimeSeconds();
// create the payload according to your need
// iss is the Service Account Email ID
var payload = new Dictionary<string, object>
{
{ "iss", "<service-account>@<project-id>.iam.gserviceaccount.com"},
{ "scope", "https://www.googleapis.com/auth/cloud-platform" },
{ "aud", "https://oauth2.googleapis.com/token" },
{ "exp", exp},
{ "iat", iat}
};
//Final token
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;
}
public static RSAParameters ReadAsymmetricKeyParameter()
{
\\ This key is fetched from the GCP Service Account JSON File.
\\"private_key": "-----BEGIN PRIVATE KEY-----\n<long-code>-----END PRIVATE KEY-----\n",
\\ pick <long-code> from above. Replace all \n with actual new line like shown below.
string pkey = @"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDSoGKK/Dzb8MBy
################################################################
################################################################
################################################################
################################################################
twySMqKKWnIC/zZljrvp4w==";
RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters1;
var keyBytes = Convert.FromBase64String(pkey);
var asymmetricKeyParameter = PrivateKeyFactory.CreateKey(keyBytes);
rsaPrivateCrtKeyParameters1 = (RsaPrivateCrtKeyParameters)asymmetricKeyParameter;
RSAParameters r = DotNetUtilities.ToRSAParameters(rsaPrivateCrtKeyParameters1);
return r;
}
}
}
使用JWT;
使用JWT.算法;
使用JWT.serializer;
使用Org.BouncyCastle.Crypto.Parameters;
使用Org.BouncyCastle.Security;
使用制度;
使用System.Collections.Generic;
使用System.Security.Cryptography;
名称空间GCP
{
类JWTTokenGenerationForGCPOAuthTokenAPI
{
公共静态字符串GenerateJWTToken()
{
var rsaparms=ReadAsymmetricKeyParameter();
var编码器=GetRS256JWTEncoder(rsaParams);
var iat=DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var exp=DateTimeOffset.UtcNow.AddMinutes(60).ToUnixTimeSeconds();
//根据需要创建有效负载
//iss是Se
private JwtSecurityToken GenerateJWT()
{
var securityKey = new Microsoft.IdentityModel.Tokens.X509SecurityKey(GetByThumbprint("YOUR-CERT-THUMBPRINT-HERE"));
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "RS256");
var JWTHeader = new JwtHeader(credentials);
var payload = new JwtPayload
{
{ "iss", "Issuer-here"},
{ "exp", (Int32)(DateTime.UtcNow.AddHours(1).Subtract(new DateTime(1970, 1, 1))).TotalSeconds},
{ "iat", (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds}
};
var token = new JwtSecurityToken(JWTHeader, payload);
return token;
}
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
};
// add headers. 'alg' and 'typ' key-values are added automatically.
var header = new Dictionary<string, object>
{
{ "{header_key}", "{your_private_key_id}" },
};
var token = encoder.Encode(header,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);
}
}
}
public static string CreateToken(Dictionary<string, object> payload)
{
string jwt = string.Empty;
RsaPrivateCrtKeyParameters keyPair;
var cert = ConfigurationManager.AppSettings["cert"];
/// cert begins -----BEGIN PRIVATE KEY----- and ends with -END PRIVATE KEY-----";
using (var sr = new StringReader(cert))
{
PemReader pr = new PemReader(sr);
keyPair = (RsaPrivateCrtKeyParameters)pr.ReadObject();
}
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters(keyPair);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(rsaParams);
jwt = Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
}
return jwt;
}
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace GCP
{
class JWTTokenGenerationForGCPOAuthTokenAPI
{
public static string GenerateJWTToken()
{
var rsaParams = ReadAsymmetricKeyParameter();
var encoder = GetRS256JWTEncoder(rsaParams);
var iat = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var exp = DateTimeOffset.UtcNow.AddMinutes(60).ToUnixTimeSeconds();
// create the payload according to your need
// iss is the Service Account Email ID
var payload = new Dictionary<string, object>
{
{ "iss", "<service-account>@<project-id>.iam.gserviceaccount.com"},
{ "scope", "https://www.googleapis.com/auth/cloud-platform" },
{ "aud", "https://oauth2.googleapis.com/token" },
{ "exp", exp},
{ "iat", iat}
};
//Final token
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;
}
public static RSAParameters ReadAsymmetricKeyParameter()
{
\\ This key is fetched from the GCP Service Account JSON File.
\\"private_key": "-----BEGIN PRIVATE KEY-----\n<long-code>-----END PRIVATE KEY-----\n",
\\ pick <long-code> from above. Replace all \n with actual new line like shown below.
string pkey = @"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDSoGKK/Dzb8MBy
################################################################
################################################################
################################################################
################################################################
twySMqKKWnIC/zZljrvp4w==";
RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters1;
var keyBytes = Convert.FromBase64String(pkey);
var asymmetricKeyParameter = PrivateKeyFactory.CreateKey(keyBytes);
rsaPrivateCrtKeyParameters1 = (RsaPrivateCrtKeyParameters)asymmetricKeyParameter;
RSAParameters r = DotNetUtilities.ToRSAParameters(rsaPrivateCrtKeyParameters1);
return r;
}
}
}