C語言單片和C#語言服務器端DES及3DES加密的實現


公司最近在做單片機和C#語言的通信。用的是Socket通信。傳輸的數據是明文,后來 在會上討論准備用DES加密(對稱加密)來做。

雙方約定 相應的“密鑰”。

以前做的加密一般都是用C#加密和C#解密。一直以為是個簡單的問題,現在和用C寫的單片機通信的時候卻出了問題。

問題是什么呢?

我找了幾個在線加密 解密的網站,還下了幾個加密解密的工具。結果相同的數據,用相同的密鑰卻得到不同的結果。

而且現在網上C語言實現的DES資料基本上是不靠譜,好多是錯誤的,都是你抄我,我抄你,抄來抄去,抄到最后沒有一個完整實現DES幾種模式加密的。

沒辦法,趕緊去找DES的原理來看,好研究了一番現在終於解決完成。保證了自己寫的代碼和幾種工具一樣的結果。現在將代碼奉上,希望能幫上大家的忙。

一,ECB模式
ECB(Electronic Code book電碼本)模式,相對簡單,將數據按照每8字節一段進行DES加解密的(一次加解密操作必須是8字節,這是算法決定的),如果最后一段不足8字節, 則按照需要補0x00或者0xFF進行計算.之后按照數據順序將所有的數據連接在一起。

這個模式說了這么多,我也不明白啥意思,不過 現在網上流傳的C語言實現的DES加密算法基本上都是這種模式。

采用這個模式以后 ,設置不設置 加密向量都沒有用的。

請注意,我在這里實現的都是 采用這種模式,所以 文中出現的加密向量有關的語句,你都可以把它給無視掉,你刪除掉它,也會得到相同的結果。
二,CBC模式
CBC(Cipher-block chaining密文分組鏈接)模式,該模式使得各段數據存在一些聯系,實現原理比較復雜,我也沒有搞懂,不過以前寫C#代碼的時候,有個加密向量,就像下面代碼這樣子的Byte數組

 

  private static byte[] IV = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };

 

 

 

我一直不明白它有什么用,現在我終於明白了,C#默認的就是這種模式。

