1. 程式人生 > >可以相互解密的C#版及C++版DES演算法程式碼(包括ECB、CBC模式,Zeros、PKCS7填充,以及Base64編解碼)

可以相互解密的C#版及C++版DES演算法程式碼(包括ECB、CBC模式,Zeros、PKCS7填充,以及Base64編解碼)

由於C#中對於DES演算法有標準類,所以使用起來特別簡單;但C++就有點費勁了,經過整合網上資源並修改bug,現在放出完整C++DES演算法程式碼,已測試通過。這裡要特別感謝http://blog.csdn.net/bengold1979/article/details/2208930,他的程式碼中大部分都沒問題,但是在PKCS7填充演算法的加密解密中有一些問題,經過調整,目前ECB、CBC模式,Zeros、PKCS7填充演算法都以可以正常執行,還有其他填充演算法尚待補充。

本文所使用的加密思路是先進行DES加密然後進行Base64編碼。解密反之。

1.先放出DES加密解密C#程式碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.IO.Compression;
using System.Xml;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
using System.ComponentModel;
using System.Security.Cryptography;
using DES.Core;
using System.Globalization;

namespace DESConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            //加密示例 /E /Stext /Y
            //解密示例 /D /Stext /Y
            if (args.Length == 0) return;
            string param1 = args[0];
            string param2 = "/S";
            bool IncludeLocalInfo = false;            
            Tools ToolObj = new Tools();

            if (param1 == "/E")
            {
                if (args.Length >= 2)
                    param2 = args[1];
                if (param2.Substring(0, 2) == "/S")
                    param2 = param2.Substring(2, param2.Length - 2);
                if (args.Length >= 3)
                    IncludeLocalInfo = (args[2] == "Y");
                Console.WriteLine("加密:{0}", Tools.Encrypt(param2, IncludeLocalInfo));    
            }
            else if (param1 == "/D")
            {
                if (args.Length >= 2)
                    param2 = args[1];
                if (param2.Substring(0, 2) == "/S")
                    param2 = param2.Substring(2, param2.Length - 2);
                if (args.Length >= 3)
                    IncludeLocalInfo = (args[2] == "Y");
                Console.WriteLine("解密:{0}", Tools.Decipher(param2, IncludeLocalInfo));
            }            
        }
    }
}


namespace DES.Core
{
    /// <summary>
    /// 核心模組的公用涵數類別。
    /// </summary>
    [Serializable]
    public class Tools
    {
        /// <summary>
        /// 常量。
        /// </summary>
        private static String _ConstValue = "HELLOYOU"; //8碼
        /// <summary>
        /// 使用DES加密
        /// </summary>
        /// <param name="Str">待加密的字串</param>
        /// <param name="IncludeLocalInfo">是否包含本地硬體訊息。</param>
        /// <returns>加密後的字串</returns>
        public static String Encrypt(String Str, bool IncludeLocalInfo)
        {
            
            try
            {
                SymmetricAlgorithm sa = new DESCryptoServiceProvider();
                String _Key = _ConstValue;
                sa.Key = Encoding.UTF8.GetBytes(_Key);
                sa.IV = Encoding.UTF8.GetBytes(_ConstValue);
                //指定加密的運算模式
                sa.Mode = System.Security.Cryptography.CipherMode.CBC;
                //獲取或設定加密演算法的填充模式
                sa.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

                ICryptoTransform ct = sa.CreateEncryptor();

                byte[] byt = Encoding.UTF8.GetBytes(Str);

                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
                cs.Write(byt, 0, byt.Length);
                cs.FlushFinalBlock();
                cs.Close();
                return Convert.ToBase64String(ms.ToArray());
            }
            catch { }
            return "";
        }
        /// <summary>
        /// 使用DES解密
        /// </summary>
        /// <param name="Str">待解密的字串</param>
        /// <param name="IncludeLocalInfo">是否包含本地硬體訊息。</param>
        /// <returns>解密後的字串</returns>
        public static String Decipher(String Str, bool IncludeLocalInfo)
        {
            if (null == Str || 0 == Str.Length) return "";
            try
            {
                SymmetricAlgorithm sa = new DESCryptoServiceProvider();
                String _Key = _ConstValue;
                sa.Key = Encoding.UTF8.GetBytes(_Key);
                sa.IV = Encoding.UTF8.GetBytes(_ConstValue);
                ICryptoTransform ct = sa.CreateDecryptor();

                byte[] byt = Convert.FromBase64String(Str);

                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
                cs.Write(byt, 0, byt.Length);
                cs.FlushFinalBlock();
                cs.Close();
                return Encoding.UTF8.GetString(ms.ToArray());
            }
            catch { }
            return "";
        }              
    }
}


