昨天做项目的时候,遇到了c++通讯发送加密数据c#解密出错问题。
因为有很多选项,特地做了个对比,研究了其中的一些参数
DES
要注意的项目:
1.密钥 Key、IV
两个密钥都是8字节
2.模式 ECB、CBC
在ECB模式下,只用key;在CBC模式下,同时使用key和IV
3.字节填充模式 非8倍数字节数、8倍数字节数
C# DES { //输入 byte[] INPUT_buffer____ = { 0x31, }; //ECB byte[] ECB_PKCS7_____ = { 0xD6, 0x98, 0x32, 0xA0, 0x62, 0x9A, 0xB7, 0x0F, }; byte[] ECB_Zeros_____ = { 0xB6, 0x61, 0x3E, 0xE6, 0x93, 0x8B, 0x45, 0x71, };// 填充Zero√ byte[] ECB_ANSIX923__ = { 0x7C, 0xB0, 0xEE, 0xE6, 0xD1, 0x3C, 0xC7, 0x88, }; byte[] ECB_ISO10126__ = { 0x0A, 0x22, 0x65, 0xE4, 0x2E, 0xB3, 0xBC, 0x34, }; //CBC byte[] CBC_PKCS7_____ = { 0x3C, 0x77, 0x8E, 0xD4, 0x82, 0xA6, 0x66, 0x36, }; byte[] CBC_Zeros_____ = { 0x40, 0x9D, 0xA7, 0xE5, 0x0D, 0xDF, 0x61, 0x7E, };// 填充Zero√ byte[] CBC_ANSIX923__ = { 0x41, 0x91, 0x0C, 0xCE, 0xC4, 0x41, 0x77, 0xFF, }; byte[] CBC_ISO10126__ = { 0x5C, 0x9C, 0xA9, 0xD6, 0x65, 0x23, 0x5E, 0x39, }; } C# DES { //输入 byte[] INPUT_buffer____ = { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, }; //ECB byte[] ECB_PKCS7_____ = { 0x74, 0xA5, 0x81, 0x53, 0x4A, 0x4B, 0xF8, 0xB1, 0x89, 0xF4, 0xD1, 0xBA, 0x96, 0x97, 0x9A, 0xD0, }; byte[] ECB_Zeros_____ = { 0x74, 0xA5, 0x81, 0x53, 0x4A, 0x4B, 0xF8, 0xB1, };// 填充Zero√ byte[] ECB_ANSIX923__ = { 0x74, 0xA5, 0x81, 0x53, 0x4A, 0x4B, 0xF8, 0xB1, 0x24, 0xC8, 0x74, 0xB9, 0x6D, 0x5C, 0x9E, 0x13, }; byte[] ECB_ISO10126__ = { 0x74, 0xA5, 0x81, 0x53, 0x4A, 0x4B, 0xF8, 0xB1, 0xAC, 0xB2, 0x70, 0x9C, 0xDC, 0xB5, 0x2C, 0x03, }; //CBC byte[] CBC_PKCS7_____ = { 0x6B, 0x0E, 0xC8, 0x18, 0x33, 0xE5, 0xE6, 0xA7, 0x70, 0xF9, 0x31, 0x8D, 0xDF, 0x6C, 0x6A, 0x86, }; byte[] CBC_Zeros_____ = { 0x6B, 0x0E, 0xC8, 0x18, 0x33, 0xE5, 0xE6, 0xA7, };// 填充Zero√ byte[] CBC_ANSIX923__ = { 0x6B, 0x0E, 0xC8, 0x18, 0x33, 0xE5, 0xE6, 0xA7, 0x28, 0xA0, 0xBC, 0x4A, 0x5A, 0x28, 0x41, 0xB8, }; byte[] CBC_ISO10126__ = { 0x6B, 0x0E, 0xC8, 0x18, 0x33, 0xE5, 0xE6, 0xA7, 0xD5, 0xF9, 0x47, 0xDD, 0xF3, 0xCE, 0x7D, 0xC2, }; } 2017-10-19 22:59:33,455 - 461560 [DEBUG] : ECB : PAD_ISO_1 2017-10-19 22:59:33,456 - 461560 [DEBUG] : B6613EE6938B45710000000000000000 2017-10-19 22:59:33,457 - 461560 [DEBUG] : ECB : PAD_ISO_2 2017-10-19 22:59:33,457 - 461560 [DEBUG] : B6613EE6938B45710000000000000000 2017-10-19 22:59:33,458 - 461560 [DEBUG] : ECB : PAD_PKCS_7 2017-10-19 22:59:33,458 - 461560 [DEBUG] : B6613EE6938B45710000000000000000 // 填充Zero√ 2017-10-19 22:59:33,459 - 461560 [DEBUG] : CBC : PAD_ISO_1 2017-10-19 22:59:33,460 - 461560 [DEBUG] : 409DA7E50DDF617E0000000000000000 2017-10-19 22:59:33,460 - 461560 [DEBUG] : CBC : PAD_ISO_2 2017-10-19 22:59:33,461 - 461560 [DEBUG] : 409DA7E50DDF617E0000000000000000 2017-10-19 22:59:33,462 - 461560 [DEBUG] : CBC : PAD_PKCS_7 2017-10-19 22:59:33,462 - 461560 [DEBUG] : 409DA7E50DDF617E0000000000000000 // 填充Zero√ 2017-10-19 23:01:30,977 - 464436 [DEBUG] : ECB : PAD_ISO_1 2017-10-19 23:01:30,979 - 464436 [DEBUG] : 74A581534A4BF8B10000000000000000 2017-10-19 23:01:30,980 - 464436 [DEBUG] : ECB : PAD_ISO_2 2017-10-19 23:01:30,981 - 464436 [DEBUG] : 74A581534A4BF8B10000000000000000 2017-10-19 23:01:30,982 - 464436 [DEBUG] : ECB : PAD_PKCS_7 2017-10-19 23:01:30,983 - 464436 [DEBUG] : 74A581534A4BF8B10000000000000000 // 填充Zero√ 2017-10-19 23:01:30,988 - 464436 [DEBUG] : CBC : PAD_ISO_1 2017-10-19 23:01:30,989 - 464436 [DEBUG] : 6B0EC81833E5E6A70000000000000000 2017-10-19 23:01:30,990 - 464436 [DEBUG] : CBC : PAD_ISO_2 2017-10-19 23:01:30,990 - 464436 [DEBUG] : 6B0EC81833E5E6A70000000000000000 2017-10-19 23:01:30,991 - 464436 [DEBUG] : CBC : PAD_PKCS_7 2017-10-19 23:01:30,992 - 464436 [DEBUG] : 6B0EC81833E5E6A70000000000000000 // 填充Zero√ 长度不足应该补充 00 ,并且只有不满足8倍数字节的时候才补充字节
不同的填充模式,对于输出的结果最后一组数据会有很大不同。
譬如:
金融DES:在末尾填充“8000...”
PKCS #7: 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
Zeros :填充字符串由设置为零的字节组成。
ANSIX923: 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节均填充数字零。
ISO10126: 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。
代码中C++库,对于其他填充模式支持不好,默认设置为 PAD_PKCS_7,并表现出跟C# Zero填充一样的效果
下面贴出代码示例
c#代码
private byte[] Encrypt(byte[] inputByteArray, string sKey) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //建立加密对象的密钥和偏移量 //原文使用ASCIIEncoding.ASCII方法的GetBytes方法 //使得输入密码必须输入英文文本 des.Mode = CipherMode.CBC; des.Padding = PaddingMode.Zeros; des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); //Write the byte array into the crypto stream //(It will end up in the memory stream) cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); //Get the data back from the memory stream byte[] result = ms.ToArray(); return result; } //解密方法 private byte[] Decrypt(byte[] inputByteArray, string sKey) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //建立加密对象的密钥和偏移量,此值重要,不能修改 des.Mode = CipherMode.CBC; des.Padding = PaddingMode.Zeros; des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); //Flush the data through the crypto stream into the memory stream cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); //Get the data back from the memory stream byte[] result = ms.ToArray(); return result; }