无法使用 .NET 验证 JSON Web 令牌 - 密钥太短 [英] Not able to validate JSON Web Token with .NET – key too short

查看:28
本文介绍了无法使用 .NET 验证 JSON Web 令牌 - 密钥太短的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用 JSONWebToken npm 模块生成了一个 jwt:

I have used JSONWebToken npm module to generate a jwt:

var jwt = require('jsonwebtoken');

var payload = {
    "iss": "https://secure.example.com/",
    "exp": 1410819380,
    "http://example.com/orgnum": "987987987",
    "http://example.com/user": "me@example.com"
};

var token = jwt.sign(payload, 'secret');

console.log(token);

这给了我以下输出:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlY3VyZS5leGFtcGxlLmNvbS8iLCJleHAiOjE0MTA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9vcmdudW0iOiI5ODc5ODc5ODciLCJodHRwOi8vZXhhbXBsZS5jb20vdXNlciI6Im1lQGV4YW1wbGUuY29tIiwiaWF0IjoxNDA4Mzk0Mjk2fQ.5X5LTg4wxDF2p49xtsRcG4S9Yk4qSfW1tMEU0AquBhc

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlY3VyZS5leGFtcGxlLmNvbS8iLCJleHAiOjE0MTA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9vcmdudW0iOiI5ODc5ODc5ODciLCJodHRwOi8vZXhhbXBsZS5jb20vdXNlciI6Im1lQGV4YW1wbGUuY29tIiwiaWF0IjoxNDA4Mzk0Mjk2fQ.5X5LTg4wxDF2p49xtsRcG4S9Yk4qSfW1tMEU0AquBhc

由于我没有指定我想要什么算法,所以它使用 SHA256.

Since I'm not specifying what algorithm I want, it uses SHA256.

现在,我尝试在 c# 中验证这一点.这并不容易......

Now, I try to verify this in c#. That didn't turn out easy...

我得到一个关于密钥大小的异常:

I get an exception about the key size:

IDX10603:System.IdentityModel.Tokens.InMemorySymmetricSecurityKey"不能少于:128"位.参数导航:key.KeySize实际大小为 48.

IDX10603: The 'System.IdentityModel.Tokens.InMemorySymmetricSecurityKey' cannot have less than: '128' bits. Parameternavn: key.KeySize The actual size was 48.

我尝试扩展密钥,创建对称密钥时出现新错误:

I I try to extend the key, I get a new error when creating the symmetric key:

Base-64 字符数组或字符串的长度无效

Invalid length for a Base-64 char array or string

我认为这与我告诉 .net 代码有关我的密钥的方式有关.由于 SymmetricKeyIssuerSecurityTokenProvider 构造函数参数被命名为 base64Key,我尝试对我的密钥进行 Base64Url 编码:

I recon this has something to do with the way I'm telling the .net code about my key. Since the SymmetricKeyIssuerSecurityTokenProvider constructor parameter is named base64Key, I have tryed to Base64Url-encode my key:

        var secret =  Base64UrlEncoder.Encode("secret");
        TokenValidationParameters validationParameters = new TokenValidationParameters
        {                
            ValidateIssuer = false,
            ValidateAudience = false,
            IssuerSigningTokens = new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret).SecurityTokens
        };

那么,我在这里缺少什么?
为什么 jsonwebtoken 可以使用短键生成和验证记事本,而 .net 不能?
为什么 .net 不能接受我给它的密钥?

So, what are I missing here?
Why can jsonwebtoken generate and validate jots with short keys while .net can not?
And why can't .net accept the keys I give it?

这是完整的 .net 代码,其中包含一个用长密钥签名的记事本:

