• C# 加解密之AES


            从这一篇开始呢,写一下常用的一些加解密方式。一般我们来说呢,对于加密,我们分为可逆和不可逆。可逆加密又可分为对称加密(AES、DES等)和非对称加密(RSA),还有就是一些编码加密等(BASE64);不可逆的呢,大部分又都称为摘要算法(MD5、SHA)。

            其实上面扯这些也是白扯,对于一般用户来讲,我从明文能变成看不懂的密文就是加密了,管他叫什么,为什么要写这些,因为我发现很多人喜欢较真,拿MD5来说吧,专业点来讲,他确实是摘要算法而不是加密算法,但很多人就是喜欢称为MD5加密,反正我觉得没啥大问题,因为的确可以理解成一种不可逆的加密,大家既然说顺口了就按顺口的来吧,反正都懂就行。

            这一篇主要来写一下对称加密算法中的AES加密,什么是对称加密?简单理解来说,我只有这一把钥匙,它既可以开锁也可以关锁,其他钥匙肯定不行。

            AES是块加密,稍微介绍一些AES的参数以及约束:

    1. Key(密钥):AES的密钥长度必须为128Bit、192Bit、256Bit(一般又都称为AES128,AES192,AES256),我们一般使用的字母数字等,占位都是1Byte,根据换算公式 1 Byte=8 Bit,所以我们的密钥长度就只能是16、24、32;
    2. IV(向量):“加密”初始块,一般为128Bit,即长度为16,与块的长度一样
    3. Mode(加密模式):可分为CBC(密码块链模式)、ECB(电子密码本模式)、OFB(输出反馈模式)、 CFB(密码反馈模式)、CTS(密码文本窃用模式)、CTR(计数器模式)
    4. Padding(填充模式):NoPadding(不填充)、PKCS7(每个字节填充该字节序列的长度)、Zeros(填充0)、ANSIX923(最后一个字节填充字节序列的长度,其余字节均填充数字零)、ISO10126(最后一个字节填充字节序列的长度,其余字节填充随机数据)、PKCS5(和PKCS7一样)

    理解了上面所描述的那些参数之后(其实不理解有没关系,只是做一下基础了解,我们大部分都只是做应用层,能用就行了);接下来我们使用代码来实现,更直观的感受下。

    实现功能:

    使用AES加密方式加解密文本数据

    开发环境:

    开发工具: Visual Studio 2013

    .NET Framework版本:4.5

    实现代码:

    1. public class AesUtil
    2. {
    3. ///
    4. /// AES加密
    5. ///
    6. ///
    7. ///
    8. public static byte[] Encrypt(AesModel aesModel)
    9. {
    10. //使用32位密钥
    11. byte[] key32 = new byte[32];
    12. //如果我们的密钥不是32为,则自动补全到32位
    13. byte[] byteKey = Encoding.UTF8.GetBytes(aesModel.Key.PadRight(key32.Length));
    14. //复制密钥
    15. Array.Copy(byteKey, key32, key32.Length);
    16. //使用16位向量
    17. byte[] iv16 = new byte[16];
    18. //如果我们的向量不是16为,则自动补全到16位
    19. byte[] byteIv = Encoding.UTF8.GetBytes(aesModel.IV.PadRight(iv16.Length));
    20. //复制向量
    21. Array.Copy(byteIv, iv16, iv16.Length);
    22. // 创建加密对象,Rijndael 算法
    23. //Rijndael RijndaelAes = Rijndael.Create();
    24. RijndaelManaged RijndaelAes = new RijndaelManaged();
    25. RijndaelAes.Mode = aesModel.Mode;
    26. RijndaelAes.Padding = aesModel.Padding;
    27. RijndaelAes.Key = key32;
    28. RijndaelAes.IV = iv16;
    29. byte[] result = null;
    30. try
    31. {
    32. using (MemoryStream ms = new MemoryStream())
    33. {
    34. using (CryptoStream EncryptStream = new CryptoStream(ms, RijndaelAes.CreateEncryptor(), CryptoStreamMode.Write))
    35. {
    36. EncryptStream.Write(aesModel.Data, 0, aesModel.Data.Length);
    37. EncryptStream.FlushFinalBlock();
    38. result = ms.ToArray();
    39. }
    40. }
    41. }
    42. catch { }
    43. return result;
    44. }
    45. ///
    46. /// AES解密
    47. ///
    48. ///
    49. ///
    50. public static byte[] Decrypt(AesModel aesModel)
    51. {
    52. //使用32位密钥
    53. byte[] key32 = new byte[32];
    54. //如果我们的密钥不是32为,则自动补全到32位
    55. byte[] byteKey = Encoding.UTF8.GetBytes(aesModel.Key.PadRight(key32.Length));
    56. //复制密钥
    57. Array.Copy(byteKey, key32, key32.Length);
    58. //使用16位向量
    59. byte[] iv16 = new byte[16];
    60. //如果我们的向量不是16为,则自动补全到16位
    61. byte[] byteIv = Encoding.UTF8.GetBytes(aesModel.IV.PadRight(iv16.Length));
    62. //复制向量
    63. Array.Copy(byteIv, iv16, iv16.Length);
    64. // 创建解密对象,Rijndael 算法
    65. //Rijndael RijndaelAes = Rijndael.Create();
    66. RijndaelManaged RijndaelAes = new RijndaelManaged();
    67. RijndaelAes.Mode = aesModel.Mode;
    68. RijndaelAes.Padding = aesModel.Padding;
    69. RijndaelAes.Key = key32;
    70. RijndaelAes.IV = iv16;
    71. byte[] result = null;
    72. try
    73. {
    74. using (MemoryStream ms = new MemoryStream(aesModel.Data))
    75. {
    76. using (CryptoStream DecryptStream = new CryptoStream(ms, RijndaelAes.CreateDecryptor(), CryptoStreamMode.Read))
    77. {
    78. using (MemoryStream msResult = new MemoryStream())
    79. {
    80. byte[] temp = new byte[1024*1024];
    81. int len = 0;
    82. while ((len = DecryptStream.Read(temp, 0, temp.Length)) > 0)
    83. {
    84. msResult.Write(temp, 0, len);
    85. }
    86. result = msResult.ToArray();
    87. }
    88. }
    89. }
    90. }
    91. catch { }
    92. return result;
    93. }
    94. ///
    95. /// AES加密字符串
    96. ///
    97. ///
    98. ///
    99. ///
    100. ///
    101. public static string Encrypt(string data, string key, string iv="")
    102. {
    103. byte[] bytes = Encoding.UTF8.GetBytes(data);
    104. byte[] result = Encrypt(new AesModel
    105. {
    106. Data = bytes,
    107. Key = key,
    108. IV = iv,
    109. Mode = CipherMode.CBC,
    110. Padding = PaddingMode.PKCS7
    111. });
    112. if (result == null)
    113. {
    114. return "";
    115. }
    116. return Convert.ToBase64String(result);
    117. }
    118. ///
    119. /// AES解密字符串
    120. ///
    121. ///
    122. ///
    123. ///
    124. ///
    125. public static string Decrypt(string data, string key, string iv = "")
    126. {
    127. byte[] bytes = Convert.FromBase64String(data);
    128. byte[] result = Decrypt(new AesModel
    129. {
    130. Data = bytes,
    131. Key = key,
    132. IV = iv,
    133. Mode = CipherMode.CBC,
    134. Padding = PaddingMode.PKCS7
    135. });
    136. if (result == null)
    137. {
    138. return "";
    139. }
    140. return Encoding.UTF8.GetString(result);
    141. }
    142. public class AesModel
    143. {
    144. ///
    145. /// 需要加密/解密的数据
    146. ///
    147. public byte[] Data { get; set; }
    148. ///
    149. /// 密钥
    150. ///
    151. public string Key { get; set; }
    152. ///
    153. /// 向量
    154. ///
    155. public string IV { get; set; }
    156. ///
    157. /// 加密模式
    158. ///
    159. public CipherMode Mode { get; set; }
    160. ///
    161. /// 填充模式
    162. ///
    163. public PaddingMode Padding { get; set; }
    164. }
    165. }
    1. private void btn_Aes_Encrypt_Click(object sender, EventArgs e)
    2. {
    3. string result= AesUtil.Encrypt(textBox1.Text, "12345678900987654321");
    4. textBox2.Text = result;
    5. }
    6. private void btn_Aes_Decrypt_Click(object sender, EventArgs e)
    7. {
    8. string result = AesUtil.Decrypt(textBox2.Text, "12345678900987654321");
    9. textBox1.Text = result;
    10. }

    实现效果:

    由简入繁,拿来即用

    更多精彩,请搜索公 Z 号:Csharp 小记

     

  • 相关阅读:
    setViaGenMode
    软件开发项目保密协议
    G. Good Key, Bad Key(思维)
    向善的力量:顺丰,如何在不确定性中寻求确定性
    如何使用 Yolov4 训练人脸口罩检测模型
    Vue:object变化侦测
    Golang实战:利用Atomic和轮询机制实现任务排队和并发流量控制
    服务类报错记录
    JMeter处理接口签名sign
    spring声明式事务
  • 原文地址:https://blog.csdn.net/qq_27410185/article/details/128011647