您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页DotnetCore 使用Jwks验证JwtToken签名

DotnetCore 使用Jwks验证JwtToken签名

来源:华佗小知识

[Fact]
public async Task VerfiyJwtTokenUseJwks()
{

    var jwt = @"your jwt token";



    var wellKnownAddress = "http://your-openid-host/.well-known/openid-configuration";
    var httpClientFactory = this.ServiceProvier.GetRequiredService<IHttpClientFactory>();
    var httpClient = httpClientFactory.CreateClient();

    var response = await httpClient.GetAsync(wellKnownAddress);
    response.EnsureSuccessStatusCode();

    var json = await response.Content.ReadAsStringAsync();
    var jObj = (JObject)JsonConvert.DeserializeObject(json);
    var jwks_uri = jObj["jwks_uri"].ToString();
    Console.WriteLine($"Jwks_uri: {jwks_uri}");


    var keySet = await httpClient.GetStringAsync(jwks_uri);
    Console.WriteLine($"keySets: {keySet}");

    var ketSets = (JObject)JsonConvert.DeserializeObject(keySet);
    var keys = (JArray)ketSets["keys"];

    var jwtArray = jwt.Split('.');
    var headerObj = (JObject)JsonConvert.DeserializeObject(DecodeJwtToken(jwtArray[0]));
    Console.WriteLine($"Token Header: {headerObj}");

    var jwtSign = jwtArray[2];

    foreach (var key in keys)
    {
        var kid = headerObj["kid"];
        if (key["kid"].ToString() == kid.ToString())
        {
            var e = key["e"].ToString();
            var n = key["n"].ToString();
            using (var rsa = System.Security.Cryptography.RSA.Create())
            {
                var rsaKeyInfo = new RSAParameters
                {
                    Modulus = DecodeBaseToByteArray(n),
                    Exponent = DecodeBaseToByteArray(e)
                };

                rsa.ImportParameters(rsaKeyInfo);
                var d = $"{jwtArray[0]}.{jwtArray[1]}";

                var success = rsa.VerifyData(
                    Encoding.UTF8.GetBytes(d),
                    DecodeBaseToByteArray(jwtSign), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                Console.WriteLine($"verfiy: {success}");

                var publicKeyPem = ExportPublicKey(rsa);

                Console.WriteLine($"PublicKey PEM: \r\n{publicKeyPem}");

            }

        }

    }
}

private string DecodeJwtToken(string baseToken)
{
    var bytes = DecodeBaseToByteArray(baseToken);
    var json = Encoding.UTF8.GetString(bytes);
    return json;
}

private byte[] DecodeBaseToByteArray(string bString)
{
    var m = (bString.Length % 4);
    if (m > 0)
    {
        if (m == 2)
        {
            bString += "==";
        }
        else
        {
            bString += "=";
        }
    }
    return Convert.FromBaseString(bString.Replace("-", "+").Replace("_", "/"));
}




public static string ExportPublicKey(RSA csp)
{
    StringWriter outputStream = new StringWriter();
    var parameters = csp.ExportParameters(false);
    using (var stream = new MemoryStream())
    {
        var writer = new BinaryWriter(stream);
        writer.Write((byte)0x30); // SEQUENCE
        using (var innerStream = new MemoryStream())
        {
            var innerWriter = new BinaryWriter(innerStream);
            innerWriter.Write((byte)0x30); // SEQUENCE
            EncodeLength(innerWriter, 13);
            innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER
            var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
            EncodeLength(innerWriter, rsaEncryptionOid.Length);
            innerWriter.Write(rsaEncryptionOid);
            innerWriter.Write((byte)0x05); // NULL
            EncodeLength(innerWriter, 0);
            innerWriter.Write((byte)0x03); // BIT STRING
            using (var bitStringStream = new MemoryStream())
            {
                var bitStringWriter = new BinaryWriter(bitStringStream);
                bitStringWriter.Write((byte)0x00); // # of unused bits
                bitStringWriter.Write((byte)0x30); // SEQUENCE
                using (var paramsStream = new MemoryStream())
                {
                    var paramsWriter = new BinaryWriter(paramsStream);
                    EncodeIntegerBigEndian(paramsWriter, parameters.Modulus); // Modulus
                    EncodeIntegerBigEndian(paramsWriter, parameters.Exponent); // Exponent
                    var paramsLength = (int)paramsStream.Length;
                    EncodeLength(bitStringWriter, paramsLength);
                    bitStringWriter.Write(paramsStream.GetBuffer(), 0, paramsLength);
                }
                var bitStringLength = (int)bitStringStream.Length;
                EncodeLength(innerWriter, bitStringLength);
                innerWriter.Write(bitStringStream.GetBuffer(), 0, bitStringLength);
            }
            var length = (int)innerStream.Length;
            EncodeLength(writer, length);
            writer.Write(innerStream.GetBuffer(), 0, length);
        }

        var base = Convert.ToBaseString(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
        // WriteLine terminates with \r\n, we want only \n
        outputStream.Write("-----BEGIN PUBLIC KEY-----\n");
        for (var i = 0; i < base.Length; i += )
        {
            outputStream.Write(base, i, Math.Min(, base.Length - i));
            outputStream.Write("\n");
        }
        outputStream.Write("-----END PUBLIC KEY-----");
    }

    return outputStream.ToString();
}


private static void EncodeLength(BinaryWriter stream, int length)
{
    if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
    if (length < 0x80)
    {
        // Short form
        stream.Write((byte)length);
    }
    else
    {
        // Long form
        var temp = length;
        var bytesRequired = 0;
        while (temp > 0)
        {
            temp >>= 8;
            bytesRequired++;
        }
        stream.Write((byte)(bytesRequired | 0x80));
        for (var i = bytesRequired - 1; i >= 0; i--)
        {
            stream.Write((byte)(length >> (8 * i) & 0xff));
        }
    }
}

private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
    stream.Write((byte)0x02); // INTEGER
    var prefixZeros = 0;
    for (var i = 0; i < value.Length; i++)
    {
        if (value[i] != 0) break;
        prefixZeros++;
    }
    if (value.Length - prefixZeros == 0)
    {
        EncodeLength(stream, 1);
        stream.Write((byte)0);
    }
    else
    {
        if (forceUnsigned && value[prefixZeros] > 0x7f)
        {
            // Add a prefix zero to force unsigned if the MSB is 1
            EncodeLength(stream, value.Length - prefixZeros + 1);
            stream.Write((byte)0);
        }
        else
        {
            EncodeLength(stream, value.Length - prefixZeros);
        }
        for (var i = prefixZeros; i < value.Length; i++)
        {
            stream.Write(value[i]);
        }
    }
}

转载于:https://www.cnblogs.com/byxxw/p/11243772.html

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务