在c#中使用json私钥签名报头和有效负载



我必须用json私钥生成一个客户端断言字符串签名。

私钥在私钥中。json文件。如何使用文件中的私钥对标头和有效负载进行签名?

除了签名部分,我已经设法使其他事情工作。以下是我用于获取Signed Client断言字符串

的代码
public string GetSignedClientAssertion()
{
var header = new Dictionary<string, string>()
{
{ "typ" , "JWT"},
{ "alg", "ES512"},
{ "kid", "TST_Staging" }
};

string token = Encode(Encoding.UTF8.GetBytes(JObject.FromObject(header).ToString())) + "." + Encode(Encoding.UTF8.GetBytes(JObject.FromObject(GetClaims()).ToString()));
var rsa = new RSACryptoServiceProvider();
var filename = System.Web.HttpContext.Current.Server.MapPath("Private.json");
string data = File.ReadAllText(filename);
string key = Encode(Encoding.UTF8.GetBytes(data));
byte[] databyte = File.ReadAllBytes(filename);

//-----I am stuck here on how to sign the token with the Private key from the private.key file
//---the method used for SignData does not work
string signature =  SignData(token, data);
signature = Encode(Encoding.UTF8.GetBytes(signature));
return signedClientAssertion = string.Concat(token, ".", signature);

}

私有的。Json有如下内容

{
"kty": "EC",
"d": "AfJ_hlRFCP0g2PghjghjghjtryrtytyFpbALpoG0gqh9tyaSv8JIZuhKYOgvbAzkI6pi2gdCce3fvWb5csiL24PiS9Ke5CKlh3QyW-YOO",
"use": "sig",
"crv": "P-521",
"kid": "TST_Staging",
"x": "ADRSCG8Acsqj6SlShpEJYa9UhA7ojghjgjK4eUVHj9CDqbH4j2_F84j7qtK4fdH94xGzYqQwV0rLfJrAISknoudPQm743H",
"y": "AYnLkWp3Up69WQoc-kZ8ugvSiCNChMiBra3jLHmSotDdzSJ6MgMCokfRdHsfsF-z4VAGq3zam1Z604_rC5N9xrtyrtyufV",
"alg": "ES512"
}

谁能指出如何用私钥签署令牌将会很有帮助。谢谢。

我自己设法找到了解决方案。我使用EC Json公钥和私钥。以前我使用的是ES512算法,在解密来自服务器的JWE响应时存在一些问题,因此我将JWT密钥算法更改为ES256,并且使用此加密和解密与josej .JWT完美配合。

我已经挣扎了一个多月寻找EC Json公钥和私钥加密和解密的解决方案。所有可用的解决方案都只针对PEM密钥方法,而对Json EC密钥没有太多的帮助。我花了很多时间找到必要的部分,把它们组合在一起,让它工作。我提供了加密和解密发生的页面的完整代码,以便有人可能会发现它很有用。

