感觉程序员学密码学不把一个库玩的很6是学不好也用不了密码学的,对crypto++而言,看源码
暂时是看不懂也看不完的,只能硬着头皮看官方文档,本人英文不是很好,如有错误请直接指出。
Base Classes
Filter
译文start
Filter是一个抽象基础类继承自BufferedTransformation.它的公共接口和他的父类相同;
但是它实现了 attachment 功能。在BufferedTransformation中 attachment 只是声明但是没有实现
译文end
学习笔记
这里出现了一个名词 抽象类,找了篇文章http://www.cnblogs.com/dongsheng/p/3343939.html
说说 抽象类 的要点吧
包含纯虚函数的类称为抽象类
不能定义抽象类的对象(个人猜测和虚表有关)
存在的意义是被继承
在filter类中这个只定义没有实现的虚函数就是virtual BufferedTransformation * NewDefaultAttachment() const;
//这里代码不全,只粘要点
class CRYPTOPP_DLL CRYPTO_NO_VTABLE Fileter:BufferedTransformation,public NotCapyable{
Filter(BufferedTransformation *attachment = NULL);
bool Attachable() {return true;}
BufferedTransformation *AttachedTransformation();
const BufferedTransformation *AttachedTransformation() const;
void Detach(BufferedTransformation *newAttachment = NULL);
protected:
virtual BufferedTransformation * NewDefaultAttachment() const;
}
译文start
有个可行的方法来区分一个Filter和BufferedTransformation对象通过调用Attachable()方法
如果对象是一个Filter,方法将会返回true,如果是BufferedTransformation则返回false
(注:通过定义新类继承Filter和BufferedTransformation,译者测试的确如此,这里不就贴代码了,
vs神器不是吹的)
Attachment(译成 附着)是一个先进并且实用的概念,通过filters和它们的依赖功能,可以用相关的少量代码
优雅的实现很多东西
当一个继承自BufferedTransformation的对象B,附着于一个继承自Filter的对象F,当数据通过Put()方法发送到F,
F将处理数据,然后通过B的Put()函数把结果转发到B. 当F调用任何的Get()方法,F将简单的转发到B,并返回B的返回值.
如果B是其他继承自Filter的对象,它也会同样如此,这形成一个附着链,这个附着链一定以一个
BufferedTransformation结束,而不是Filter.
(注:在Filter中没有实现Put() 和 Get(),BufferedTransformation实现了Put() 和 Get())
这非常简单. 而且很神奇!看例子
char const* zInputFile=...;
char const* zOutputFile=...;
SHA hash;
FileSource(zInputFile,true,new HashFilter(hash,new FileSink(zOutputFile),true));
上述代码通过FileSouce打开被zInputFile指定的文件,通过HashFilter把该文件传送给SHA hash模块,并且通过
FileSink存储原来的数据和计算得到的摘要到zOutpuFile指定的文件中(译注:该文件为新建文件),如果在最后一行的
true 参数被省略掉,缺省的false将会应用,那么输出文件不会保存原来数据,只会有原来数据的消息摘要
译文end
附着方法(Attachment methods)
译文start
构造函数.所有从继承自Filter的类和Filter类本身,都有一个BufferedTransformation*类型的参数
这个参数指定了一个指针,这个指针指向一个继承自BufferedTransformation对象,这个对象附着于(attach)
那个即将由构造函数构造的对象.
一旦附着关系开始,附着目标对象拥有指向被用来附着的对象指针,一旦附着目标对象被摧毁,
被用作附着的对象会自动被释放.
当调用构造函数时,如果被用来附着的对象没有被指定或者传递了一个空指针,那么一个预先确定的对象会被创建
一般来说,会创建一个MessageQueue对象.一个MessageQueue对象将会储存所有它从Put()方法获取的数据,这些
数据之后可以通过Get()方法获得,它Put()方法和Get()方法所获取的数据的顺序相同。
Attach().附着另外一个transformation对象到 附着链 的尾部
Detach().删除当前的附着链,摧毁并且释放它包含的所有对象,然后附着指定的对象,如果传递的是个空指针,
那就创建一个默认对象
AttachedTransformation().返回一个指向当前被用作附着的对象,不能是NULL
// 和之前那个例子类似,但是没有使用sink
// HashFilter创建一个MessageQueue附着对象
// 通过Get()提取消息摘要
char const* zInputFile = ...;
char const* zOutputFile = ...;
SHA hash;
FileSource source(zInputFile, true, new HashFilter(hash));
byte abDigest[SHA::DIGESTSIZE];
if (source.Get(abDigest, sizeof(abDigest)) != sizeof(abDigest))
throw "shouldn't happen";
使用Deatach()和Attach()
// 在对象创建时期,不抽取(pump)任何东西,而不是立即抽取(pump)整个文件(在FileSource中使用false参数,
// 而不是之前的true)
string sEncoding;
FileSource source(zInputFile, false, new StringSink(sEncoding));
//source.Pump(3);这句译者者测试时报错(vs2017 & win10)
// 再附着上FileSink, 最后写入文件
// 写入的文件应该是16进制或者base64encode
source.Detach(new HexEncoder);
source.Attach(new FileSink(zOutputFile));
source.PumpAll();
译文end
Sink
译文start
不像Source,Sink抽象基础类继承自BufferedTransformation.在一个filters**附着链**中,sink
总是在链中的最后一个对象:
示例:将一个文件中的内容读取到一个字符串中
char const* zInputFile="temp.txt";
string content;
FileSource source(zInputFile,true,new StringSink(content));
cout<<content;
(译者注:继承关系:FileSink->Sink->BufferdTransformation,FileSource->Source->Filter)
示例:把哈希值存入一段缓存区中
string sData="Hello CryptoPP";
byte abDigest[SHA::DIGESTSIZE];
SHA sha;
StringSource source(sData,true,
new HashFilter(sha,
new ArraySink(abDigest,sizeof(abDigest))));
(译注:继承关系:StringSource->Source->Filter,ArraySink->Sink->BufferedTransformation)
译文end
派生类
MeterFilter,TransparentFilter,OpaqueFilter
StreamCiherFilter
略
HashFilter,HashVerifier
(译注:HashFilter->Filter)
HashFilter被消息摘要算法初始化,HashFilter使用这个算法来计算素所有输入数据的哈希值,直到第一个
MessageEnd()信号,当它遇到MessageEnd()信号时,它把计算所得的哈希值输出到它的附着transformation
HashFilter会根据初始化参数决定在输出哈希值前是否把数据输入到附着transformation.
一旦 MessageEnd(), 被指向这个消息摘要就被重置并且可以处理另外一条消息.
HashVerifier是一个灵活的filter,它处于验证输入消息的摘要的目的封装一个消息摘要算法.
有很多标志可以被设置在HashVerifier初始化的时候,这依赖于哈希值将会被装载到哪(消息的起始还是结束),
无论消息,依赖于消息和哈希值是否会被传送到附着transformation,依赖于验证结果是否被传送到,附着transformaiton
以及异常是否会排除如果摘要验证失败。
char const* zInputFile = ...;
char const* zOutputFile = ...;
SHA hash;
FileSource(zInputFile, true,
new HashFilter(hash,
new FileSink(zOutputFile),
true));
// The last 'true' parameter means that the whole message
// will be forwarded to FileSink, not just the calculated hash.
// If omitted, the default value would be 'false'.
SignerFilter,VerifierFilter
SignerFilter一般而言是一个基本类,它封装一个PK_Signer派生类来应用一个数字签名到输入数据,
只有数字签名被传送到附着transformation.
Verifier一般而言也是一个基础类封装一个PK_Signer派生类来验证一个输入数据的数字签名,这个数字签名背身必须
通过PutSignature()方法传送给VerifierFilter对象
在实际中,在PK_Signer和PK_Verifier对象上分别使用SignMessage()和VerifyMessage()方法
通常更简单
AutoSeededRandomPool rng;
// The below type is derived from PK_Signer
RSASSA_PKCS1v15_SHA_Signer privkey = ...;
char const* zInputFile = ...;
string sSignature;
FileSource(zInputFile, true,
new SignerFilter(rng, privkey,
new StringSink(sSignature)));
// sSignature now contains the digital signature computed on the
// contents of the input file using SHA and RSA
Redirector
Redirector是一个Sink,它在附着链的末尾,但是传递输入数据到另外一条附着链,使用Redirector和使用普通的附着
之间的不同是Redirector并不游泳它的附着transformatuion,它不会摧毁并能切释放附着对象一旦它被摧毁
示例:连接文件
void ConcatenateFiles(BufferedTransformation& bt)
{
char const* zInputFile1 = ...;
char const* zInputFile2 = ...;
char const* zInputFile3 = ...;
// Concatenate the three files into the same BufferedTransformation object.
// Only allow the MessageEnd() signal to be passed into bt at the end
// of the last file.
FileSource(zInputFile1, true, new Redirector(bt, false));
FileSource(zInputFile2, true, new Redirector(bt, false));
FileSource(zInputFile3, true, new Redirector(bt));
}
...
string sConcatenated;
ConcatenateFiles(StringSink(sConcatenated));
ArraySink
ArraySink是一个用来把数据存进一个预先定好大小的缓存区;已经存储的字节数和还能使用的空间可以通过
AvailableSize()方法和TotalPutlength()确定.
示例:将一个哈希值存入一段缓存区
string sData = ...;
byte abDigest[SHA::DIGESTSIZE];
SHA sha;
StringSource(sData, true,
new HashFilter(sha,
new ArraySink(abDigest, sizeof(abDigest))));
StringSinkTemplate,StringSink
StringSinkTemplate是一个Sink模板,它把数据存储到任何派生自std::basic_string的string类型
StringSink是一个 StringSinkTemplate的typedef
当StirngSink使用一个非空目标字符串初始化,目标字符串会被添加上去;原先的内容保持不变
StringSource
StringSource是一个Source,它从一个Ascii字符串或者一个字符串缓存区中提取字符串