拙网论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 294|回复: 0

c# c++ DES通讯

[复制链接]

949

主题

1001

帖子

3736

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3736
发表于 2019-7-5 09:55:04 | 显示全部楼层 |阅读模式

https://www.cnblogs.com/Again/p/7698187.html

昨天做项目的时候,遇到了c++通讯发送加密数据c#解密出错问题。
因为有很多选项,特地做了个对比,研究了其中的一些参数
DES
要注意的项目:
1.密钥 Key、IV
两个密钥都是8字节
2.模式 ECB、CBC
在ECB模式下,只用key;在CBC模式下,同时使用key和IV
3.字节填充模式  非8倍数字节数、8倍数字节数
[url=][/url]
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_12017-10-19 22:59:33,456 - 461560 [DEBUG] : B6613EE6938B457100000000000000002017-10-19 22:59:33,457 - 461560 [DEBUG] : ECB : PAD_ISO_22017-10-19 22:59:33,457 - 461560 [DEBUG] : B6613EE6938B457100000000000000002017-10-19 22:59:33,458 - 461560 [DEBUG] : ECB : PAD_PKCS_72017-10-19 22:59:33,458 - 461560 [DEBUG] : B6613EE6938B45710000000000000000 // 填充Zero√2017-10-19 22:59:33,459 - 461560 [DEBUG] : CBC : PAD_ISO_12017-10-19 22:59:33,460 - 461560 [DEBUG] : 409DA7E50DDF617E00000000000000002017-10-19 22:59:33,460 - 461560 [DEBUG] : CBC : PAD_ISO_22017-10-19 22:59:33,461 - 461560 [DEBUG] : 409DA7E50DDF617E00000000000000002017-10-19 22:59:33,462 - 461560 [DEBUG] : CBC : PAD_PKCS_72017-10-19 22:59:33,462 - 461560 [DEBUG] : 409DA7E50DDF617E0000000000000000 // 填充Zero√2017-10-19 23:01:30,977 - 464436 [DEBUG] : ECB : PAD_ISO_12017-10-19 23:01:30,979 - 464436 [DEBUG] : 74A581534A4BF8B100000000000000002017-10-19 23:01:30,980 - 464436 [DEBUG] : ECB : PAD_ISO_22017-10-19 23:01:30,981 - 464436 [DEBUG] : 74A581534A4BF8B100000000000000002017-10-19 23:01:30,982 - 464436 [DEBUG] : ECB : PAD_PKCS_72017-10-19 23:01:30,983 - 464436 [DEBUG] : 74A581534A4BF8B10000000000000000 // 填充Zero√2017-10-19 23:01:30,988 - 464436 [DEBUG] : CBC : PAD_ISO_12017-10-19 23:01:30,989 - 464436 [DEBUG] : 6B0EC81833E5E6A700000000000000002017-10-19 23:01:30,990 - 464436 [DEBUG] : CBC : PAD_ISO_22017-10-19 23:01:30,990 - 464436 [DEBUG] : 6B0EC81833E5E6A700000000000000002017-10-19 23:01:30,991 - 464436 [DEBUG] : CBC : PAD_PKCS_72017-10-19 23:01:30,992 - 464436 [DEBUG] : 6B0EC81833E5E6A70000000000000000  // 填充Zero√长度不足应该补充 00 ,并且只有不满足8倍数字节的时候才补充字节[url=][/url]

不同的填充模式,对于输出的结果最后一组数据会有很大不同。
譬如:
金融DES:在末尾填充“8000...”
PKCS #7: 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
Zeros :填充字符串由设置为零的字节组成。
ANSIX923: 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节均填充数字零。
ISO10126: 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。

代码中C++库,对于其他填充模式支持不好,默认设置为 PAD_PKCS_7,并表现出跟C# Zero填充一样的效果
下面贴出代码示例
c#代码
[url=][/url]
        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;        }[url=][/url]


