ASP.NET 核心 5 - 解码 AES-GCM-256 JWE
ASP.NET Core 5 - Decoding an AES-GCM-256 JWE
我正在尝试解码加密令牌但未成功。
我尝试了 c# 的 AesGcm class,但它给我一个关于 TAG 的错误:
The computed authentication tag did not match the input authentication tag.
这是我尝试解码的方式:
string tag = token.Split(".")[4];
byte[] tag_byte = Base64UrlEncoder.DecodeBytes(tag);
new AesGcm(secretKey_byte).Decrypt(iv_byte, ciphertext_byte, tag_byte, decryptedPayload);
然后我切换到 BouncyCastle 并收到此错误:
Invalid value for MAC size: 176
代码:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
string ciphertext = token.Split(".")[3];
byte[] ciphertext_byte = Encoding.UTF8.GetBytes(ciphertext);
string cipherText_Encoded = System.Convert.ToBase64String(ciphertext_byte);
string secretKey_hash = Utils.ComputeSha256Hash(secretKey);
string iv = token.Split(".")[2];
byte[] iv_byte = Encoding.UTF8.GetBytes(iv);
string iv_Encoded = System.Convert.ToBase64String(iv_byte);
string tag = token.Split(".")[4];
byte[] tag_byte = Encoding.UTF8.GetBytes(tag);
string decryptedToken = Utils.DecryptWithGCM(cipherText_Encoded, secretKey_hash, iv_Encoded , tag_byte);
--
public static string ComputeSha256Hash(string rawData)
{
// Create a SHA256
using (SHA256 sha256Hash = SHA256.Create())
{
// ComputeHash - returns byte array
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
// Convert byte array to a string
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
builder.Append(bytes[i].ToString("x2"));
}
return builder.ToString();
}
}
public static string DecryptWithGCM(string EncryptedString, string KeyString, string NonceString, byte[] tag)
{
byte[] key = Convert.FromBase64String(KeyString);
byte[] nonce = Convert.FromBase64String(NonceString);
byte[] ciphertext = Convert.FromBase64String(EncryptedString);
var plaintextBytes = new byte[ciphertext.Length];
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), tag.Length * 8, nonce);
cipher.Init(false, parameters);
var bcCiphertext = ciphertext.Concat(tag).ToArray();
var offset = cipher.ProcessBytes(bcCiphertext, 0, bcCiphertext.Length, plaintextBytes, 0);
cipher.DoFinal(plaintextBytes, offset);
return Encoding.UTF8.GetString(plaintextBytes);
}
这是我的令牌和密钥
密钥:(散列前)
04ee52c7e54ba6452efe6769836b4aa510c6010804fd5668515b305e9b929808
令牌:
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiY3R5IjoiSldUIn0..q3vM69iWaVqnwAcs.bt64YI5c0ndwJrWuK5teMiL0gVu8ZpfPAeXNZNKsad_Hu0Hkx6oy8nu3SRZxbUhaOsQ-nPUCyaoR3tyqsPTRJm4yskk61h3iY2kmhftqWE27poCgkJurifZOUNccX1EtXOx-Qd9SbAmUbJYCWRx98tG4VYb_oztSCy5lusYmbt-M32_UYpMvFMTH8pT4Ux7JittzKC3HOtxiJlbUCGO0Zz9U6KPtIG_CWs0hjweafmigo30xD99YEEpaljULMFfFGCylrfCGeyjyR1RFjmNXGdJsO0kohraJ-DHY9K_JMNi0trlvksJAZghifi-zdHSZgurF06bi6AMJjMqw2t6V2RHn_pUz8wLVoOlvHKtHOfziyg_tsM_GVOaEz-nmu29-bboRewlP7Ihvv1YgG0cOnhpqyd3s_WI7J3CJTtnEYdRQp1F2S8z5pNwrArVy-FxmvGVY-xgdenisG0tRbg3EmGF6kdhFOlSjaVSiYA_ZnQBVftIvz7pvL5kptTxTjgEBgnfAZtM89MNpCFIZ4yTKGtwnmyY9tIfpqmgCPP9erHYWgg1Sn14VibRZO86G_c5LR6n9ZW92qB4KD3SlbJ9IaA27bipwDsYFBllhBIrlhaxTmlifQz4UuaJ_5oRCfDn9faDDv3MaFYyvquAMMhrau8yio_hEgggzUqbzykYrNd6U6rwhHcOfNdardkIc7u9HrPH7AiYsZpVMZ6H5yctvykbVwpMiDgjSpG-_ox776uNdsWIQCp9z5JFawr4nxXsibcrYRJDvwKNwQkYj3Vox-e3mBsjz9jxIc-Yon4BlzTi8U__mhUg.1YVfxEJlvIKdVQVKtHu5ew
好的,我已经放弃 built-in 解密器和 BouncyCastle,并选择尝试 Jose-jwt nuget 包。
https://github.com/dvsekhvalnov/jose-jwt
而且有效!
byte[] secretKey_byte = Utils.ComputeSha256Hash(secretKey);
JweToken decryptedToken = JWE.Decrypt(token, secretKey_byte);
就这么简单。
解密后的 JWT 将在 decryptedToken.Plaintext
下
我正在尝试解码加密令牌但未成功。
我尝试了 c# 的 AesGcm class,但它给我一个关于 TAG 的错误:
The computed authentication tag did not match the input authentication tag.
这是我尝试解码的方式:
string tag = token.Split(".")[4];
byte[] tag_byte = Base64UrlEncoder.DecodeBytes(tag);
new AesGcm(secretKey_byte).Decrypt(iv_byte, ciphertext_byte, tag_byte, decryptedPayload);
然后我切换到 BouncyCastle 并收到此错误:
Invalid value for MAC size: 176
代码:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
string ciphertext = token.Split(".")[3];
byte[] ciphertext_byte = Encoding.UTF8.GetBytes(ciphertext);
string cipherText_Encoded = System.Convert.ToBase64String(ciphertext_byte);
string secretKey_hash = Utils.ComputeSha256Hash(secretKey);
string iv = token.Split(".")[2];
byte[] iv_byte = Encoding.UTF8.GetBytes(iv);
string iv_Encoded = System.Convert.ToBase64String(iv_byte);
string tag = token.Split(".")[4];
byte[] tag_byte = Encoding.UTF8.GetBytes(tag);
string decryptedToken = Utils.DecryptWithGCM(cipherText_Encoded, secretKey_hash, iv_Encoded , tag_byte);
--
public static string ComputeSha256Hash(string rawData)
{
// Create a SHA256
using (SHA256 sha256Hash = SHA256.Create())
{
// ComputeHash - returns byte array
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
// Convert byte array to a string
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
builder.Append(bytes[i].ToString("x2"));
}
return builder.ToString();
}
}
public static string DecryptWithGCM(string EncryptedString, string KeyString, string NonceString, byte[] tag)
{
byte[] key = Convert.FromBase64String(KeyString);
byte[] nonce = Convert.FromBase64String(NonceString);
byte[] ciphertext = Convert.FromBase64String(EncryptedString);
var plaintextBytes = new byte[ciphertext.Length];
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), tag.Length * 8, nonce);
cipher.Init(false, parameters);
var bcCiphertext = ciphertext.Concat(tag).ToArray();
var offset = cipher.ProcessBytes(bcCiphertext, 0, bcCiphertext.Length, plaintextBytes, 0);
cipher.DoFinal(plaintextBytes, offset);
return Encoding.UTF8.GetString(plaintextBytes);
}
这是我的令牌和密钥
密钥:(散列前)
04ee52c7e54ba6452efe6769836b4aa510c6010804fd5668515b305e9b929808
令牌:
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiY3R5IjoiSldUIn0..q3vM69iWaVqnwAcs.bt64YI5c0ndwJrWuK5teMiL0gVu8ZpfPAeXNZNKsad_Hu0Hkx6oy8nu3SRZxbUhaOsQ-nPUCyaoR3tyqsPTRJm4yskk61h3iY2kmhftqWE27poCgkJurifZOUNccX1EtXOx-Qd9SbAmUbJYCWRx98tG4VYb_oztSCy5lusYmbt-M32_UYpMvFMTH8pT4Ux7JittzKC3HOtxiJlbUCGO0Zz9U6KPtIG_CWs0hjweafmigo30xD99YEEpaljULMFfFGCylrfCGeyjyR1RFjmNXGdJsO0kohraJ-DHY9K_JMNi0trlvksJAZghifi-zdHSZgurF06bi6AMJjMqw2t6V2RHn_pUz8wLVoOlvHKtHOfziyg_tsM_GVOaEz-nmu29-bboRewlP7Ihvv1YgG0cOnhpqyd3s_WI7J3CJTtnEYdRQp1F2S8z5pNwrArVy-FxmvGVY-xgdenisG0tRbg3EmGF6kdhFOlSjaVSiYA_ZnQBVftIvz7pvL5kptTxTjgEBgnfAZtM89MNpCFIZ4yTKGtwnmyY9tIfpqmgCPP9erHYWgg1Sn14VibRZO86G_c5LR6n9ZW92qB4KD3SlbJ9IaA27bipwDsYFBllhBIrlhaxTmlifQz4UuaJ_5oRCfDn9faDDv3MaFYyvquAMMhrau8yio_hEgggzUqbzykYrNd6U6rwhHcOfNdardkIc7u9HrPH7AiYsZpVMZ6H5yctvykbVwpMiDgjSpG-_ox776uNdsWIQCp9z5JFawr4nxXsibcrYRJDvwKNwQkYj3Vox-e3mBsjz9jxIc-Yon4BlzTi8U__mhUg.1YVfxEJlvIKdVQVKtHu5ew
好的,我已经放弃 built-in 解密器和 BouncyCastle,并选择尝试 Jose-jwt nuget 包。 https://github.com/dvsekhvalnov/jose-jwt
而且有效!
byte[] secretKey_byte = Utils.ComputeSha256Hash(secretKey);
JweToken decryptedToken = JWE.Decrypt(token, secretKey_byte);
就这么简单。 解密后的 JWT 将在 decryptedToken.Plaintext
下