(1)標頭檔案DES.H

宣告DES類及Base64編碼類

//---------------------------------------------------------------------------

#ifndef DESH
#define DESH
#include <vcl.h>
//---------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////
//                                                                  //
// DES.h: declaration of the TDES、TBase64、TBase64DES class.     //
//                                                                  //
//////////////////////////////////////////////////////////////////////

/* TDES類說明
 *
 * 該類是DES和3DES演算法類
 *
 */
class TDES
{
public:
    TDES();
    virtual ~TDES();

    //加密解密
	enum
	{
		ENCRYPT = 0,    // 加密
		DECRYPT,        // 解密
	};

	//DES演算法的模式
	enum
	{
		ECB     = 0,    // ECB模式
		CBC             // CBC模式
	};

	typedef bool (*PSubKey)[16][48];

	//Pad填充的模式
	enum
	{
		PAD_ISO_1 = 0,  // ISO_1填充:資料長度不足8位元的倍數,以0x00補足,如果為8位元的倍數,補8個0x00
		PAD_ISO_2,      // ISO_2填充:資料長度不足8位元的倍數,以0x80,0x00..補足,如果為8位元的倍數,補0x80,0x00..0x00
		PAD_PKCS_7      // PKCS7填充:資料長度除8餘數為n,以(8-n)補足為8的倍數,如果為8位元的倍數,補8個0x08
	};

	/* 執行DES演算法對文字加解密
	 *
	 * Description    : 執行DES演算法對文字加解密
	 * @param bType   : 型別:加密ENCRYPT,解密DECRYPT
	 * @param bMode   : 模式:ECB,CBC
	 * @param In      : 待加密串指標
	 * @param Out     : 待輸出串指標
	 * @param datalen : 待加密串的長度,同時Out的緩衝區大小應大於或者等於datalen
	 * @param Key     : 金鑰(可為8位,16位,24位)支援3金鑰
	 * @param keylen  : 金鑰長度,多出24位部分將被自動裁減
	 * @return true--成功;false--失敗;
	 */
	static bool RunDES(bool bType, bool bMode, int PaddingMode, const unsigned char* IV, const unsigned char* In,
		unsigned char* Out, unsigned datalen, const unsigned char* Key, unsigned keylen);

protected:
	//計算並填充子金鑰到SubKey資料中
	static void SetSubKey(PSubKey pSubKey, const unsigned char Key[8]);

	//DES單元運算
	static void DES(unsigned char Out[8], const unsigned char In[8], const PSubKey pSubKey, bool Type);

	/* 補足8位資料
	 *
	 * Description    : 根據協議對加密前的資料進行填充
	 * @param nType   : 型別:PAD型別
	 * @param In      : 資料串指標
	 * @param Out     : 填充輸出串指標
	 * @param datalen : 資料的長度
	 * @param padlen  : (in,out)輸出buffer的長度,填充後的長度
	 * @return true--成功;false--失敗;
	 */
	static bool RunPad(bool bType, int nType, const unsigned char* In,
		unsigned datalen, unsigned char* Out, unsigned& padlen);
};
//---------------------------------------------------------------------------