using System.Net;
using System.Text;  // For class Encoding
using System.IO;    // For StreamReader
using System;
using System.Collections.Generic;
using System.Configuration;
using Jose;
using System.Security.Cryptography;
using System.Web;
using Jose.keys;
using Stream = System.IO.Stream;
using System.Web.Script.Serialization;
using Newtonsoft.Json;
public partial class holding : System.Web.UI.Page
{
string ClientID = "mlDBKnXXXXXTYRTYRTYyYdmzFGD6HcBPsHZ2W";
string RemoteURL = "https://www.example.org";
string RemoteTokenAppend = "/token";
string RedirectURL = "https://www.exampleabc.com/holding.aspx";
//-----private key for Encrypting the token
string PrivateKey = @" 
{
""x"": ""4kELRTR545GDGDGtvilOLrtr5luaQaWgaTlpqUf7o"",
""y"": ""iCyNdwX73FWKJTjn1Q19gdjEILKjEILK3Y_XwgY3Y_XwgY"",
""d"": ""wiYrwNa5SgBNgdqRtSMpaUvRmipaBJ6hfmL1CUMpwlQ"",
""kty"": ""EC"",
""crv"": ""P-256""
}";
Dictionary<string, object> PrivateKeyHeader = new Dictionary<string, object>
{
{ "typ", "JWT" },
{ "kid", "TST_SERVER" },
{ "alg", "ES256" }
};
//----Public Enc key for Decrypting the JWE token from the remote host
string PublicKey_Enc = @" 
{
""x"": ""_ylhMfdVwaRrLx8HL8z7X1ixVkk2rbpwD9oU-uAqyhE"",
""y"": ""aCRo4kY2dTl7wZXjsp2NJyF9Tcmzk1XZN5ueJWNq7Lk"",
""d"": ""Jz9aEpbt_4aKL5FVdCLlux7U-Ubt_4aKL5VdCLLTR2Y"",
""kty"": ""EC"",
""crv"": ""P-256""
}";
public void Page_Load(object sender, EventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(RemoteURL + RemoteTokenAppend);
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
request.ProtocolVersion = HttpVersion.Version10;
var postData = "client_assertion_type=" + HttpUtility.UrlEncode("urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
postData += "&client_id=" + HttpUtility.UrlEncode(ClientID);
postData += "&grant_type=" + HttpUtility.UrlEncode("authorization_code");
postData += "&redirect_uri=" + HttpUtility.UrlEncode(RedirectURL);
postData += "&code=" + HttpUtility.UrlEncode(Request.QueryString["code"]);
postData += "&client_assertion=" + EncryptTokenJose();
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("Content-Encoding", "ISO-8859-1");
request.ContentLength = data.Length;
try
{
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var webResponse = (HttpWebResponse)request.GetResponse();
var webStream = webResponse.GetResponseStream();
var responseReader = new StreamReader(webStream);
var response = responseReader.ReadToEnd();
//---Decrypt the Response from Remote
string JoseRes = DecryptTokenJose(response.ToString());
//---close the response reader
responseReader.Close();
Response.Write("<br><br>Payload = " + JoseRes + "<br><br>");
//---Get the json string and values from the decrypted Token
JsonTextReader reader = new JsonTextReader(new StringReader(JoseRes));
var sData = JsonSerializer.CreateDefault().Deserialize<payload>(reader);
//----Sample Payload
//---- Payload = { "sub":"s=S775566X,u=c57acrtereb8-d102-455a-860a-ae7dretef4b8d","aud":"mlDBKnGyYfgdgdmzwx770mqXKb6HcBPsHZ2W","amr":["pwd","swk"],"iss":"https://www.exampleabc.com","exp":1637810980,"iat":1637810380,"nonce":"TJtv85f586sTgxjUlFm5"}
//----get the sub from Payload
string sub = sData.sub;
Response.Write("<br><br>Sub = " + sub + "<br><br>");
//---Get the list array of sub to extract the IC
string[] subList = sub.Split(',');
//---Get the first item of the array to get the IC
Response.Write("<br><br>NRIC = " + subList[0] + "<br><br>");
//---Retrieved IC value will be s=S775566X, so replace s= to "" to get the exact NRIC value and set the Session value
Session["NRIC"] = subList[0].Replace("s=", "");
//---if Session["RedirctPage"] is set then go to that page
if (Session["RedirctPage"] != null)
Response.Redirect(Session["RedirctPage"].ToString());
else
Response.Redirect("Register_uat.aspx");
}
catch (WebException ex)
{
using (WebResponse response = ex.Response)
{

string ErrorString = "Error from the Server:-----<br><br>";
HttpWebResponse httpResponse = (HttpWebResponse)response;                   
using (Stream data1 = response.GetResponseStream())
using (var reader = new StreamReader(data1))
{
ErrorString += reader.ReadToEnd();
Response.Write(ErrorString);
}

}
}
}
public string EncryptTokenJose()
{
const uint JwtToAadLifetimeInSeconds = 60 * 2; 
DateTime validFrom = DateTime.UtcNow;
long exp = ConvertToTimeT(validFrom + TimeSpan.FromSeconds(JwtToAadLifetimeInSeconds));
long iat = ConvertToTimeT(validFrom);
//---Payload string
string payloadStr = "{"aud":"" + RemoteURL + "","exp":" + exp.ToString() + ","iss":"" + ClientID + "","iat": " + iat.ToString() + ","sub":"" + ClientID + ""}";
//---get the Private key to form the public key
JsonTextReader reader = new JsonTextReader(new StringReader(PrivateKey));
var jwk = JsonSerializer.CreateDefault().Deserialize<JWK>(reader);
var publicECCKey = EccKey.New(Base64Url.Decode(jwk.x), Base64Url.Decode(jwk.y), Base64Url.Decode(jwk.d), usage: CngKeyUsages.KeyAgreement);
string token = Jose.JWT.Encode(payloadStr, publicECCKey, JwsAlgorithm.ES256, extraHeaders: PrivateKeyHeader);
return token;
}
public string DecryptTokenJose(string Res)
{
var jss = new JavaScriptSerializer();
string json = Res;
Dictionary<string, string> sData = jss.Deserialize<Dictionary<string, string>>(json);
string AccessToken = sData["access_token"].ToString();
string TokenType = sData["token_type"].ToString();
string IdToken = sData["id_token"].ToString();
Response.Write("<br><br>" + IdToken + "<br><br>");
//---get the Public key Enc to decrypt the JWE token
JsonTextReader reader = new JsonTextReader(new StringReader(PublicKey_Enc));
var jwk = JsonSerializer.CreateDefault().Deserialize<JWK>(reader);
var publicECCKey = EccKey.New(Base64Url.Decode(jwk.x), Base64Url.Decode(jwk.y), Base64Url.Decode(jwk.d), usage: CngKeyUsages.KeyAgreement);
//---get the decrypted token
string token = Jose.JWT.Decode(IdToken, publicECCKey, JweAlgorithm.ECDH_ES_A128KW, JweEncryption.A256CBC_HS512);
//----todo: Verify the signature of the decoded JWS token
//----5 parts token with dot(.) as separator
string[] toklist = token.Split('.');
//----get the 2nd item of the list which will have the Payload with User IC details
string Payload = toklist[1];
//----decode the payload to bytes and from bytes to readable string
var base64EncodedBytes = Base64Url.Decode(Payload);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
public static long ConvertToTimeT(DateTime dt)
{
return (long)(dt - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds;
}
public class payload
{
public string sub { get; set; }
public string aud { get; set; }
public string iss { get; set; }
public string exp { get; set; }
public string iat { get; set; }
}
public class JWK
{
public string x { get; set; }
public string y { get; set; }
public string d { get; set; }
}
}

最新更新