crytoppp库分析-base

//BASE的编码、解码

// basecode.cpp - written and placed in thepublic domain by Wei Dai

#include "pch.h"

#ifndef CRYPTOPP_IMPORTS

#include "basecode.h"
#include "fltrimpl.h"
#include

NAMESPACE_BEGIN(CryptoPP)

//编码类的独立初始化,传入参数集

void BaseN_Encoder::IsolatedInitialize(constNameValuePairs ¶meters)
{
//参数集对象的初始化

//classCRYPTOPP_NO_VTABLE NameValuePairs

parameters.GetRequiredParameter("BaseN_Encoder",Name::EncodingLookupArray(), m_alphabet);

parameters.GetRequiredIntParameter("BaseN_Encoder",Name::Log2Base(), m_bitsPerChar);

//m_bitsPerChar为一次参与BASE编码的2进制位数,必须在1-7之间
if (m_bitsPerChar <= 0 || m_bitsPerChar >=8)
throwInvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7inclusive");

//填充符

byte padding;
bool pad;
if (parameters.GetValue(Name::PaddingByte(),padding))
pad =parameters.GetValueWithDefault(Name::Pad(), true);
else
pad = false;
m_padding = pad ? padding : -1;

m_bytePos = m_bitPos =0;

//计算输出缓冲区大小(BYTE为单位),并申请缓冲区

//因为以8位为单位,所以凑成能被BASE基数的位数m_bitsPerChar整除的最小数

int i = 8;
while (i%m_bitsPerChar != 0)
i += 8;

//计算缓冲区大小,以字节为单位
m_outputBlockSize = i/m_bitsPerChar;

//申请缓冲区

m_outBuf.New(m_outputBlockSize);
}

 

//BASEN的编码函数(如BASE64、BASE32等等)