/* TBase64類說明
 *
 * 該類是Base64編碼類
 *
 */
class TBase64
{
public:
	static char* Base64_Encode(const char* src);
	static char* Base64_Decode(const char* src);
protected:
	static void Base64_Encode(unsigned char* src,unsigned char* dest, int srclen);
	static void Base64_Decode(unsigned char* src, unsigned char* dest, int srclen);
	static int GetLenEncode(const char* src);
	static int GetLenDecode(const char* src);
};
//---------------------------------------------------------------------------
#endif


//---------------------------------------------------------------------------


#pragma hdrstop

#include "DES.h"
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------

#pragma package(smart_init)
///////////////////////////////////////////////////////////////////////////////////
//                                                                               //
// DES.cpp: implementation of the TDES and TBase64 class.                      //
//                                                                               //
// Date: 2014.09.10                                                              //
// Description:                                                                  //
//    DES類,支援ECB、CBC演算法,PAD_ISO_1、PAD_ISO_2、PKCS7填充模式               //
//    BASE64類,支援將BYTE轉為Base64編碼                                         //
//                                                                               //
///////////////////////////////////////////////////////////////////////////////////

const char _ConstValue[] = {"HELLOYOU"};//8碼
。。。。。。。。。部分程式碼請參考上文提到的連結。。。。。。。。。。。。。。。。
/*使用示例:

*/
bool TDES::RunDES(bool bType, bool bMode, int PaddingMode, const unsigned char* Iv, const unsigned char* In,
		unsigned char* Out, unsigned datalen, const unsigned char* Key, unsigned keylen)
{
	memset(Out, 0x00, strlen(Out));
	unsigned char* outbuf = Out;
    //判斷輸入合法性
	if(!(/*In && */outbuf && Key && /*datalen &&*/ keylen>=8)) // 空字串加密的時候In和datalen都為0,應該去掉此判斷
		return false;

	unsigned char* inbuf = new unsigned char[datalen + 8];
	memset(inbuf, 0x00, datalen + 8);
	memcpy(inbuf, In, datalen);
	unsigned padlen = datalen;
	// 根據填充模式填充
	if (!RunPad(bType, PaddingMode, In, datalen, inbuf, padlen))
	{
		delete []inbuf; inbuf = NULL;
		return false;
	}
	unsigned char* tempBuf = inbuf;

    bool m_SubKey[3][16][48];        //金鑰
    //構造並生成SubKeys
	unsigned char nKey = (keylen>>3)>=3 ? 3: (keylen>>3);
    for(int i=0;i<nKey;i++)
    {
        SetSubKey(&m_SubKey[i],&Key[i<<3]);
    }

    if(bMode == ECB)    //ECB模式
    {
        if(nKey ==  1)  //單Key
        {
            int j = padlen>>3;
            for(int i=0,j = padlen>>3;i<j;++i,outbuf+=8,tempBuf+=8)
            {
                DES(outbuf,tempBuf,&m_SubKey[0],bType);
            }
        }
        else
        if(nKey == 2)   //3DES 2Key
        {
            for(int i=0,j = padlen>>3;i<j;++i,outbuf+=8,tempBuf+=8)
            {
                DES(outbuf,tempBuf,&m_SubKey[0],bType);
                DES(outbuf,outbuf,&m_SubKey[1],!bType);
                DES(outbuf,outbuf,&m_SubKey[0],bType);
            }
        }
        else            //3DES 3Key
        {
            for(int i=0,j=padlen>>3;i<j;++i,outbuf+=8,tempBuf+=8)
            {
                DES(outbuf,tempBuf,&m_SubKey[bType? 2 : 0],bType);
                DES(outbuf,outbuf,&m_SubKey[1],!bType);
                DES(outbuf,outbuf,&m_SubKey[bType? 0 : 2],bType);
            }
        }
    }
    else                //CBC模式
	{
		unsigned char   cvec[8] =   ""; // 扭轉向量
		unsigned char   cvin[8] =   ""; // 中間變數
		memcpy(cvec, Iv, 8);

        if(nKey == 1)   //單Key
        {
			for(int i=0,j=padlen>>3;i<j;++i,outbuf+=8,tempBuf+=8)
            {
				if(bType    ==  TDES::ENCRYPT)
                {
                    for(int j=0;j<8;++j)     //將輸入與扭轉變數異或
                    {
                        cvin[j] =   tempBuf[j] ^ cvec[j];
                    }
                }
                else
                {
                    memcpy(cvin,tempBuf,8);
                }

                DES(outbuf,cvin,&m_SubKey[0],bType);

                if(bType    ==  TDES::ENCRYPT)
                {
                    memcpy(cvec,outbuf,8);         //將輸出設定為扭轉變數
                }
                else
                {
					for(int j=0;j<8;++j)     //將輸出與扭轉變數異或
                    {
						outbuf[j]  =   outbuf[j] ^ cvec[j];
                    }
                    memcpy(cvec,cvin,8);            //將輸入設定為扭轉變數
                }
			}
		}
        else
        if(nKey == 2)   //3DES CBC 2Key
        {
            for(int i=0,j=padlen>>3;i<j;++i,outbuf+=8,tempBuf+=8)
            {
                if(bType    ==  TDES::ENCRYPT)
                {
                    for(int j=0;j<8;++j)     //將輸入與扭轉變數異或
                    {
						cvin[j] =   tempBuf[j] ^ cvec[j];
                    }
				}
                else
                {
                    memcpy(cvin,tempBuf,8);
                }

                DES(outbuf,cvin,&m_SubKey[0],bType);
                DES(outbuf,outbuf,&m_SubKey[1],!bType);
                DES(outbuf,outbuf,&m_SubKey[0],bType);

                if(bType    ==  TDES::ENCRYPT)
                {
                    memcpy(cvec,outbuf,8);         //將輸出設定為扭轉變數
                }
                else
                {
                    for(int j=0;j<8;++j)     //將輸出與扭轉變數異或
                    {
                        outbuf[j]  =   outbuf[j] ^ cvec[j];
                    }
                    memcpy(cvec,cvin,8);            //將輸入設定為扭轉變數
                }
            }
        }
        else            //3DES CBC 3Key
        {
            for(int i=0,j=padlen >>3;i<j;++i,outbuf+=8,tempBuf+=8)
            {
                if(bType    ==  TDES::ENCRYPT)
                {
                    for(int j=0;j<8;++j)     //將輸入與扭轉變數異或
                    {
                        cvin[j] =   tempBuf[j] ^ cvec[j];
                    }
                }
                else
                {
                    memcpy(cvin,tempBuf,8);
                }

                DES(outbuf,cvin,&m_SubKey[bType ? 2 : 0],bType);
                DES(outbuf,outbuf,&m_SubKey[1],!bType);
                DES(outbuf,outbuf,&m_SubKey[bType ? 0 : 2],bType);

                if(bType    ==  TDES::ENCRYPT)
				{
                    memcpy(cvec,outbuf,8);         //將輸出設定為扭轉變數
                }
                else
                {
                    for(int j=0;j<8;++j)     //將輸出與扭轉變數異或
                    {
						outbuf[j]  =   outbuf[j] ^ cvec[j];
                    }
                    memcpy(cvec,cvin,8);            //將輸入設定為扭轉變數
                }
			}
        }
	}
	if(inbuf)
	{
		delete []inbuf;
		inbuf = NULL;
	}
	if(bType == TDES::DECRYPT)
	{
		if(PaddingMode    ==  PAD_ISO_1)
		{
			//待補充
		}
		else
		if(PaddingMode    ==  PAD_ISO_2)
		{
			//待補充
		}
		else
		if(PaddingMode    ==  PAD_PKCS_7)
		{
			unsigned int l_Out = strlen(Out);
			unsigned int l_num = Out[l_Out-1];
			if (l_num <= 8) // 非法密文會造成此處出問題,加以保護
				memset(Out+l_Out-l_num, 0x00, l_num);
		}
	}

	return true;
}




/*******************************************************************/
  /*
  函 數 名 稱:  RunPad
  功 能 描 述: 根據協議對加密前的資料進行填充
  參 數 說 明: bType   :型別:PAD型別
				In      :資料串指標
				Out     :填充輸出串指標
				datalen :資料的長度
				padlen  :(in,out)輸出buffer的長度,填充後的長度

  返回值 說明: bool    :是否填充成功
  修 改 歷 史:
		2014.09.10 修改PKCS7填充演算法;修改明文是8byte的整倍數時加密解密演算法;修改解密演算法
  更 新 日 期:  2014.09.10
  */
/*******************************************************************/
bool TDES::RunPad(bool bType, int nType, const unsigned char* In,
		 unsigned datalen, unsigned char* Out, unsigned& padlen)
{
    if (nType < PAD_ISO_1 || nType > PAD_PKCS_7)
        return false;

	if (In == NULL || datalen < 0 || Out == NULL)
        return false;
	int res = (datalen & 0x07);

	if(bType == TDES::DECRYPT)
	{
		padlen = datalen;
		memcpy(Out, In, datalen);
		return true;
	}

	padlen = (datalen+8-res);
	memcpy(Out,In,datalen);

	if(nType    ==  PAD_ISO_1)
	{
		memset(Out+datalen,0x00,8-res);
    }
    else
    if(nType    ==  PAD_ISO_2)
    {
        memset(Out+datalen,0x80,1);
        memset(Out+datalen,0x00,7-res);
    }
    else
    if(nType    ==  PAD_PKCS_7)
    {
		memset(Out+datalen,8-res,8-res);
	}
	else
	{
		// 其他填充模式尚待補充
        return false;
    }

    return true;
}