Here's the complete .net code with a jot signed with a long key:

        var jwtToken =
            "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlY3VyZS5leGFtcGxlLmNvbS8iLCJleHAiOjE0MTA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9vcmdudW0iOiI5ODc5ODc5ODciLCJodHRwOi8vZXhhbXBsZS5jb20vdXNlciI6Im1lQGV4YW1wbGUuY29tIiwiaWF0IjoxNDA4Mzk1NjY4fQ.ZceiiEO_Mn5_GZp5D_r68VTT33fbocn1BTTznD6u3cs";
        var secret = Base64UrlEncoder.Encode("super duper secret with some more on top");


        TokenValidationParameters validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                ValidateAudience = false,
                IssuerSigningTokens = new SymmetricKeyIssuerSecurityTokenProvider("issuer", secret).SecurityTokens
            };


        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler()
            {
                Configuration = new SecurityTokenHandlerConfiguration()
                    {
                        CertificateValidationMode = X509CertificateValidationMode.None
                    }
            };

        SecurityToken validatedToken;
        var claimsPrincipal = tokenHandler.ValidateToken(jwtToken, validationParameters, out validatedToken);
        return claimsPrincipal.Claims;

更新:

我在这段代码中只使用了微软的东西.我正在使用 OwinMicrosoft.Owin.Security.Jwt 版本 2.1.0System.IdentityModel.Tokens.Jwt 版本 4.0.0-RC2.

I'm only using Microsoft-stuff in this code. I'm using the Owin packages Microsoft.Owin.Security.Jwt version 2.1.0 with System.IdentityModel.Tokens.Jwt version 4.0.0-RC2.

那里有多篇博文指出您需要手动更新 System.IdentityModel.Tokens.Jwt 包.

There are multiple blog posts out there stating that you'll need to manually update the System.IdentityModel.Tokens.Jwt package.

推荐答案

我不确定您使用的是什么 API,因为 official Microsoft one 不包含您正在使用的属性.我的猜测是,您使用的是过时的版本.

I'm not sure what API you are using, since the official Microsoft one does not contain the properties that you are using. My guess would be, you are using an outdated version.

我从这个 Nuget 包中获取了 API.这是对我有用的代码:

I took the API from this Nuget package. And this is the code, that worked for me:

using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.ServiceModel.Security.Tokens;
using System.Text;

namespace SO25372035
{
    class Program
    {
        static void Main()
        {
            const string tokenString =  @"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlY3VyZS5leGFtcGxlLmNvbS8iLCJleHAiOjE0MTA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9vcmdudW0iOiI5ODc5ODc5ODciLCJodHRwOi8vZXhhbXBsZS5jb20vdXNlciI6Im1lQGV4YW1wbGUuY29tIiwiaWF0IjoxNDA4NDE5NTQwfQ.jW9KChUTcgXMDp5CnTiXovtQZsN4X-M-V6_4rzu8Zk8";
            JwtSecurityToken tokenReceived = new JwtSecurityToken(tokenString);

            byte[] keyBytes = Encoding.UTF8.GetBytes("secret");
            if (keyBytes.Length < 64 && tokenReceived.SignatureAlgorithm == "HS256")
            {
                Array.Resize(ref keyBytes, 64);
            }
            TokenValidationParameters validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                AudienceUriMode = AudienceUriMode.Never,
                SigningToken = new BinarySecretSecurityToken(keyBytes),
            };

            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

            ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(tokenReceived, validationParameters);
            IEnumerable<Claim> a = claimsPrincipal.Claims;
            foreach (var claim in a)
            {
                Console.WriteLine(claim);
            }
        }
    }
}

请注意,我必须调整包含密钥的数组的大小,以便密钥长度通过验证.看来 HMAC 的密钥长度始终等于块大小,并且对于 SHA256,它是 512 位.有 MinimumSymmetricKeySizeInBits定义 SimmetricKey 最小长度的静态属性,但它似乎不能设置为小于 128.

Note, that I had to resize the array containing the key so that key length passes the validation. It appears that they key length for HMAC is always equal to the block size, and for SHA256 it's 512 bits. There is MinimumSymmetricKeySizeInBits static property that defines the minimum length of a SimmetricKey, but it appears it can't be set to be less than 128.

这篇关于无法使用 .NET 验证 JSON Web 令牌 - 密钥太短的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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