C# 實現 國密SM4/ECB/PKCS7Padding對稱加密解密,爲了演示方便本問使用的是Visual Studio 2022 來構建代碼的
1、新建項目,之後選擇 項目 鼠標右鍵選擇 管理NuGet程序包管理,輸入 BouncyCastle 回車 添加BouncyCastle程序包
2、代碼如下:CBC模式
byte[] plaintext = Encoding.UTF8.GetBytes("1234567890國abcdefghijklmnopqrstuvwxyz"); byte[] keyBytes = Encoding.UTF8.GetBytes("1234567890123456"); byte[] iv = Encoding.UTF8.GetBytes("0123456789ABCDEF"); // SM4/CBC加密 KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes); ParametersWithIV keyParamWithIv = new ParametersWithIV(key, iv); IBufferedCipher inCipher = CipherUtilities.GetCipher("SM4/CBC/PKCS7Padding"); inCipher.Init(true, keyParamWithIv); byte[] cipher = inCipher.DoFinal(plaintext); //Console.WriteLine("加密後的密文(hex): {0}", BitConverter.ToString(cipher, 0).Replace("-", string.Empty)); rtbCard.Text = $"加密後的密文: {Convert.ToBase64String(cipher).Replace("-", string.Empty)}"; // SM4/CBC解密 inCipher.Reset(); inCipher.Init(false, key); byte[] bin = inCipher.DoFinal(cipher); string ans = Encoding.UTF8.GetString(bin); //Console.WriteLine("解密後的密文(hex): {0}", Convert.ToBase64String(cipher).Replace("-", string.Empty)); //Console.WriteLine("解密明文內容: {0}\t是否匹配: {1}", ans, Enumerable.SequenceEqual(plaintext, bin)); rtbCard.Text = rtbCard.Text + "\r\n" + $"解密明文內容: {ans}\t是否匹配: {Enumerable.SequenceEqual(plaintext, bin)}";
代碼如下:ECB模式
byte[] plaintext = Encoding.UTF8.GetBytes("1234567890國abcdefghijklmnopqrstuvwxyz"); byte[] keyBytes = Encoding.UTF8.GetBytes("1234567890123456"); byte[] iv = Encoding.UTF8.GetBytes("0123456789ABCDEF"); // SM4/ECB加密 KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes); //ParametersWithIV keyParamWithIv = new ParametersWithIV(key, iv); ParametersWithIV keyParamWithIv = new ParametersWithIV(key, iv); //IBufferedCipher inCipher = CipherUtilities.GetCipher("SM4/CBC/PKCS7Padding"); IBufferedCipher inCipher = CipherUtilities.GetCipher("SM4/ECB/PKCS7Padding"); //inCipher.Init(true, keyParamWithIv); inCipher.Init(true, key); byte[] cipher = inCipher.DoFinal(plaintext); //Console.WriteLine("加密後的密文(hex): {0}", BitConverter.ToString(cipher, 0).Replace("-", string.Empty)); rtbCard.Text = $"加密後的密文: {Convert.ToBase64String(cipher).Replace("-", string.Empty)}"; // SM4/ECB解密 inCipher.Reset(); //inCipher.Init(false, keyParamWithIv); inCipher.Init(false, key); byte[] bin = inCipher.DoFinal(cipher); string ans = Encoding.UTF8.GetString(bin); Console.WriteLine("解密後的密文(hex): {0}", Convert.ToBase64String(cipher).Replace("-", string.Empty)); Console.WriteLine("解密明文內容: {0}\t是否匹配: {1}", ans, Enumerable.SequenceEqual(plaintext, bin)); rtbCard.Text = rtbCard.Text + "\r\n" + $"解密明文內容: {ans}\t是否匹配: {Enumerable.SequenceEqual(plaintext, bin)}";
3、運行
4、SM4密碼算法是一個分組算法。數據分組長度爲128比特,密鑰長度爲128 比特。加密算法採用32 輪迭代結構,每輪使用一個輪密鑰。我們在實現可用data字節的形式,即祕鑰Data爲16位,加密數據Data需爲16的整數倍,這兩點很重要。
1、ECB模式
觀察第一塊,和第三塊,皆爲明文塊0,相同的輸入產生相同的輸出
2、CBC模式
CBC(密文分組鏈接方式),它的實現機制使加密的各段數據之間有了聯繫。
也是按照data 16位來分組,第一組數據與初始化向量IV異或後的結果進行加密,密得到第一組密文C1(初始化向量I爲全零),第二組數據與第一組的加密結果C1異或以後的結果進行加密,得到第二組密文C2...... 最後C1C2C3......Cn即爲加密結果。此種方法安全性高,但是不利於並行計算,有誤差傳遞,需要初始化向量IV。
參考鏈接: