繁体   English   中英

c#JWT将ES256 PEM文件加载到CngKey(jose-jwt)

[英]c# JWT load ES256 PEM file into CngKey (jose-jwt)

作为快速概述,我试图使用https://github.com/dvsekhvalnov/jose-jwt库通过C#生成ES256算法-JWT令牌。

正如指示所述:

ES256,ES384,ES256 ECDSA签名需要相应长度的CngKey(通常为私有)椭圆曲线键。 通常,现有的CngKey通过密钥存储提供程序的CngKey.Open(..)方法加载。 但是如果你想使用原始密钥材料(x,y)和d,jose-jwt提供了方便的帮助器EccKey.New(x,y,d)。

CngKey.Open()声明它打开一个现有的键,但通过它的声音我应该使用CngKey.Import()而不是? 当我尝试调用CngKey.Import()时,它返回以下错误:

参数不正确。

基本上我要问的是将现有PEM文件转换为Jose.JWT.Encode()函数所需的CngKey对象的最简单方法是什么? 任何帮助将受到高度赞赏。 谢谢!

下面是我的代码(出于安全目的,这不是真正的私钥):

public string GenerateToken(int contactID, Database _db)
        {
            var contact = GetContact(contactID, _db);
            var payload = new Dictionary<string, object>()
            {
                {"broker", 1},
                {"contact_id", contact.id},
                {"name", contact.fname + " " + contact.lname + ""},
                {"iss", "www.somewhere.com"},
                {"iat", (DateTime.Now - UnixEpoch).TotalSeconds},
                {"nbf", (DateTime.Now - UnixEpoch).TotalSeconds},
                {"exp", (DateTime.Now.AddDays(30) - UnixEpoch).TotalSeconds}
            };    

            string privateKey =
            "MHcCAQEffEIIIHHHHHHHHHHHHHHHffHHHHHHHHHHHHHHHHHHHHHHHoGgCCqGSM49" +
            "AwEHhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhI+pRkAxAb13" +
            "77vz2Yjjjjjjjjjjjjjjjjjjjjw==";
            byte[] b = Convert.FromBase64String(privateKey);

            CngKey cng = CngKey.Import(b, CngKeyBlobFormat.EccPrivateBlob);
            string token = Jose.JWT.Encode(payload, cng, JwsAlgorithm.ES256);
            return token;
        }

我和jose-jwt有同样的问题,并使用我自己的GetECDsaPrivateKey()实现工作。 请注意,您的项目应以.NET 4.6.1为目标。 请按照以下步骤操作:

1.使用openssl生成p12 X509Certificate2

> openssl ecparam -name prime256v1 -genkey > private-key.pem
> openssl ec -in private-key.pem -pubout -out public-key.pem
> openssl req -new -key private-key.pem -x509 -nodes -days 365 -out public.cer
> winpty openssl pkcs12 -export -in public.cer -inkey private-key.pem -out publiccert.p12

2.通过从上面生成的证书中读取私钥来生成JWT

var claims = new Dictionary<string, object>()
{
    { "sub", "mr.x@contoso.com" },
    { "exp", 1300819380 }
};

var certificate = new X509Certificate2("publiccert.p12", "passcode");
string token = SignJWTWithCert(certificate, claims);

private static string SignJWTWithCert(X509Certificate2 cert, object claims)
{
        var header = new { alg = "ES256", typ = "JWT" };
        byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
        byte[] claimsBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(claims, Formatting.None));

        using (ECDsa ecdsa = cert.GetECDsaPrivateKey())
        {
            if (ecdsa == null)
                throw new ArgumentException("Cert must have an ECDSA private key", nameof(cert));

            var payload = Base64UrlEncode(headerBytes) + "." + Base64UrlEncode(claimsBytes);
            var signature = ecdsa.SignData(Encoding.UTF8.GetBytes(payload), HashAlgorithmName.SHA256);
            return payload + "." + Base64UrlEncode(signature);
        }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM