【问题标题】:Using jwt with AES256 signing credentials将 jwt 与 AES256 签名凭据一起使用
【发布时间】:2017-06-27 21:58:45
【问题描述】:

我正在尝试利用 Microsoft 的身份模型令牌通过多个网站对登录用户进行身份验证。我使用 HmacSha256 算法进行了这项工作,但我的公司要求我使用 AES256。我将在下面显示代码,但我的问题是有人知道如何使用 AES256 签名算法创建令牌吗? 什么有效:

var plainTextSecurityKey = "My very large security key to encrypt and pass in a token";


var signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.Default.GetBytes(plainTextSecurityKey));
 var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(signingKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256);

 var header = new JwtHeader(signingCredentials);

 var claimsIdentity = new ClaimsIdentity(new List<Claim>()
 {
    new Claim(ClaimTypes.Name,<passedinlanid>),
    new Claim(ClaimTypes.Role,<passedinrole>),
 }, "Custom");

var securityTokenDescriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor()
{
    Audience = "https://myurl.com",
    Issuer = "http://my.tokenissuer.com",
    Subject = claimsIdentity,
    SigningCredentials = signingCredentials,
};

var tokenHandler = new JwtSecurityTokenHandler();
var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);

我需要使用的是线

 var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(signingKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.Aes256Encryption);

但我在线 var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);

现在我明白错误的意思了,只是不知道有没有办法使用 JWT 使用 AES256 加密?

【问题讨论】:

  • 我相信这个错误意味着您请求的算法在您使用的库和平台中不受支持。您能否详细说明您正在使用什么平台和库?
  • .NET 4.5.2,C#,并且我同时使用 System.IdentityModel.Tokens.Jwt; Microsoft.IdentityModel.Tokens;
  • 我想我为任何可能需要答案的人找到了一种解决方法。我所做的是通过 HmacSha256 算法创建令牌,然后使用 AES256 算法加密该令牌。然后将其存储在 httpOnly cookie 中。在接收端,我读取 cookie 值,解密 AES256 字符串,然后像往常一样验证令牌。我知道这可能是加密过度,但我的公司要求我使用 AES256。我会在答案中发布我的代码。

标签: aes token jwt


【解决方案1】:

这是最终代码。

public string GetJwtToken(String lanID,string Role)
        {


            var plainText = lanID + "-" + ConfigurationManager.AppSettings["TokenText"].ToString();
            var plainTextSecurityKey = lanID + "-" + ConfigurationManager.AppSettings["TokenKey"].ToString();
            var signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.Default.GetBytes(plainText));
            var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(signingKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256);

            var header = new JwtHeader(signingCredentials);

            var claimsIdentity = new ClaimsIdentity(new List<Claim>()
             {
                 new Claim(ClaimTypes.Name, lanID),
                 new Claim(ClaimTypes.Role,Role),
             }, "Custom");

            var securityTokenDescriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor()
            {
                Audience = "https://myvalidaud.com",
                Issuer = "http://my.tokenissuer.com",
                Subject = claimsIdentity,
                SigningCredentials = signingCredentials,
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);

            //we encrypt the token with AES256
            var signedAndEncodedToken = Encrypt(tokenHandler.WriteToken(plainToken), plainTextSecurityKey);

            //after this is returned its assigned to a cookie
            return signedAndEncodedToken;
        }



        public static Boolean ValidateJwt(string jwt,string lanId)
        {

            var handler = new JwtSecurityTokenHandler();
            var plainText = lanId + "-" + ConfigurationManager.AppSettings["TokenText"].ToString();
            var plainTextSecurityKey = lanId + "-" + ConfigurationManager.AppSettings["TokenKey"].ToString();

            //decrypt jwt from AES first
            jwt = Decrypt(jwt, plainTextSecurityKey);

            var signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.Default.GetBytes(plainText));

            var validationParameters = new TokenValidationParameters()
            {
                ValidAudiences = new string[]
                {
                    "https://myvalidaud.com"

                },
                ValidIssuers = new string[]
                {
                    "http://my.tokenissuer.com",
                    "http://my.othertokenissuer.com"
                },
                IssuerSigningKey = signingKey
            };

            try
            {
                Microsoft.IdentityModel.Tokens.SecurityToken validatedToken;
                handler.ValidateToken(jwt, validationParameters, out validatedToken);
                return true;
            }
            catch (Exception e)
            {
                return false;

            }


        }

        //AES has fixed BLOCK size of 128 bits, and a variable KEY size of 128, 192, or 256 bits. The key size is what discerns AES-128 from AES-256, block size is always 128
        //Salt size of 32 bytes makes a 256 bits
        public static string Encrypt(string plainText, string key)
        {
            if (string.IsNullOrEmpty(plainText))
                throw new ArgumentNullException("plainText");
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");

            // Derive a new Salt and IV from the Key
            using (var keyDerivationFunction = new Rfc2898DeriveBytes(key, _saltSize))
            {
                var saltBytes = keyDerivationFunction.Salt;
                var keyBytes = keyDerivationFunction.GetBytes(32);
                var ivBytes = keyDerivationFunction.GetBytes(16);

                // Create an encryptor to perform the stream transform.
                // Create the streams used for encryption.
                using (var aesManaged = new AesManaged())
                using (var encryptor = aesManaged.CreateEncryptor(keyBytes, ivBytes))
                using (var memoryStream = new MemoryStream())
                {
                    using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                    using (var streamWriter = new StreamWriter(cryptoStream))
                    {
                        // Send the data through the StreamWriter, through the CryptoStream, to the underlying MemoryStream
                        streamWriter.Write(plainText);
                    }

                    // Return the encrypted bytes from the memory stream, in Base64 form so we can send it right to a database (if we want).
                    var cipherTextBytes = memoryStream.ToArray();
                    Array.Resize(ref saltBytes, saltBytes.Length + cipherTextBytes.Length);
                    Array.Copy(cipherTextBytes, 0, saltBytes, _saltSize, cipherTextBytes.Length);

                    return Convert.ToBase64String(saltBytes);
                }
            }
        }


        public static string Decrypt(string ciphertext, string key)
        {
            if (string.IsNullOrEmpty(ciphertext))
                throw new ArgumentNullException("cipherText");
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");

            // Extract the salt from our ciphertext
            var allTheBytes = Convert.FromBase64String(ciphertext);
            var saltBytes = allTheBytes.Take(_saltSize).ToArray();
            var ciphertextBytes = allTheBytes.Skip(_saltSize).Take(allTheBytes.Length - _saltSize).ToArray();

            using (var keyDerivationFunction = new Rfc2898DeriveBytes(key, saltBytes))
            {
                // Derive the previous IV from the Key and Salt
                var keyBytes = keyDerivationFunction.GetBytes(32);
                var ivBytes = keyDerivationFunction.GetBytes(16);

                // Create a decrytor to perform the stream transform.
                // Create the streams used for decryption.
                // The default Cipher Mode is CBC and the Padding is PKCS7 which are both good
                using (var aesManaged = new AesManaged())
                using (var decryptor = aesManaged.CreateDecryptor(keyBytes, ivBytes))
                using (var memoryStream = new MemoryStream(ciphertextBytes))
                using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                using (var streamReader = new StreamReader(cryptoStream))
                {
                    // Return the decrypted bytes from the decrypting stream.
                    return streamReader.ReadToEnd();
                }
            }
        }

【讨论】:

    猜你喜欢
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    • 2015-07-18
    • 2020-04-30
    • 2017-01-25
    • 2018-06-17
    相关资源
    最近更新 更多