//轉換前 aaaaaabb ccccdddd eeffffff
//轉換後 00aaaaaa 00bbcccc 00ddddee 00ffffff
void TBase64::Base64_Encode(unsigned char* src,unsigned char* dest, int srclen)
{
	//編碼函式
	unsigned char EncodeIndex[] =
	{
		//編碼索引表
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
	 	'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/','='
	};

	 int sign = 0;
	 for (int i = 0; i!= srclen; i++,src++,dest++)
	 {
		  switch(sign)
		  {
			  case 0://編碼第1位元組
			   *(dest) = EncodeIndex[*src >> 2];
			   break;
			  case 1://編碼第2位元組
			   *dest = EncodeIndex[((*(src-1)  & 0x03) << 4) | (((*src) & 0xF0) >> 4)];
			   break;
			  case 2://編碼第3位元組
			   *dest = EncodeIndex[((*(src-1) &0x0F) << 2) | ((*(src) & 0xC0) >> 6)];
			   *(++dest) = EncodeIndex[(*(src) &0x3F)];//編碼第4位元組
			   break;
		  }
		  (sign == 2)?(sign = 0):(sign++);
	 }

	 switch(sign)
	 {
	 	//3的餘數位元組,後補=處理
		 case 0:
		  break;
		 case 1:
		 // *(dest++) = EncodeIndex[((*(src-1)  & 0x03) << 4) | (((*src) & 0xF0) >> 4)];
		  *(dest++) = EncodeIndex[((*(src-1)  & 0x03) << 4) ];
		  *(dest++) = '=';
		  *(dest++) = '=';
		  break;
		 case 2:
		 // *(dest++) = EncodeIndex[((*(src-1) &0x0F) << 2) | ((*(src) & 0xC0) >> 6)];
		  *(dest++) = EncodeIndex[((*(src-1) &0x0F) << 2)];
		  *(dest++) = '=';
		  break;
		 default:
		  break;
	 }
}
//---------------------------------------------------------------------------

void TBase64::Base64_Decode(unsigned char* src, unsigned char* dest, int srclen)
{
	unsigned char DecodeIndex[] =
	{
		//解碼索引表
		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,//0  00-15
		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,//1  16-31
		0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x3E,0x40,0x40,0x40,0x3F,//2  32-47    43[+](0x38)  47[/](0x39)
		0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x40,0x40,0x40,0x40,0x40,0x40,//3  48-63    48[0](0x34)- 57[9](0x3D)  61[=](0x40)
		0x40,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,//4  64-79    65[A](0x00)- 79[O](0x0E)
		0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x40,0x40,0x40,0x40,0x40,//5  80-95    80[P](0x0F)- 90[Z](0x19)
		0x40,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,//6  96-111   97[a](0x1A)-111[o](0x28)
		0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x40,0x40,0x40,0x40,0x40 //7 112-127  122[p](0x29)-122[z](0x33)
	};

	//解碼處理函式 //len%4 == 0總為true;
	for (int i = 0; i != srclen/4; i++)//對於不足4個的不作計算
	{
		//每個字元,通過陣列直接得到其值,比較快
		*dest = (DecodeIndex[*src] << 2) | ((DecodeIndex[*(src+1)] & 0x30) >> 4);
		*(dest+1) = (DecodeIndex[*(src+1)] << 4) | ((DecodeIndex[*(src+2)] &0x3C) >> 2);
		*(dest+2) = ((DecodeIndex[*(src+2)] & 0x03) << 6) | (DecodeIndex[*(src+3)] & 0x3F);
		src += 4;
		dest += 3;
	}
}
//---------------------------------------------------------------------------
//*/
int TBase64::GetLenEncode(const char* src)
{
	//求編碼後的長度
	int len = strlen((char*)src);
	return (len + (len%3 == 0? 0:(3-len%3)))/3*4 + 1;
}
//---------------------------------------------------------------------------
int TBase64::GetLenDecode(const char* src)
{
	//求解碼後的長度
	int len = strlen(src);
	return len/4*3 + 1;
}
//---------------------------------------------------------------------------
char* TBase64::Base64_Encode(const char* src)
{
	int src_len = strlen(src);
	int lenEncode = GetLenEncode(src);
	unsigned char* Base64Out = new unsigned char[lenEncode];
	memset(Base64Out, 0x00, lenEncode);
	Base64_Encode((unsigned char *)src, (unsigned char *)Base64Out, src_len);//原字元長度
	return Base64Out;
}
//---------------------------------------------------------------------------
char* TBase64::Base64_Decode(const char* src)
{
	int lenEncode = strlen(src);
	int lenDecode = GetLenDecode((const char *)src);//獲得編碼後字串的再解碼的長度
	unsigned char* pDecodeStr = new unsigned char[lenDecode];
	memset(pDecodeStr, 0x00, lenDecode);
	Base64_Decode((unsigned char *)src, pDecodeStr, lenEncode);//編碼後的字元長度
	return pDecodeStr;
}
//---------------------------------------------------------------------------



(3)測試程式碼標頭檔案Base64DES.H

//---------------------------------------------------------------------------

#ifndef Base64DESH
#define Base64DESH
#include "DES.h"
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) WINAPI void MainTest();

#endif


(4)測試程式碼Base64DES.CPP檔案

//---------------------------------------------------------------------------


#pragma hdrstop

#include "Base64DES.h"
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------

#pragma package(smart_init)
extern const char _ConstValue[];

/*
測試程式碼1
*/

