我试图利用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加密?
答案 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();
}
}
}