c#demo
byte[] buffer = { 0x02, 0xDF, 0xD1, 0x9F, 0x23, 0xC9, 0x29, 0xA7, 0x3B, 0xB9, 0x92, 0xED, 0x2A, 0xB2, 0x47, 0x03, 0x7E, 0x6F, 0x27, 0x92, 0x0E, 0xDB, 0x17, 0xB2, 0x53, 0x2C, 0x48, 0x38, 0x61, 0x8E, 0x2E, 0xB2, 0xD2, 0xB7, 0xCA, 0x4F, 0x7D, 0xCE, 0x0F, 0xA4, 0xD7, 0x06, 0xA7, 0x29 };byte[] minwen = Decrypt(buffer, "password");

c++ 代码
来源于[邹德强代码]
DES.h
DES.cpp

代码中C++库,对于其他填充模式支持不好,默认设置为 PAD_PKCS_7,并表现出跟C# Zero填充一样的效果
c++封装,相当于使用案例
[url=][/url]
#ifndef CDES_H_CAESAR_1_DEF  #define CDES_H_CAESAR_1_DEF    #include <string>#include <iostream>class HGDes    {  private:    HGDes();    virtual ~HGDes();    public:    //加密 - 从流中加密数据    static void DES_Decrypt(std::istream& input,std:stream& output);    //解密 - 从流中解密数据    static void DES_Encrypt(std::istream& input,std:stream& output);    //加密 - 加密文本到base64格式      static std::string Encrypt_to_Base64(std::string input);    //解密 - 从base64格式解密文本    static std::string Decrypt_from_Base64(std::string input);};    #endif//CDES_H_CAESAR__DEF  [url=][/url]

[url=][/url]
// DES.cpp: implementation of the CDES class.  //  //////////////////////////////////////////////////////////////////////  #include "HGDES.h"  #include "memory.h"  #include <iostream>  #include <sstream>#include "DES.h"#include "..\Base64\Base64.h"using namespace std;         HGDes::HGDes()  {  }    HGDes::~HGDes()  {  }  void HGDes:ES_Encrypt(std::istream& input,std:stream& output){    //计算缓冲区长度    input.seekg(0, input.end);    int datalen = input.tellg();    input.seekg(0, input.beg);    int outlen = ((datalen/8)*8) + ((datalen%8==0) ? 0:8);    //创建缓冲区    char* In = new char[datalen];    char* Out = new char[outlen];    memset(In,0,datalen);    memset(Out,0,outlen);    for (int i=0 ; i<datalen ; i++)    {        In = input.get();    }    int keylen = 8;    char Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,};    char IV[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,};    Des::RunDes(Des::ENCRYPT,Des::CBC, In,Out,datalen,Key,keylen);     for (int i = 0; i < outlen ; i++)    {        output<<Out;    }}void HGDes:ES_Decrypt(std::istream& input,std:stream& output){    //计算缓冲区长度    input.seekg(0, input.end);    int datalen = input.tellg();    input.seekg(0, input.beg);    int outlen = ((datalen/8)*8) + ((datalen%8==0) ? 0:8);    //创建缓冲区    char* In = new char[datalen];    char* Out = new char[datalen];    memset(In,0,datalen);    memset(Out,0,datalen);    for (int i=0 ; i<datalen ; i++)    {        In = input.get();    }    int keylen = 8;    char Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,};    char IV[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,};    Des::RunDes(Des:ECRYPT,Des::CBC, In,Out,datalen,Key,keylen);     //计算末尾0的数量    int count = 0;    for (int i = outlen - 1; i >= 0 ; i--)    {        if (Out != 0)        {            break;        }        count++;    }    for (int i = 0; i < outlen - count ; i++)    {        output<<Out;    }}std::string HGDes::Encrypt_to_Base64(std::string input){    if (input.empty())    {        return "";    }    else    {        std::stringstream inputstream;        inputstream << input;        std::stringstream outputstream;        DES_Encrypt(inputstream,outputstream);        std::string result = Base64::base64_encode(outputstream);        return result;    }}std::string HGDes:ecrypt_from_Base64(std::string input){    if (input.empty())    {        return "";    }    else    {        std::stringstream inputstream;        Base64::base64_decode(input,inputstream);        std::stringstream outputstream;        DES_Decrypt(inputstream,outputstream);        return outputstream.str();    }}[url=][/url]



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|抱朴守拙BBS

GMT+8, 2025-5-25 23:11 , Processed in 0.190379 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表