zoukankan      html  css  js  c++  java
  • C# 中的 AEAD_AES_256_GCM

    • 注意:AEAD_AES_256_GCM Key的长度必须是32位,nonce的长度必须是12位,附加数据有可能为空值。AEAD_AES_128_GCM Key的长度必须是16位,nonce的长度必须是12位,附加数据有可能为空值。

    使用中AEAD_AES_256_GCM还是AEAD_AES_128_GCM加密,是根据key的长度来决定的。
    size = key.Length * 8
    256 = 32 * 8, AEAD_AES_256_GCM的key长度必须是 32 位。
    128 = 16 * 8, AEAD_AES_128_GCM的key长度必须是 16 位。

    英文好的可以看这个文档rfc5116

    使用官方AesGcm类

    自aspnetcore3.0之后,System.Security.Cryptography支持 AES_GCM,不支持.net framework。在加密时,请使用AesGcmEncryptToBase64_WithTag方法,这个方法的结果包含了tag (authentication tag)。加密结果最后面的16位字符就是tag,但是官方的加密方法没有帮我们拼接上。

    /// <summary>
    /// 使用 AesGcm 解密
    /// </summary>
    /// <param name="key">key32位字符</param>
    /// <param name="nonce">随机串12位</param>
    /// <param name="encryptedData">密文(Base64字符)</param>
    /// <param name="associatedData">(可能null)</param>
    /// <returns></returns>
    static string AesGcmDecryptFromBase64(string key, string nonce, string encryptedData, string associatedData)
    {
        var keyBytes = Encoding.UTF8.GetBytes(key);
        var nonceBytes = Encoding.UTF8.GetBytes(nonce);
        var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData);
        
        var encryptedBytes = Convert.FromBase64String(encryptedData);
        //tag size is 16
        var cipherBytes = encryptedBytes[..^16];
        var tag = encryptedBytes[^16..];
        var decryptedData = new byte[cipherBytes.Length];
        using var cipher = new AesGcm(keyBytes);
        cipher.Decrypt(nonceBytes, cipherBytes, tag, decryptedData, associatedBytes);
        return Encoding.UTF8.GetString(decryptedData);
    }
    
    /// <summary>
    /// 使用 AesGcm AEAD_AES_256_GCM 加密,不要在正式环境中使用这个方法。因为在解密时不知道tag,除非额外返回tag。
    /// </summary>
    /// <param name="key">key32位字符</param>
    /// <param name="nonce">随机串12位</param>
    /// <param name="plainData">明文</param>
    /// <param name="associatedData">附加数据(可能null)</param>
    /// <returns>只返回加密数据不包含authentication tag</returns>
    static string AesGcmEncryptToBase64(string key, string nonce, string plainData, string associatedData)
    {
        var keyBytes = Encoding.UTF8.GetBytes(key);
        var nonceBytes = Encoding.UTF8.GetBytes(nonce);
        var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData);
    
        var plainBytes = Encoding.UTF8.GetBytes(plainData);
        var cipherBytes = new byte[plainBytes.Length];
        using var cipher = new AesGcm(keyBytes);
        //tag size must be is 16 
        var tag = new byte[16];
        cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes);
        
        return Convert.ToBase64String(cipherBytes);
    }
    
    /// <summary>
    /// 使用 AesGcm进行AEAD_AES_256_GCM加密
    /// </summary>
    /// <param name="key">key32位字符</param>
    /// <param name="nonce">随机串12位</param>
    /// <param name="plainData">明文</param>
    /// <param name="associatedData">附加数据(可能null)</param>
    /// <returns>base64(加密后数据 + authentication tag)</returns>
    static string AesGcmEncryptToBase64_WithTag(string key, string nonce, string plainData, string associatedData)
    {
        var keyBytes = Encoding.UTF8.GetBytes(key);
        var nonceBytes = Encoding.UTF8.GetBytes(nonce);
        var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData);
    
        var plainBytes = Encoding.UTF8.GetBytes(plainData);
        var cipherBytes = new byte[plainBytes.Length];
        //tag size is 16
        var tag = new byte[16];
        using var cipher = new AesGcm(keyBytes);
        cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes);
        
        var cipherWithTag = new byte[cipherBytes.Length + tag.Length];
        Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, 0, cipherBytes.Length);
        Buffer.BlockCopy(tag, 0, cipherWithTag, cipherBytes.Length, tag.Length);
        
        return Convert.ToBase64String(cipherWithTag);
    }

    测试代码

    var text = "{'A':123, count:'10', isOk:false, body:{'Text':'select * from table_A where name=@_p1', result:[{'id':1, 'age':23}]}}";
    //KEY 必须是两个32位
    var key = "1234567890_1234567890_1234567890";
    
    var nonce = "77d0a5ff3937";//Guid.NewGuid().ToString("N").Substring(0, 12);
    
    
    var associated = "6df132d42d0b4581"; //Guid.NewGuid().ToString("N").Substring(0, 16);
    
    var pythonResult = "PrTO/594j0CYMi2CQF9IFIp7UNkiTtIiIUbmR+jv1c1iO8Ng/HDFHDjL2t0DYo7xo5Vr0O0fUg9hD3bfCoomP+taVaPrW2kJbPTiFXkohXk3T80lQIdWP5lrl21vJvZO3MbmvshyjU+Oxk7pSnjiE5mw/sPXBs4jzS5wtvLUgHvWGaNxzw==";
    
    Console.WriteLine();
    
    var cipherText = AesGcmEncryptToBase64(key, nonce, text, nonce);
    
    Console.WriteLine($"原始密文Base64  :	{cipherText}");
    
    //Console.WriteLine($"密文tag Base64:		{AesGcmEncryptToBase64(keyBytes,  nonceBytes,  text, associatedBytes)}");
    
    Console.WriteLine($"Python GCM密文  :	{pythonResult}");
    
    var cryptText1 = AesGcmEncryptByBouncyCastle(key, nonce, text, associated);
    Console.WriteLine($"BouncyCastle密文: 	{cryptText1} ");
    
    var cryptText2 = AesGcmEncryptToBase64_WithTag(key, nonce,  text, associated);
    Console.WriteLine($"密文+Tag Base64 : 	{cryptText2} ");
    
    Console.WriteLine();
    Console.WriteLine();
    
    var t30 = AesGcmDecryptByBouncyCastle(key, nonce, pythonResult, associated);
    Console.WriteLine($"BouncyCastle 解密 Python      :{t30} 	isOk:{text == t30}");
    
    var t40 = AesGcmDecryptFromBase64(key, nonce, pythonResult, associated);
    Console.WriteLine($"AesGcm       解密 Python      :{t40} 	isOk:{text == t40}");
    
    Console.WriteLine();
    Console.WriteLine();
    
    var t31 = AesGcmDecryptByBouncyCastle(key, nonce, cryptText1, associated);
    Console.WriteLine($"BouncyCastle 解密 BouncyCastle:{t31} 	isOk:{text == t31}");
    
    var t41 = AesGcmDecryptFromBase64(key, nonce, cryptText1, associated);
    Console.WriteLine($"AesGcm       解密 BouncyCastle:{t41} 	isOk:{text == t41}");
    
    Console.WriteLine();
    Console.WriteLine();
    
    var t32 = AesGcmDecryptByBouncyCastle(key, nonce, cryptText2, associated);
    Console.WriteLine($"BouncyCastle 解密 密文+Tag    :{t32} 	isOk:{text == t32}");
    
    var t42 = AesGcmDecryptFromBase64(key, nonce, cryptText2, associated);
    Console.WriteLine($"AesGcm       解密 密文+Tag    :{t42} 	isOk:{text == t42}");

    转载来源:https://www.cnblogs.com/jzblive/p/14386757.html

  • 相关阅读:
    IDEA热部署插件JRebel使用
    IntelliJ IDEA 代码注释
    解决redis显示中文为乱码问题
    C#的六种修饰符
    Bat批处理把文件夹包括子文件夹下面的某个文件复制到另一个目录下
    html不识别<br/>,后台返回<br/>,前端不换行解决办法
    C# Task的应用
    c# 生成json字符串和解析json字符串处理
    在 C# 中将 List<dynamic> 转换为 List<string>
    C#读取主从文件的excel并把结果为pass的文件打包
  • 原文地址:https://www.cnblogs.com/kangao/p/14942542.html
Copyright © 2011-2022 走看看