現在奉上C#的實現代碼:

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "abcdefgh";
            string str1 = "1234567887654321";

            string str2 = DES3Encrypt(str, str1);
            Console.WriteLine(str2);

            Console.WriteLine(DES3Decrypt(str2, str1));
        }


        #region DES加解密

        private static byte[] IV = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };///這段代碼可以刪除掉
        //默認密鑰向量
        //private static byte[] IV = { 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01 };
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="input">待加密的字符串</param>
        /// <param name="key">加密密鑰</param>
        /// <returns></returns>
        public static string Encrypt(string pToEncrypt, string sKey)
        {
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
            provider.Mode = CipherMode.CBC;
            //provider.Padding = PaddingMode.None;
            byte[] bytes = Encoding.Default.GetBytes(pToEncrypt);
            provider.Key = Encoding.ASCII.GetBytes(sKey);
            provider.IV = Encoding.ASCII.GetBytes(sKey);

            /* 創建一個內存流對象 */
            MemoryStream stream = new MemoryStream();

            /* 創建一個加密流對象 */
            CryptoStream stream2 = new CryptoStream(stream, provider.CreateEncryptor(), CryptoStreamMode.Write);

            /* 將要加密的文本寫到加密流中 */
            stream2.Write(bytes, 0, bytes.Length);

            /* 更新緩沖 */
            stream2.FlushFinalBlock();

            /* 獲取加密過的文本 */
            StringBuilder builder = new StringBuilder();
            foreach (byte num in stream.ToArray())
            {
                builder.AppendFormat("{0:X2}", num);
            }
            stream2.Close();
            stream.Close();
            return builder.ToString();

            //return Convert.ToBase64String(stream.ToArray());

            //byte[] bytes4 = stream.ToArray();
            //string str=Encoding.Default.GetString(bytes4);
            //return str;
        }
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="input">待解密的字符串</param>
        /// <param name="key">解密密鑰,要求為8位,和加密密鑰相同</param>
        /// <returns>解密成功返回解密后的字符串,失敗返源串</returns>
        public static string Decrypt(string DecryptString, string Key)
        {
            try
            {
                //byte[] inputByteArray = Convert.FromBase64String(DecryptString);


                /** 
                 **將一個字符串轉16進制字節數組而已
                 **/
                byte[] inputByteArray = new byte[DecryptString.Length / 2];
                for (int x = 0; x < DecryptString.Length / 2; x++)
                {
                    int i = (Convert.ToInt32(DecryptString.Substring(x * 2, 2), 16));
                    inputByteArray[x] = (byte)i;
                }
                //byte[] inputByteArray = Encoding.UTF8.GetBytes(DecryptString);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.Mode = CipherMode.CBC;
                des.Padding = PaddingMode.None;

                des.Key = Encoding.ASCII.GetBytes(Key);
                des.IV = Encoding.ASCII.GetBytes(Key);


                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, des.CreateDecryptor(), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();

                mStream.Close();
                cStream.Close();
                return Encoding.Default.GetString(mStream.ToArray());
            }
            catch
            {
                return "";
            }
        }
        #endregion

        #region 3DES 加密解密

        public static string DES3Encrypt(string data, string key)
        {
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

            //DES.GenerateKey();
            //byte[] cKey = DES.Key;

            DES.Key = ASCIIEncoding.ASCII.GetBytes(key);
            DES.Mode = CipherMode.ECB;
            DES.Padding = PaddingMode.None;

            ICryptoTransform DESEncrypt = DES.CreateEncryptor();

            byte[] Buffer = ASCIIEncoding.ASCII.GetBytes(data);


            byte[] result = DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length);
            StringBuilder builder = new StringBuilder();
            foreach (byte num in result)
            {
                builder.AppendFormat("{0:X2}", num);
            }
            return builder.ToString();
            //return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
        }

        public static string DES3Decrypt(string DecryptString, string key)
        {
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
            //DES.GenerateKey();
            DES.Key = ASCIIEncoding.ASCII.GetBytes(key);
            DES.Mode = CipherMode.ECB;
            DES.Padding = PaddingMode.None;
            ICryptoTransform DESDecrypt = DES.CreateDecryptor();
            string result = "";
            try
            {
                //byte[] Buffer = Convert.FromBase64String(data);
                /*字符串轉16進制字節數組*/
                byte[] inputByteArray = new byte[DecryptString.Length / 2];
                for (int x = 0; x < DecryptString.Length / 2; x++)
                {
                    int i = (Convert.ToInt32(DecryptString.Substring(x * 2, 2), 16));
                    inputByteArray[x] = (byte)i;
                }

                //byte[] Byteresult = DESDecrypt.TransformFinalBlock(inputByteArray, 0, inputByteArray.Length);
                //StringBuilder builder = new StringBuilder();
                //foreach (byte num in Byteresult)
                //{
                //    builder.AppendFormat("{0:X2}", num);
                //}
                //return builder.ToString();
                result = ASCIIEncoding.ASCII.GetString(DESDecrypt.TransformFinalBlock(inputByteArray, 0, inputByteArray.Length));
            }
            catch (Exception e)
            {
            }
            return result;
        }

        #endregion
    }
}

 

然后我們對比一下效果:

這是一個工具加密后的效果,使用的是DES。

要加密的字符串是:abcdefg

加密的密鑰為:12345678

這是C#的加密 解密效果圖:

 

OK一樣的效果。

 

然后再把單片機那那邊的實現效果給展示一下:

當然C語言版本的是我下載別人的代碼,鏈接在這里

http://files.cnblogs.com/erwin/yxyDES2_C_Edition.rar

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM