可以相互解密的C#版及C++版DES算法代码(包括ECB、CBC模式,Zeros、PKCS7填充,以及Base64编解码)
来源:互联网 发布:linux系统安装教程图解 编辑:程序博客网 时间:2024/06/15 15:00
由于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 ""; } }}
2.C++代码(BCB编写)此部分请参照http://blog.csdn.net/bengold1979/article/details/2208930,我调整了DES算法函数及填充函数,其他变化不大,另外我增加了Base64编码类
(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个0x00PAD_ISO_2, // ISO_2填充:数据长度不足8比特的倍数,以0x80,0x00..补足,如果为8比特的倍数,补0x80,0x00..0x00PAD_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
(2)DES.CPP文件请参考http://blog.csdn.net/bengold1979/article/details/2208930,我将有变动的部分贴出来。
//---------------------------------------------------------------------------#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]; //密钥 //构造并生成SubKeysunsigned 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){//待补充}elseif(PaddingMode == PAD_ISO_2){//待补充}elseif(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 00ffffffvoid 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-150x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,//1 16-310x40,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#代码相互解密。如有不妥之处,欢迎大家提出宝贵意见。
0 0
- 可以相互解密的C#版及C++版DES算法代码(包括ECB、CBC模式,Zeros、PKCS7填充,以及Base64编解码)
- Java版适用于PHP版3DES加密解密(PHP语言开发的MCRYPT_3DES算法、MCRYPT_MODE_ECB模式、PKCS7填充方式)
- Android DES加密的CBC和ECB加密解密模式
- Android DES加密的CBC模式加密解密和ECB模式加密解密
- PHP DES加密/解密 ECB 、pkcs5/pkcs7
- AES CBC方式,PKCS7填充加密解密,和其他语言试过,可以共用
- Java 运用 Bouncy Castle 进行 AES128 加密解密(CBC 模式 PKCS7 填充 )
- Java 运用 Bouncy Castle 进行 AES128 加密解密(CBC 模式 PKCS7 填充 )
- Base64编解码原理及AES加解密算法的使用
- 3DES、DES的CBC、ECB
- java和.net相互http请求并且经过des的cbc模式加密解密
- java和.net相互http请求并且经过des的cbc模式加密解密(转)
- ECB CBC DES TDES 算法原理
- triple Des加密之ECB加密解密、CBC加密解密
- LINUX、C#下使用DES算法CBC模式进行对称加密、解密
- C#/JAVA/PHP 互通DES加解密算法(ECB模式支持8位)
- C/C++: 3DES-ECB模式加密,可以与C#和Java互通
- DES ECB模式JAVA PHP C#实现加密、解密兼容
- Linux编程基础:C标准库IO缓冲区与内核缓冲区的区别
- Lua,ruby和Python的比较
- Spring四种依赖注入方式
- SQLite创建多个表
- insmod源码分析
- 可以相互解密的C#版及C++版DES算法代码(包括ECB、CBC模式,Zeros、PKCS7填充,以及Base64编解码)
- MySQL
- MFC 打开指定文件夹对话框
- vs 2010调用matlab dll显示窗口核心代码
- JFreeChart的使用
- 自定义 Popwindow
- lua学习2
- QML类型说明-GmmaAdjust
- Java之统计并输出文本文件中元音字母a,e,i,o,u的个数