size_t BaseN_Encoder::Put2(const byte *begin,size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
while (m_inputPosition < length)

//while (m_inputPosition< length)开始
{

if (m_bytePos ==0)

//初始化输出缓冲区全部置0,以开始新一轮
memset(m_outBuf,0, m_outputBlockSize
);

{

 

//m_inputPosition移一个字节,取编码源流begin中的当前需要处理位置的字节b

//开始新一轮处理,以将该字节处理后所余下位数不够处理或正好处理完毕为一轮

//注意unsignedint在32位系统中,有32位大小,但m_inputPosition

//以一个字节为单位移动

unsignedint b = begin[m_inputPosition++], bitsLeftInSource = 8;

//bitsLeftInSource为源本次需要处理的位数,初值为8

//在b中以BASE基数的位数为单位扩展后填充8位缓冲区=====begin

//处理源和目标,将源以BASE基数要求的位数为单位拆开后,放入输出缓冲区

//的每个字节内,如BASE64则把源二进制流以6位为单位,放入每个字节中,

//一个字节还有2位暂时没用到,从源二进制流中每次取8位进行处理,这

//是必要的,因为要以字节为单位访问内存

while(true)

//while(true)循环开始
{

//确保m_bitPos在BASE基数位数之内

assert(m_bitPos < m_bitsPerChar);

 


//m_bitPos为上次应处理但未处理只能移交本次处理的位数,因为上次位数

//太少无法处理,如:BASE64,第一次顺利处理6位;第二次要处理2位,因为

//每次必须处理6位,所以第二次将b中2位移至最左边;然后,将b右移8-6=2

//位保存在m_outBuf[m_bytePos]中,然后进行判断发现无法完成处理,只能

//在第三从begin取一个字节放入b中,读入b中的最左4位新的二进制,

//放入m_outBuf[m_bytePos]的最右边。

//m_bitsPerChar为BASE的基数(如BASE64为6),即每个字母代表几位二进制数

//bitsLeftInTarget为输出缓冲区本次能够接受的位数,也是源本次能够处理的位数

//bitsLeftInSource为源本次需要处理的位数

//因为上次几位无法处理,所以需要本次一起处理

unsignedint bitsLeftInTarget = m_bitsPerChar-m_bitPos;


//输出缓冲区为m_outBuf,大小为m_outputBlockSize字节

//m_bytePos为输出目标当前位置(以字节为单位)

//m_outBuf是个字节为单位的块

//操作为:从b的左边开始,取bitsLeftInTarget

//将输出缓冲区m_outBuf的当前字节的后bitsLeftInTarget位(如BASE64为后6位)

//设为源的当前字节b能够处理的二进制数(如BASE64为6位二进制数)

//b为当前需要处理的源数据,先处理输出缓冲区

m_outBuf[m_bytePos]|= b >> (8-bitsLeftInTarget);//b本身没未改变

//再进行判断,原因是上次无法处理的几位先给予m_outBuf[m_bytePos],以免丢失
if(bitsLeftInSource >= bitsLeftInTarget)
{

//源本次需要处理的位数大于或等于输出缓冲区本次能够接受的位数,即

//有几位本次未能处理完毕或者正好已经处理完了

//如:BASE64,第一次处理时源肯定还有2位没有处理

//m_bitPos置0,因为当前位能顺利处理完,不需要移交给下次处理

  m_bitPos = 0;

//当前bitsLeftInTarget位处理完毕,输出缓冲区进入

//下一字节进行下次处理

++m_bytePos;


//更新下次源需要处理的位数为源本次没有处理完的位数

bitsLeftInSource-= bitsLeftInTarget;

if (bitsLeftInSource== 0)

//下次源需要处理的位数为0,退出while(true)循环,进行BASE编码
break;

//将已经处理的位左移出b,仅留未处理的位以给下次处理

b<<= bitsLeftInTarget;

//使用0xff掩码,只保留b的右8位,因为b有32位
b&= 0xff;
}
else
{

//源本次需要处理的位数小于输出缓冲区本次能够接受的位数,不能进行处理

//说明源的本次位数太少,满足不了输出缓冲区接收的需要,读入新的二进制流

 

//bitsLeftInSource位需要移交给下次处理,更新源的未能处理的位数

//将m_bitPos设为源本次未处理位数m_bitPos加本次需要处理但不能进行处

//理的位数。m_bytePos不能改变,因为m_outBuf[m_bytePos]还有几位没处理完

m_bitPos+= bitsLeftInSource;

//退出while(true)循环

break;
}
}

}

//while(true)结束

//在b中以BASE基数的位数为单位扩展后填充8位缓冲区=====end

//确保缓冲区的当前位置是在缓冲区容量之内

assert(m_bytePos <=m_outputBlockSize);

 

//如果源已经读完且缓冲区填充完毕,进行BASE转换=====begin

//有种情况在下一步考虑,就是:缓冲区没有填充完,但是源已经读完

 if (m_bytePos == m_outputBlockSize)
{

//输出缓冲区已经填充完毕

//注意此时输出缓冲区内仅为待转换为字母表中相关字母的数,

 //如BASE64,则仅为1-64之间的数。
inti;

 //下面的循环条件为什么不是i<=m_bytePos,原因在于

//缓冲区的大小是BASE基数位数的倍数,所以只要缓冲区能填充满

 //最后一定正好遇到下次源需要处理的位数为0,退出while(true)

//循环的情况而退出,但++m_bytePos在退出前就已经执行。
for (i=0;i
{
//确保输出缓冲区每个数都在BASE基数所能表达的最大范围内

assert(m_outBuf[i]< (1 << m_bitsPerChar));

//进行编码转换
m_outBuf[i]= m_alphabet[m_outBuf[i]];
}

 //输出缓冲区内容
FILTER_OUTPUT(1,m_outBuf, m_outputBlockSize, 0);
m_bytePos =m_bitPos = 0;//m_bytePos设为0后,可激活生成新的缓冲区
}

//如果缓冲区填充完毕,进行BASE转换=====end


}//while(m_inputPosition < length)结束,至此完成源的BASE编码

//m_inputPosition==length时,源全部读取完毕,需要加消息尾部
if (messageEnd)
{

//处理消息尾部的填充符

 if (m_bitPos > 0)

//结束时,源中还有余位,证明属于缓冲区未填满就已经源已经读完,而此时

//++m_bytePos必须补上,因为后面的for循环不是i<=m_bytePos
++m_bytePos;

//缓冲区没有填充完,但是源已经读完

//将缓冲区中的源转换

int i;
for (i=0; i
m_outBuf[i] =m_alphabet[m_outBuf[i]];

//如果有填充符且源中还有余位

if(m_padding != -1 && m_bytePos > 0)
{
memset(m_outBuf+m_bytePos,m_padding, m_outputBlockSize-m_bytePos);
m_bytePos =m_outputBlockSize;
}

//将缓冲区内容输出
FILTER_OUTPUT(2, m_outBuf,m_bytePos, messageEnd);
m_bytePos = m_bitPos = 0;
}
FILTER_END_NO_MESSAGE_END;
}

//解码类的独立初始化

void BaseN_Decoder::IsolatedInitialize(constNameValuePairs ¶meters)
{
//参数集初始化

parameters.GetRequiredParameter("BaseN_Decoder",N

ame::DecodingLookupArray(),m_lookup);

parameters.GetRequiredIntParameter("BaseN_Decoder",Name::Log2Base(), m_bitsPerChar);
if (m_bitsPerChar <= 0 || m_bitsPerChar >=8)
throwInvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7inclusive");

m_bytePos = m_bitPos =0;

//计算缓冲区大小

int i = m_bitsPerChar;
while (i%8 != 0)
i += m_bitsPerChar;
m_outputBlockSize = i/8;

m_outBuf.New(m_outputBlockSize);
}

//BASE解码函数

size_t BaseN_Decoder::Put2(const byte *begin,size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;

//while(m_inputPosition <length)==begin
while(m_inputPosition < length)
{

//m_inputPosition为当前位置,length为源总长度
unsigned int value;
//取源的当前字节所指向的字母代表的整数,m_lookup为字母表的反查表

//m_lookup的声明:constint *m_lookup。将BASE解码后的值取到value中

value =m_lookup[begin[m_inputPosition++]];

//当BASE的基数为7位,字母能代表最大的整数小于256

if(value >= 256)
continue;

if (m_bytePos == 0&& m_bitPos == 0)//申请新缓冲区
memset(m_outBuf,0, m_outputBlockSize);

crytoppp库分析-base

//粘的工作涉及到2个字节,缓冲区第二个字节填充value的移位位数

//的计算为16-newBitPos如上图所示,将前2个字节的(n+n)位粘

//在一起,一定在第2个字节内空出16-newBitPos位,这也是移位位数

{

//m_bitbos为m_outBuf当前已经填充了字节的位数

//newBitPos为m_outBuf当前字节已经填充的位数与本次需要BASE基数

//的位数之和,实际意义在于检测当前字节还余下多少空间,是否能容

//下需要处理的位数

//m_bitsPerChar为BASE基数的位数
int newBitPos= m_bitPos + m_bitsPerChar;

 

if(newBitPos <= 8)

//当前字节余下的空间能满足本次需要处理的位数,可以继续处理
m_outBuf[m_bytePos]|= value << (8-newBitPos);
else
{

//当前字节余下的空间不能容下本次需要处理的位数,需要分次在m_outBuf的

//当前字节和下一字节的空间处理,即粘

//第一次先取填充value的左边,直至把当前字节余下的空间填满为止

m_outBuf[m_bytePos] |= value >>(newBitPos-8);

//第一次先取填充value的右边,把右边部分放置于m_outBuf下一字节的前部

m_outBuf[m_bytePos+1]|= value << (16-newBitPos);
}

 

//更新m_bitPos为m_outBuf当前已经填充了字节的位数,

m_bitPos= newBitPos;

 

//计算当前的m_bytePos值,因为本次循环至此为止,m_bytePos并没有

//改变,而m_outBuf的下一字节已经开始填充了。m_bitPos也应重新更新,

//因为m_outBuf当前字节已经填充了几位

while(m_bitPos >= 8)
{
m_bitPos-= 8;
++m_bytePos;
}
}

//缓冲区正好填充满

if(m_bytePos == m_outputBlockSize)
{
FILTER_OUTPUT(1,m_outBuf, m_outputBlockSize, 0);
m_bytePos = m_bitPos =0;//为缓冲区重新初始化作准备

}

}

//while (m_inputPosition <length)==end

//输出缓冲区的消息尾部
if (messageEnd)
{
FILTER_OUTPUT(2, m_outBuf,m_bytePos, messageEnd);
m_bytePos = m_bitPos = 0;
}
FILTER_END_NO_MESSAGE_END;
}

 

乐智小天地——免费索取巧虎新体验VCD!

panelpower——参加调查,丰厚奖金回报!

华尔街英语——免费拿运动英语手册!

//CPP文件,接(2)

//BASEN解码类的初始化解码数组

//lookup为解码数组,base为字母表大小,caseInsensitive大小写是否敏感

voidBaseN_Decoder::InitializeDecodingLookupArray(int *lookup, constbyte *alphabet, unsigned int base, bool caseInsensitive)
{
std::fill(lookup, lookup+256, -1);

for (unsigned int i=0;i<base; i++)
{
if (caseInsensitive &&isalpha(alphabet[i]))
{

//忽略大小写
assert(lookup[toupper(alphabet[i])]== -1);
lookup[toupper(alphabet[i])]= i;
assert(lookup[tolower(alphabet[i])]== -1);
lookup[tolower(alphabet[i])]= i;
}
else
{

//大小写有别
assert(lookup[alphabet[i]]== -1);
lookup[alphabet[i]]= i;
}
}
}

//Grouper类独立初始化

void Grouper::IsolatedInitialize(constNameValuePairs &parameters)
{
m_groupSize =parameters.GetIntValueWithDefault(Name::GroupSize(), 0);
ConstByteArrayParameter separator,terminator;
if (m_groupSize)
parameters.GetRequiredParameter("Grouper",Name::Separator(), separator);
else
parameters.GetValue(Name::Separator(),separator);
parameters.GetValue(Name::Terminator(),terminator);

m_separator.Assign(separator.begin(),separator.size());
m_terminator.Assign(terminator.begin(),terminator.size());
m_counter = 0;
}

//Grouper类的编码

size_t Grouper::Put2(const byte *begin, size_tlength, int messageEnd, bool blocking)
{
FILTER_BEGIN;
if (m_groupSize)
{
while (m_inputPosition <length)
{
if (m_counter== m_groupSize)
{

//组空间满,输出m_separator缓冲区
FILTER_OUTPUT(1,m_separator, m_separator.size(), 0);
m_counter= 0;
}

size_tlen;
FILTER_OUTPUT2(2,len = STDMIN(length-m_inputPosition, m_groupSize-m_counter),
begin+m_inputPosition,len, 0);
m_inputPosition+= len;
m_counter +=len;
}
}
else

//最后一个组的输出
FILTER_OUTPUT(3, begin, length,0);

if (messageEnd)
{
FILTER_OUTPUT(4, m_terminator,m_terminator.size(), messageEnd);
m_counter = 0;
}
FILTER_END_NO_MESSAGE_END
}

NAMESPACE_END

#endif

//CRYPTOPP头文件

#ifndef CRYPTOPP_BASECODE_H
#define CRYPTOPP_BASECODE_H

#include "filters.h"
#include "algparam.h"
#include "argnames.h"

NAMESPACE_BEGIN(CryptoPP)

//! base n encoder, where n is a power of2

//继承关系:

//Unflushable<Filter>->BaseN_Encoder

//Unflushable<Filter>->BaseN_Decoder

//Bufferless<Filter>->Grouper


class CRYPTOPP_DLL BaseN_Encoder : publicUnflushable<Filter>
{
public:
BaseN_Encoder(BufferedTransformation*attachment=NULL)
{Detach(attachment);}

BaseN_Encoder(const byte*alphabet, int log2base, BufferedTransformation *attachment=NULL,int padding=-1)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(),alphabet)
(Name::Log2Base(),log2base)
(Name::Pad(),padding != -1)
(Name::PaddingByte(),byte(padding)));
}

voidIsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, intmessageEnd, bool blocking);

private:
const byte *m_alphabet;
int m_padding, m_bitsPerChar,m_outputBlockSize;
int m_bytePos, m_bitPos;
SecByteBlock m_outBuf;
};

//! base n decoder, where n is a power of2
class CRYPTOPP_DLL BaseN_Decoder : publicUnflushable<Filter>
{
public:
BaseN_Decoder(BufferedTransformation*attachment=NULL)
{Detach(attachment);}

BaseN_Decoder(const int*lookup, int log2base, BufferedTransformation*attachment=NULL)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(),lookup)(Name::Log2Base(), log2base));
}

voidIsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, intmessageEnd, bool blocking);

static void CRYPTOPP_APIInitializeDecodingLookupArray(int *lookup, const byte *alphabet,unsigned int base, bool caseInsensitive);

private:
const int *m_lookup;
int m_padding, m_bitsPerChar,m_outputBlockSize;
int m_bytePos, m_bitPos;
SecByteBlock m_outBuf;
};

//! filter that breaks input stream intogroups of fixed size

//将输入流分成固定大小的块
class CRYPTOPP_DLL Grouper : public Bufferless<Filter>
{
public:
Grouper(BufferedTransformation*attachment=NULL)
{Detach(attachment);}

Grouper(int groupSize, conststd::string &separator, const std::string &terminator,BufferedTransformation *attachment=NULL)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::GroupSize(),groupSize)
(Name::Separator(),ConstByteArrayParameter(separator))
(Name::Terminator(),ConstByteArrayParameter(terminator)));
}

voidIsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, intmessageEnd, bool blocking);

private:
SecByteBlock m_separator, m_terminator;
size_t m_groupSize, m_counter;
};

NAMESPACE_END

#endif

你可能感兴趣的:(top)