c#JWT将ES256 PEM文件加载到CngKey(jose-jwt) [英] c# JWT load ES256 PEM file into CngKey (jose-jwt)

查看:226
本文介绍了c#JWT将ES256 PEM文件加载到CngKey(jose-jwt)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As a quick overview I am attempting to generate a ES256 algorithm -JWT token via C# using the https://github.com/dvsekhvalnov/jose-jwt library.

根据路线说明:

ES256,ES384,ES256 ECDSA签名需要CngKey(通常是私有的) 相应长度的椭圆曲线键.通常存在的CngKey 通过Key Storage Provider中的CngKey.Open(..)方法加载.但是如果 您想使用原始密钥材料(x,y)和d,jose-jwt提供 方便的帮手EccKey.New(x,y,d).

ES256, ES384, ES256 ECDSA signatures requires CngKey (usually private) elliptic curve key of corresponding length. Normally existing CngKey loaded via CngKey.Open(..) method from Key Storage Provider. But if you want to use raw key material (x,y) and d, jose-jwt provides convenient helper EccKey.New(x,y,d).

CngKey.Open()声明它会打开一个现有的键,但是从声音上来说,我应该使用CngKey.Import()代替?当我尝试调用CngKey.Import()时,它将返回以下错误:

The CngKey.Open() states it opens an existing key, but by the sounds of it I should be using the CngKey.Import() instead? When I attempt to call the CngKey.Import() it returns the following error:

参数不正确.

The parameter is incorrect.

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

Basically what I am asking is what is the simplest way to convert an existing PEM file into the CngKey object which is required for the Jose.JWT.Encode() function? Any help would be highly appreciated. Thanks!

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

Below is my code(for security purposed that is not the real private key):

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 为目标.请按照以下步骤操作:

I had the same problem with jose-jwt and got it working using my own implementation of GetECDsaPrivateKey(). Note that your project should target .NET 4.6.1. Please follow the steps below:

1.使用 openssl

> 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 :

2.Generate a JWT by reading private key from above generated certificate:

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

这篇关于c#JWT将ES256 PEM文件加载到CngKey(jose-jwt)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