应用Cryptopp库实现AES加密【转】

2019-07-13 09:24发布


crypto++自身的wiki上就有一些例子,可以参考:
   http://www.cryptopp.com/wiki/Category:Sample
(本文来源:http://ste.xidian.edu.cn/bbs/a/a.asp?B=5&ID=224&p=1&q=1&r=146  )
应用Cryptopp库实现AES加密
在win32的操作系统下用vc6++来编译Crypto++? Library 5.1 的源代码,在对应的目录下会产生文件夹Debug,在文件夹Debug里,会有一个编译好的静态库文件cryptlib.lib;下面通过实例研究这个静态库文件的使用:

在应用lib文件时先把库里的头文件和lib文件复制到工程的目录里这是最好的方法,或者把它们放到一个文件夹里修改指定的include 目录,即在菜单Tools中选Options,在Options的对话框里选Directories 在include files和Library files 的页面添加指向该文件夹的路径。



Hash函数的应用:

Hash函数的最基本的用法就是计算Hash值,一个Hash函数是一个多对一的映射,可以输入任意长度的消息,输出却是一个固定长度的消息,而且,只要有一点很微小的差异的两个消息之间的Hash值也会有很大的差异,根据两个不同的Hash值就可以判断对应的两个消息是不同的。所以Hash函数通常用于数字签名和消息的完整性检测等等一些安全性方面的应用。下面举一个计算字符串的Hash值简单的例子。

#pragma comment (lib,"cryptlib.lib")  //加载lib文件的语句

#include "md5.h"

#include

using namespace CryptoPP; //使用名字空间CryptoPP

 using namespace std; //使用名字空间std



void main(){

    byte message[128];       byte m[16];

       cout<<"输入字符串"<
       MD5 md5; md5.Update(message,128); md5.Final(m);        

       for(int i=0;i<16;i++)printf("%02x",m);printf(" ");            

}

这个例子首先生成MD5对象(类MD5在md5.h里定义),调用方法Update()和Final(),这两个方法是定义在基类HashTransformation里的。void Update (const byte *input, unsigned int length) 是用来处理输入的方法,input 是byte型是将要计算Hash值的字符串,length是字符串的长度。void Final (byte *digest) 是计算当前消息的Hash值并重新开始新的消息的方法,digest是用来存放Hash值的byte型数组。

HashTransformation还定义了几个常用的方法 void CalculateDigest (byte *digest, const byte *input, unsigned int length)也是用来计算hash值的方法,可以用md5. CalculateDigest(m,message,128),来替换上面例子md5.Update(message,128)与 md5.Final(m) 这两个语句。

在消息完整性检测方面我们通常都是检测文件的完整性,一个相当大的文件如果对其进行一个很微小的修改我们根本看不出的,但是它们的Hash值却有很大的变化,所以我们只要比较Hash值就很容易看出该文件是否为原来的文件。计算文件的Hash值在这个密码库的支持下就比较简单就用下面的一行代码就行了

FileSource f(file, true, new HashFilter(md5,

                new HexEncoder(new ArraySink(buffer,2 * MD5::DIGESTSIZE))));

这一行代码总共用了4个类ArraySink、HexEncoder、HashFilter和FileSource。首先用类ArraySink复制一个2 * MD5::DIGESTSIZE 字节的buffer存储缓冲区,接着用类HexEncoder把这个缓冲区转换为16进制。计算Hash值主要用到类HashFilter。类FileSource是把要计算Hash值的文件file进行一定的转换放入临时缓冲区,然后调用实例化的HashFilter对其进行计算相应Hash函数的Hash值。

对称密码的应用

我们说明DES的编程。DES有四种工作模式:电子密码本模式(electronic codebook mode),密码分组链接模式(cipher block chaining mode),密码反馈模式(cipher feedback mode)以及输出反馈模式(output feedback mode)。

应用对称密码首先我们要确定用那种工作模式,即用ECB, CBC, CFB和OFB中的那种模式。Crypto++提供的工作模式对象,其本质上是把分组密码(block cipher)转换成序列密码(stream cipher)。下面就是创建工作模式CFB的例子:

byte key[AES::DEFAULT_KEYLENGTH], iv[AES::BLOCKSIZE];
CFB_Mode::Encryption cfbEncryption(key, AES::DEFAULT_KEYLENGTH, iv);

其中iv 是一个增量值,可以随便取一个字符串。

知道什么创建工作模式后我们就通过具体的例子来研究对称密码的用法。下面我们来看高级加密标准AES在工作模式CFB下的简单应用。

string AESEncryptString(const char *instr, const char *passPhrase) // AES加密字符串函数{


    std::string outstr;

    byte iv[AES::BLOCKSIZE]="123456";

    AES::Encryption aesEncryption((byte *)passPhrase, AES::DEFAULT_KEYLENGTH);

CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv);

    StreamTransformationFilter 

cfbEncryptor(cfbEncryption, new HexEncoder(new StringSink(outstr)));

    cfbEncryptor.Put((byte *)instr, strlen(instr));

    cfbEncryptor.MessageEnd();

    return outstr;

}

string AESDecryptString(const char *instr, const char *passPhrase)// AES解密字符串函数{


    std::string outstr;

    byte iv[AES::BLOCKSIZE]="123456";

    CFB_Mode::Decryption 

cfbDecryption((byte *)passPhrase, AES::DEFAULT_KEYLENGTH, iv);

    HexDecoder 

decryptor(new StreamTransformationFilter(cfbDecryption, new StringSink(outstr)));

    decryptor.Put((byte *)instr, strlen(instr));

    decryptor.MessageEnd();

    return outstr;

}

在应用这两个函数时要加三个头文件 aes.h、hex.h和modes.h。

加密函数string AESEncryptString(const char *instr, const char *passPhrase)中参数instr是要加密的字符串,passPhrase是密钥。这个函数的基本流程为:先用密钥passPhrase初始化一个AES的加密对象aesEncryption,然后用aesEncryption和增值量iv创建一个加密的CFB工作模式,iv是可以随便取一个字符串,但是要注意加密使用的iv要和解密的一样,否则解密不了。这里我们用了一个流过滤器StreamTransformationFilter对工作模式进行包装, StreamTransformationFilter可以作为一个Filter对象。StreamTransformationFilter将在需要的时候将缓冲区数据阻塞。为了让输出的密文比较直观,我们在处理输出时用十六进制输出,所以我们在这里用了转换为十六进制的类HexEncoder。方法Put()是对输入进行处理,然后调用上面的加密对象对字符串进行加密,方法MessageEnd()是输入的结束性标志。

解密函数string AESDecryptString(const char *instr, const char *passPhrase) 中参数instr是要解密的密文,passPhrase是密钥。解密函数的基本流程和加密的差不多,只是用到的类和加密的是相对的。用密钥passPhrase和iv创建一个AES解密的CFB工作模式对象cfbDecryption,然后用流过滤器StreamTransformationFilter对工作模式进行包装,用转化十六进制为byte型的类HexDecoder对对象进行转化得出对象decryptor,再调用方法Put()对输入进行处理,然后调用上面的加密对象对字符串进行解密。

现在我们就用这两个函数对字符串“贵州大学计算机软件与理论研究所 Guizhou University”进行加解密,密钥我们用“guizhoudaxue”,在vc6编译平台下,运行结果为:






由于AES加密速度比较快、效率高而且比较安全,所以我们通常用来对文件进行加解密,下面我们就来看加解密文件的例子。
void AESEncryptFile(const char *in, const char *out, const char *passPhrase)//加密文件

{

       byte iv[AES::BLOCKSIZE]="123456";

    AES::Encryption aesEncryption((byte *)passPhrase, AES::DEFAULT_KEYLENGTH);

       CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv);

       FileSource

 f(in, true, new StreamTransformationFilter(cfbEncryption, new FileSink(out)));

}

void AESDecryptFile(const char *in, const char *out, const char *passPhrase)//解密文件

{

       byte iv[AES::BLOCKSIZE]="123456";

    CFB_Mode::Decryption cfbDecryption((byte *)passPhrase, 16, iv);

       FileSource 

  f(in, true, new StreamTransformationFilter(cfbDecryption, new FileSink(out)));      

}

在应用这两个函数时要加四个头文件 aes.h、hex.h、files.h和modes.h。

加密函数void AESEncryptFile(const char *in, const char *out, const char *passPhrase)中参数in是要加密的文件名,out是要解密的文件名,passPhrase是密钥。这个函数的基本流程为:先用增量值iv和密钥passPhrase创建一个AES加密的CFB工作模式对象aesEncryption。

下面来看在工作模式CBC下用DES-EDE对字符串加解密的简单例子。下面给出两个函数。

string EncryptString(const char *instr, const char *passPhrase){ //加密函数

       string outstr;

       DefaultEncryptorWithMAC  //生成对象

encryptor(passPhrase, new HexEncoder(new StringSink(outstr)));

       encryptor.Put((byte *)instr, strlen(instr)); encryptor.MessageEnd(); return outstr;

}

string DecryptString(const char *instr, const char *passPhrase){ //解密函数

       string outstr;

       HexDecoder 

decryptor(new DefaultDecryptorWithMAC(passPhrase, new StringSink(outstr)));

       decryptor.Put((byte *)instr, strlen(instr));     decryptor.MessageEnd();      return outstr;

}

加密函数string EncryptString(const char *instr, const char *passPhrase) 中instr是要加密的字符串,passPhrase是用来加密的密钥。这个函数用了密码库里的四个类DefaultEncryptorWithMAC、HexEncoder和StringSink。StringSink 是类StringSinkTemplate的一个实例化,主要作用是添加输入到一个字符串对象。HexEncoder在hex.h里定义是用来转换所给的数据为十六进制。DefaultEncryptorWithMAC在default.h里定义,是用DES-EDE2 和 HMAC/SHA-1 在密钥下进行加密,Put()和MessageEnd()是这个类的两个基本的方法。unsigned int Put (const byte *inString, unsigned int length, bool blocking=true)是用来处理输入多重的字节,bool MessageEnd (int propagation=-1, bool blocking=true)用来作为输入消息的结束标志。这个函数的基本流程是:首先用类StringSink 把outstr添加到一个String对象,接着用HexEncoder把这个对象转换为十六进制。然后用加密密钥passPhrase产生一个DefaultEncryptorWithMAC对象encryptor,最后调用encryptor的方法Put()来处理输入instr进而对其进行加密,把加密后的密文放到outstr。

解密函数string DecryptString(const char *instr, const char *passPhrase) 中instr是要解密的字符串,passPhrase是用来解密的密钥,跟加密的密钥要相同。也用了三个类HexDecoder、DefaultDecryptorWithMAC和StringSink。HexDecoder是把给定的十六进制数据转换成为byte型。DefaultDecryptorWithMAC 也是定义在default.h文件里与类DefaultEncryptorWithMAC相应的是用来解密。这个函数的基本流程是:首先用类StringSink 把outstr添加到一个String对象,然后用解密密钥passPhrase产生一个DefaultDecryptorWithMAC对象,利用类HexDecoder对DefaultDecryptorWithMAC对象进行数据转换生成对象decryptor,然后利用decryptor的方法Put()进行输入处理,进而进行解密,把解密后的明文放到outstr。