extern "C" __declspec(dllexport) WINAPI void MainTest()
{
	puts("Testing RunDES......");

	char In[1024] = {0};
	char Out[1024] = {0};
	char Key[8] = {0};
	memcpy(Key, _ConstValue, 8);
	char IV[8] = {0};
	memcpy(IV, _ConstValue, 8);
	puts("please input your words");
	gets(In);

	// 對str進行DES加密,CBC + PKCS7模式
	memset(Out, 0x00, 1024);
	TDES::RunDES(TDES::ENCRYPT, TDES::CBC, TDES::PAD_PKCS_7, IV, In, Out, strlen(In), Key, strlen(Key));
	puts("after encrypting:");
	puts(Out);

	// 將加密後的strout進行Base64編碼
	char* Base64Out =  TBase64::Base64_Encode(Out);
	printf("Base64編碼之後,您的檔案經過DES加密後的密文是:\n");
	printf("%s\n", Base64Out);

	// 對Base64編碼的pEncodeStr進行解碼
	char* ByteIn =  TBase64::Base64_Decode(Base64Out);
	printf("Base64解碼之後的明文是:\n");
	puts(ByteIn);

	// 用Base64解碼後的pDecodeStr進行DES解密,CBC + PKCS7模式
	memset(In, 0x00, 1024);
	TDES::RunDES(TDES::DECRYPT, TDES::CBC, TDES::PAD_PKCS_7, IV, ByteIn, In, strlen(ByteIn), Key, strlen(Key));
	printf("Base64解碼之後,您的檔案經過DES解密後的明文是:\n");
	puts(In);

	// 用未經編碼的strout直接DES解密,CBC + PKCS7模式
	puts("after decrypting:");
	memset(In, 0x00, 1024);
	TDES::RunDES(TDES::DECRYPT, TDES::CBC, TDES::PAD_PKCS_7, IV, Out, In, strlen(Out), Key, strlen(Key));
	puts(In);

	delete []Base64Out; Base64Out=NULL;
	delete []ByteIn; ByteIn=NULL;
}
// ---------------------------------------------------------------------------




經過測試,此部分C++DES演算法可以和C#程式碼相互解密。如有不妥之處,歡迎大家提出寶貴意見。

相關推薦

可以相互解密C#C++DES演算法程式碼(包括ECBCBC模式ZerosPKCS7填充以及Base64解碼)

由於C#中對於DES演算法有標準類,所以使用起來特別簡單;但C++就有點費勁了,經過整合網上資源並修改bug,現在放出完整C++DES演算法程式碼,已測試通過。這裡要特別感謝http://blog.csdn.net/bengold1979/article/details/2

Base64解碼(C++) (轉)

標頭檔案h#include <string>using namespace std;class ZBase64{public:    /*編碼    DataByte        [in]輸入的資料長度,以位元組為單位    */    string Encode(const unsigned

c語言通過openssl aes對稱加解密base64解碼將密碼儲存成密文

今天遇到這樣一個問題,將客戶端中的一個密碼儲存到檔案中以供下次使用,但是儲存的密碼不能直接儲存明文,需要進行加密處理,再三考慮之後,這個加密的過程需要雙向的可逆的過程,MD5等方式是不適用的,因為記住密碼意味著下次我還需要還原這個密碼進行使用,所以最後選擇了openssl的aes演算法,然而ae

圖相關(三)圖的鄰接矩陣表示(C++)最最小生成樹演算法(prim和kruskal)

一.測試用圖 鄰接矩陣表示: //prim注意是無向圖 vector<vector<int>> p(6, vector<int>(6, INF));//類似dijikstra,沒有邊的點設為INF p[0][1] = 10;

圖相關(二)圖的鄰接矩陣表示(C++)最短路徑演算法

一.Dijikstra演算法 注意:計算最短路徑時,需要把鄰接矩陣中沒有邊的位置初始化為無窮大;此處以INF表示,INF可以取0x3f3f3f3f,不能直接設為INT_MAX(因為做加法時會上溢)。 測試用圖: 其鄰接矩陣表示為: vector<vector<int

C# RSA加密解密加簽驗籤支援JAVA格式公鑰私鑰PEM格式公鑰私鑰.NET格式公鑰私鑰一般模式【支援公鑰加密私鑰解密】(一)

2017-12-04日更新:增加支援微信支付。程式碼註釋中//☆☆☆☆.NET 4.6以後特有☆☆☆☆的別用,那個不對。 RSA非對稱加密。簡明扼要吧,直說乾貨。(在此特別感謝下貳進位制,提供JAVA版的公鑰私鑰) C#RSA加簽解籤加密比較常見,一般遇到的問題是非.NET

Mac系統Android Studio獲取除錯開發SHA1方法

除錯版: 1.直接在Android Studio工程中開啟Terminal: 2.輸入keytool -list -v -keystore ~/.android/debug.keystore 回車

C語言中使用Libb64進行Base64解碼

tar 語言 number const string ken doc get eof Libb64下載地址http://sourceforge.net/projects/libb64 以下為Demo CLibb64Demo.c #include <stdio.h&g

C++實現base64解碼

將昨天的php程式碼改造成C++ /*base_64.h檔案*/ #ifndef BASE_64_H #define BASE_64_H /** * Base64 編碼/解碼 * @author liruixing */ class Base64{ private: std

[c++]base64解碼 and image

      //½«Í¼ÏñתΪbase64¸ñʽ vector&l

C++ 實現圖片base64解碼

最近使用人臉識別restfulAPI遇到了要求圖片base64編碼後傳輸問題。 藉此機會瞭解下什麼是base64編碼。 1 什麼是base64編碼 所謂Base64,就是說選出64個字元—-小寫字母a-z、大寫字母A-Z、數字0-9、符號”+”、”

9.C++中的base64解碼實現

#include <string> #include <iostream> #include<stdio.h> using namespace std; std::string base64_encode(unsigned char con

ubuntu下c++中base64解碼測試和圖片解碼測試

全棧工程師開發手冊 (作者:欒鵬) 字元陣列的base64編解碼 base64.h #include <string> std::string base64_encode(unsigned char const* , unsigned in

《程式設計師的第一年》---------- 資料探勘之資料處理(C#基於熵的離散化演算法程式碼

熵(entropy)是最常用的離散化度量之一。它由Claude Shannon在資訊理論和資訊增益概念的開創性工作中首次引進。基於熵的離散化是一種監督的、自頂向下的分裂技術。它在計算和確定分裂點(劃分屬性區間的資料值)時利用類分佈資訊。為了離散數值屬性A,該方法選擇A的具

base64解碼原理與C程式碼實現

1、base64編碼原理分析: (1)、背景與應用: 可參考部落格:Base64編碼原理與應用 所謂base64就是基於ASCII碼的64個可見字元子集的一種編碼方式。 (2)、編碼原理與核心分析: 上面提到的子集如下所示: A~Z、a~z、0~

python3url解碼base64解碼ASE加解密

字元編解碼 Python3相對於Python2的一大改變就是,對預設字元型別進行了修改。Python2中定義字串預設為二進位制字串,強制加字首u的才是unicode字串;而Python3中字串預設為unicode,強制加字首b的才是二進位制字串。(也就是剛好反過來了) 這裡的二進位制字串:指

C語言程式設計 實踐參考 分段函式求值switch語句

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C語言程式設計 實踐參考——個人所得稅計算器if語句

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C++primer第五 函式過載函式匹配

函式過載即同一作用域內的幾個函式名字相同但形參列表不同,注意,不允許兩個函式除了返回型別外其他所有的要素都相同。 在大多數情況下,我們容易確定某次呼叫應該選用哪個過載函式,然而,當幾個過載函式的形引數量相等以及某些形參可以由其他型別轉換得來時,就比較複雜了。函式匹配首先是確定候選函式和可行函式,

C#程式設計應用教程(第2)》馬駿.pdf

書籍簡介: 《C#程式設計及應用教程(第2版)》詳細介紹C#程式設計及其應用技術。全書由C#程式設計基礎、Windows應用程式設計和web應用程式設計三部分組成.主要內容包括C#言基礎知識、面向物件的程式設計技術、Windows窗體控制元件、目錄與檔案管理、圖形影象處理、ADONET、報