使用带有AES256签名凭据的jwt

时间:2017-02-09 18:34:13

标签: aes token jwt

我试图利用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);

但是我得到了错误({&#34; IDX10634:无法创建SignatureProvider。\ n算法:&#39; http://www.w3.org/2001/04/xmlenc#aes256-cbc&#39;,SecurityKey:&#39; Microsoft.IdentityModel.Tokens .SymmetricSecurityKey&#39; \ n不受支持。&#34;})在线上 var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);

现在我明白错误意味着什么,只是不知道是否有办法使用JWT使用AES256加密?

1 个答案:

答案 0 :(得分:0)

这是最终的代码。

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