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