王朝网络
分享
 
 
 

RC5,RC5-CBC,RC5-CBC-PAD和RC5-CTS算法

王朝other·作者佚名  2008-05-31
宽屏版  字体: |||超大  

本备忘录的状态

本文档讲述了一种Internet社区的Internet标准跟踪协议,它需要进一步进行讨论和建

议以得到改进。请参考最新版的“Internet正式协议标准”(STD1)来获得本协议的标准化

程度和状态。本备忘录的发布不受任何限制。

版权声明

Copyright(C)TheInternetSociety(2001).

目录

1.实现概述 2

2.总览 3

3.术语和符号 3

4.RC5密钥的描述 4

4.1创建一个RC5密钥 4

4.2销毁一个RC5密钥 5

4.3设置一个RC5密钥 5

5.设置一个RC5密钥 6

5.1初始常量定义 7

5.2接口定义 7

5.3转换密钥从字节到字 8

5.4初始化扩展密钥表 8

5.5混合密钥 8

6.RC5块密码的描述 9

6.1加载A和B的值 9

6.2重申轮函数 10

6.3存储A和B的值 10

7.RC5-CBC和RC5-CBC-Pad模式的描述 11

7.1创建密码对象 11

7.2撤消密码对象 12

7.3为密码对象设置初始向量 13

7.5消息的处理部分 14

7.5.1输出缓冲区大小的检查 15

7.5.2将明文分成块 15

7.6最后块的处理 16

8.RC5-CTS的描述 17

9.测试程序和向量 18

9.1测试程序和向量 18

9.2测试向量 22

9.3测试结果 23

10.安全考虑 25

11.ASN.1标识符 26

12.参考 26

13.作者地址 27

1.实现概述

这个文档定义了四种形式的密码算法拥有足够的信息以确保不同实现间的协同工作

能力。第一种是原始的RC5块加密,RC5密码使用固定的输入长度使用一个依靠密钥的转

换产生一个固定长度的输出块。第二种是,RC5-CBC,是RC5的块密码链接模式。它能处

理长度是RC5块尺寸倍数的消息。第三种是,RC5-CBC-Pad,处理任意长度的明文,尽管

密文将比明文长但长度至多长一个RC5块。RC5-CTS密码是RC5算法的密文挪用模式,处

理任意长度的明文且密文的长度匹配明文的长度。

RC5密码是1994由麻萨诸塞技术研究所的RonaldL.Rivest教授发明的。它是一种非

常快速且简单的算法由块尺寸,轮数,和密钥长度参数化。这些参数能被调整以满足不同的

安全目的,性能和出口能力。

合并的RSA数据安全已经归档了RC5密码的专利的申请和RC5,RC5-CBC,

RC5-CBC-Pad,RC5-CTS并分类了各种变更。

2.总览

这个备忘录是对存在的出版资料的重述。RC5的描述是遵从Rivest教授原始的RC5

论文中的符号和解释顺序。CBC模式出现在参考著作中例如BrUCeSchneier写的。CBC-Pad

模式与公钥加密标准(PKCS#5)相同。参考C代码被包括只是为了清楚等同于英语的描述。

密码将以一种倒置的面向对象的风格来解释。首先,RC5密钥将伴随着密钥扩展算

法出现。接着RC5块密码将被解释,最后,将规定RC5-CBC和RC5-CBC-Pad密码。为了

简短,只有加密过程被描述。解密可以通过转化加密的步骤来实现。

此处的面向对象的描述应该使得实现交互性系统更加轻易,尽管并不像参考文献中

的功能描述那样简单。有两个对象类,密钥和密码算法。两个类用同一种方式共享创建和撤

消这些对象的操作确保秘密信息没有被返回给存储治理者。

密钥也拥有一个“set”操作拷贝一个秘密密钥到对象。密码对象的“set”操作定义

了轮数,和初始向量。

在这个备忘录描述了对于密码对象四个操作。绑定一个密钥到密码对象,为每一个

密码对象设置一个新的初始向量没有改变密钥,一个消息的加密部分(对于长的消息要执行

多次),和处理消息的最后一个部分可以进行填充或检查消息的长度。

总之,密码将根据这些操作被解释:

RC5_Key_Create-创建一个密钥对象.

RC5_Key_Destroy-撤消一个密钥的对象.

RC5_Key_Set-绑定一个用户密钥到密钥对象.

RC5_CBC_Create-创建一个密码对象.

RC5_CBC_Destroy-撤消一个密码对象.

RC5_CBC_Encrypt_Init-绑定一个密钥对象到一个密码对象.

RC5_CBC_SetIV-设置一个初始向量不用改变密钥.

RC5_CBC_Encrypt_Update-一个消息的处理部分.

RC5_CBC_Encrypt_Final-消息末尾的处理.

3.术语和符号

术语“Word”指的是一个非凡长度位数的字符串既可以作为一个无符号整数也可以

作为一个位向量。例如一个“word”可以是32位也可以是64位取决于需要的RC5密码块的

的尺寸。一个32位字将产生一个64位的块。为了取得最好的性能RC5子长度应和CPU的寄

存器的长度相匹配。术语“byte”指8位二进制位数。

下面的变量在此备忘录中将以如下定义使用:

W这个变量表示的是RC5以二进制位数计算的字的尺寸。是块尺寸的一半在此备忘录

中字的尺寸采用的是32和64。

WW此变量是RC5以字节计算的字尺寸。

B此变量是以位计算的块尺寸。是2倍的字尺寸。当RC5被用作64位的块密码。B是

64,W是32。0<B<257。在简单的代码中,B被用作一个代替密码系统参数的变量,

但是这个使用应该是上下文明显的。

BB此变量是以字节计算的块尺寸。BB=B/8。

b这个变量是密钥的字节长度。B0<=b<256。

K作为一个b个字节长的密钥序列,通过K[0],...,K[b-1]索引。

R此变量是一个内部RC5转换的轮数。0<=R<256。

T此变量是一个扩展密钥表的字数。总是2*(R+1)。1<T<513。

S作为扩展密钥表的字数组,通过S[0],..,S[T-1]索引。

N此变量是明文消息的字节长度。

P作为名文消息以一个N字节数组形式存储,通过P[0],..,P[N-1]索引。

C作为密文输出以一个字节数组形式存储,通过C[0],C[1],...索引。

I作为CBC模式的初始向量以一个字节数组形式存储,通过I[0],..,I[BB-1]索引。

4.RC5密钥的描述

像大多数密码块,RC5将一个小的用户密钥扩展为一个内部密钥表。用户密钥的字节

长度是密码的参数之一。因此RC5的用户密钥对象必须能拥有可变长度密钥。一个C的可能

的结构是:

/*RC5的用户密钥对像的定义.*/

typedefstructrc5UserKey

{

intkeyLength;/*InBytes.*/

unsignedchar*keyBytes;

}rc5UserKey;

对密钥的基本操作是创建,销毁和设置。为了避免将密钥资料暴露给一个应用的其他

部分,,密钥的销毁操作应该在将分配给密钥的空间释放给存储治理者之前将该存储空间置

零。一个一般的密钥对象可以支持其他的操作像产生一个新的随机密钥和从协商的密钥信息

中获取密钥。

4.1创建一个RC5密钥

创建一个密钥,密钥对象的存储空间必须被分配和初始化。下面的C代码假设一个

称作“malloc”的函数将从堆返回一个未初始化的存储空间块,或0指出一个错误。

/*分配和初始化一个RC5用户密钥.

*假如有问题返回0.

*/

rc5UserKey*RC5_Key_Create()

{

rc5UserKey*pKey;

pKey=(rc5UserKey*)malloc(sizeof(*pKey));

if(pKey!=((rc5UserKey*)0))

{

pKey->keyLength=0;

pKey->keyBytes=(unsignedchar*)0;

}

return(pKey);

}

4.2销毁一个RC5密钥

为了销毁一个密钥,存储空间必须被置零和被释放给一个存储治理者。以下C代码

假设称作“free”的函数将返回一个存储块给堆。

/*置零且释放一个RC5用户密钥.

*/

voidRC5_Key_Destroy(pKey)

rc5UserKey*pKey;

{

unsignedchar*to;

intcount;

if(pKey==((rc5UserKey*)0))

return;

if(pKey->keyBytes==((unsignedchar*)0))

return;

to=pKey->keyBytes;

for(count=0;count<pKey->keyLength;count++)

*to++=(unsignedchar)0;

free(pKey->keyBytes);

pKey->keyBytes=(unsignedchar*)0;

pKey->keyLength=0;

free(pKey);

4.3设置一个RC5密钥

设置一个密钥对象将密钥拷贝到一个从堆分配的存储空间。

/*设置RC5用户密钥的值.

*拷贝密钥字节以便调用者能置零和释放原来的值.

*假如出现问题返回0

*/

intRC5_Key_Set(pKey,keyLength,keyBytes)

rc5UserKey*pKey;

intkeyLength;

unsignedchar*keyBytes;

{

unsignedchar*keyBytesCopy;

unsignedchar*from,*to;

intcount;

keyBytesCopy=(unsignedchar*)malloc(keyLength);

if(keyBytesCopy==((unsignedchar*)0))

return(0);

from=keyBytes;

to=keyBytesCopy;

for(count=0;count<keyLength;count++)

*to++=*from++;

pKey->keyLength=count;

pKey->keyBytes=keyBytesCopy;

return(1);

}

5.设置一个RC5密钥

这部分描述了密钥扩展算法。作为非凡的定义,示例代码假设块的大小为64位。几

个编程参数依靠于块大小。

/*定义RC5为一个64位块密码.*/

/*The"unsignedint"willbe32bitsonallbut*/

/*theoldestcompilers,whichwillmakeit16bits.*/

/*OnaDECAlpha"unsignedlong"is64bits,not32.*/

#defineRC5_WORDunsignedint

#defineW(32)

#defineWW(W/8)

#defiNeroT_MASK(W-1)

#defineBB((2*W)/8)/*Bytesperblock*/

/*Definemacrosusedinmultipleprocedures.*/

/*Thesemacrosassumes">>"isanunsignedoperation,*/

/*andthatxandsareoftypeRC5_WORD.*/

#defineSHL(x,s)((RC5_WORD)((x)<<((s)&ROT_MASK)))

#defineSHR(x,s,w)((RC5_WORD)((x)>>((w)-((s)&ROT_MASK))))

#defineROTL(x,s,w)((RC5_WORD)(SHL((x),(s))SHR((x),(s),(w))))

5.1初始常量定义

两个常量,Pw和Qw,定义为可以使用任意大小的W表达式如下:

Pw=Odd((e-2)*2**W)

Qw=Odd((phi-1)*2**W)

e是自然对数的底(2.71828...),phi是黄金比例(1.61803...),2**W是2的W

此方,Odd(x)等于x假如x是奇数或等于x+1假如x是偶数。W等于16,32和64,Pw和

Qw常量是下面的16进制值:

#defineP160xb7e1

#defineQ160x9e37

#defineP320xb7e15163

#defineQ320x9e3779b9

#defineP640xb7e151628aed2a6b

#defineQ640x9e3779b97f4a7c15

#ifW==16

#definePwP16/*Select16bitwordsize*/

#defineQwQ16

#endif

#ifW==32

#definePwP32/*Select32bitwordsize*/

#defineQwQ32

#endif

#ifW==64

#definePwP64/*Select64bitwordsize*/

#defineQwQ64

#endif

5.2接口定义

密钥扩展规则转换b-byte密钥,K,为一个扩展密钥,S,是一个T=2*(R+1)个字的

序列。扩展算法使用了两个常量是来自常量e和phi.这些被用于初始化S,然后使用K进行

修改。使用这个规则的一个C代码程序头如下:

/*EXPandanRC5userkey.

*/

voidRC5_Key_Expand(b,K,R,S)

intb;/*Bytelengthofsecretkey*/

char*K;/*Secretkey*/

intR;/*Numberofrounds*/

RC5_WORD*S;/*Expandedkeybuffer,2*(R+1)words*/

{

5.3转换密钥从字节到字

这个步骤转换了b-byte密钥为一个存储在L数组中的字序列。在一个小端字节序的

处理器上通过将L数组置零再拷贝K的b个字节实现。下面的代码将在所有的处理器上获得

这个效果:

inti,j,k,LL,t,T;

RC5_WORDL[256/WW];/*Basedonmaxkeysize*/

RC5_WORDA,B;

/*LLisnumberofelementsusedinL.*/

LL=(b+WW-1)/WW;

for(i=0;i<LL;i++){

L[i]=0;

}

for(i=0;i<b;i++){

t=(K[i]&0xFF)<<(8*(i%4));/*0,8,16,24*/

L[i/WW]=L[i/WW]+t;

}

5.4初始化扩展密钥表

这一步使用一个基于Pw加Qw再模2的W次方的算术级的固定伪随机数模式来填充

S表。元素S[i]等于i*Qw+Pw模2的W次方。这个表可以被预计算和按所需进行拷贝或在空

闲时间计算。C代码如下:

T=2*(R+1);

S[0]=Pw;

for(i=1;i<T;i++){

S[i]=S[i-1]+Qw;

}

5.5混合密钥

这一步混合密钥K到扩展密钥S。混合函数的循环次数K为被初始化的L元素的个

数的3倍,表示为LL,S中的元素个数表示为T。每个循环类似一个加密内部循环的反复因

为两个变量A和B是由这个加密循环的第一部分和第二部分更新的。

A和B的初始值为0,i作为S数组的索引,j作为L数组的索引。第一个循环左移

式的局部结果通过计算S[i],A和B的和得到。然后将这个结果循环左移3位后赋给A。接

着将A的值赋给S[i]。第二个循环左移的局部结果通过计算L[i],A和B的和得到。然后

将这个结果循环左移A+B位后赋给B。接着将B的值赋给L[j]。在循环结束前i、j的值

加1模各自对应的数组的长度。C代码如下:

i=j=0;

A=B=0;

if(LL>T)

k=3*LL;/*Secretkeylen>expandedkey.*/

else

k=3*T;/*Secretkeylen<expandedkey.*/

for(;k>0;k--){

A=ROTL(S[i]+A+B,3,W);

S[i]=A;

B=ROTL(L[j]+A+B,A+B,W);

L[j]=B;

i=(i+1)%T;

j=(j+1)%LL;

}

return;

}/*EndofRC5_Key_Expand*/

6.RC5块密码的描述

这部分通过解释对一个简单输入块进行加密操作的步骤来说明RC5块密码。解密处理

与加密处理步骤相反,因此在此不对此进行解释。RC5密码的参数有一个版本号,V,一个轮

数,R,一个以位计数的字尺寸,W。此处的描述对应RC5的原始版本(V=16十六进制数)囊括

了R的任意正值和W的值16,32和64。

这一处理的输入是密钥扩展表,S,轮数,R,输入缓冲区的指针,in,和输出缓冲区

的指针,out。一个可能的C代码程序头定义如下:

voidRC5_Block_Encrypt(S,R,in,out)

RC5_WORD*S;

intR;

char*in;

char*out;

{

6.1加载A和B的值

这一步转换输入字节为两个无符号整数称作A和B。当RC5被用作64位块密码A和B

是32位的值。第一个输入的字节作为A的低位字节。第四个输入的字节作为A的高位字字

节,第五个输入字节作为B的低位字节,最后一个输入的字节作为B的高位字节。这种转换

对于小端字节序处理器是非常有效率的例如Intel系列。C代码表达如下:

inti;

RC5_WORDA,B;

A=in[0]&0xFF;

A+=(in[1]&0xFF)<<8;

A+=(in[2]&0xFF)<<16;

A+=(in[3]&0xFF)<<24;

B=in[4]&0xFF;

B+=(in[5]&0xFF)<<8;

B+=(in[6]&0xFF)<<16;

B+=(in[7]&0xFF)<<24;

6.2重申轮函数

这一步将扩展密钥与输入混合在一起做基本的加密操作。扩展密钥数组的头两个字]

被分别填充到A和B,然后轮函数被重复R次。

轮函数的前半部分基于A、B和扩展密钥中下一个未用的字的值为A计算一个新的

值。首先A与B异或然后将此结果循环左移B次。循环每次循环W位(例如:对于有64

位块密码的RC5版本循环32位)。实际的循环次数至少是B的W位以2为底的对数。接着

加扩展密钥数组的下一个未用的字形成A的新值。

轮函数的后半部分操作是相同的除了A、B的角色互换一下。非凡B保存A与B异

或的结果然后将此结果循环左移A次,接着加上下一个扩展密钥数组中未用的字成为B的

新值。

用C代码表达的一种方式如下:

A=A+S[0];

B=B+S[1];

for(i=1;i<=R;i++){

A=A^B;

A=ROTL(A,B,W)+S[2*i];

B=B^A;

B=ROTL(B,A,W)+S[(2*i)+1];

}

6.3存储A和B的值

最后一步是转换A和B为一个字节序列。这是打开操作的反变换。C代码可能的表

达如下:

out[0]=(A>>0)&0xFF;

out[1]=(A>>8)&0xFF;

out[2]=(A>>16)&0xFF;

out[3]=(A>>24)&0xFF;

out[4]=(B>>0)&0xFF;

out[5]=(B>>8)&0xFF;

out[6]=(B>>16)&0xFF;

out[7]=(B>>24)&0xFF;

return;

}/*EndofRC5_Block_Encrypt*/

7.RC5-CBC和RC5-CBC-Pad模式的描述

这部分描述了RC5密码的CBC和CBC-Pad模式。这一描述是基于RC5密钥对象和

较早的RC5块密码。

7.1创建密码对象

密码对象需要明了填充模式,轮数,扩展密钥,初始向量,CBC链接块和输入缓冲

区。C代码可能的结构定义形式如下:

/*DefinitionoftheRC5CBCalgorithmobject.

*/

typedefstructrc5CBCAlg

{

intPad;/*1=RC5-CBC-Pad,0=RC5-CBC.*/

intR;/*Numberofrounds.*/

RC5_WORD*S;/*Expandedkey.*/

unsignedcharI[BB];/*Initializationvector.*/

unsignedcharchainBlock[BB];

unsignedcharinputBlock[BB];

intinputBlockIndex;/*NextinputBlockbyte.*/

}rc5CBCAlg;

创建一个密码算法对象,参数必须被检查然后为扩展密钥表分配空间。扩展密钥使用

早先描述的方法来进行初始化。最后,状态变量(填充模式、轮数和输入缓冲区)被赋予初

始值。C代码可能的实现方式如下:

/*AllocateandinitializetheRC5CBCalgorithmobject.

*Return0ifproblems.

*/

rc5CBCAlg*RC5_CBC_Create(Pad,R,Version,bb,I)

intPad;/*1=RC5-CBC-Pad,0=RC5-CBC.*/

intR;/*Numberofrounds.*/

intVersion;/*RC5versionnumber.*/

intbb;/*BytesperRC5block==IVlen.*/

char*I;/*CBCIV,bbbyteslong.*/

{

rc5CBCAlg*pAlg;

intindex;

if((Version!=RC5_FIRST_VERSION)

(bb!=BB)(R<0)(255<R))

return((rc5CBCAlg*)0);

pAlg=(rc5CBCAlg*)malloc(sizeof(*pAlg));

if(pAlg==((rc5CBCAlg*)0))

return((rc5CBCAlg*)0);

pAlg->S=(RC5_WORD*)malloc(BB*(R+1));

if(pAlg->S==((RC5_WORD*)0)){

free(pAlg);

return((rc5CBCAlg*)0);

}

pAlg->Pad=Pad;

pAlg->R=R;

pAlg->inputBlockIndex=0;

for(index=0;index<BB;index++)

pAlg->I[index]=I[index];

return(pAlg);

}

7.2撤消密码对象

撤消密码是创建它的反变换所关心的问题是在将存储空间返回给存储治理者之前将

其值置为0。C代码的可能实现方式如下:

/*ZeroandfreeanRC5algorithmobject.

*/

voidRC5_CBC_Destroy(pAlg)

rc5CBCAlg*pAlg;

{

RC5_WORD*to;

intcount;

if(pAlg==((rc5CBCAlg*)0))

return;

if(pAlg->S==((RC5_WORD*)0))

return;

to=pAlg->S;

for(count=0;count<(1+pAlg->R);count++)

{

*to++=0;/*Twoexpandedkeywordsperround.*/

*to++=0;

}

free(pAlg->S);

for(count=0;count<BB;count++)

{

pAlg->I[count]=(unsignedchar)0;

pAlg->inputBlock[count]=(unsignedchar)0;

pAlg->chainBlock[count]=(unsignedchar)0;

}

pAlg->Pad=0;

pAlg->R=0;

pAlg->inputBlockIndex=0;

free(pAlg);

}

7.3为密码对象设置初始向量

对于CBC密码对象,算法的状态依靠于扩展密钥,CBC链接块和任何内部缓存的

输入。经常相同的密钥被许多治理者使用每一个拥有独一无二的初始向量。消除创建新的密

码对象的系统开销,提供一个答应调用者为一个以存在的密码对象改变初始向量的操作将更

有意义。C代码的可能实现方式如下:

/*SetupanewinitializationvectorforaCBCoperation

*andresettheCBCobject.

*ThiscanbecalledafterFinalwithoutneedingto

*callInitorCreateagain.

*Returnzeroifproblems.

*/

intRC5_CBC_SetIV(pAlg,I)

rc5CBCAlg*pAlg;

char*I;/*CBCInitializationvector,BBbytes.*/

{

intindex;

pAlg->inputBlockIndex=0;

for(index=0;index<BB;index++)

{

pAlg->I[index]=pAlg->chainBlock[index]=I[index];

pAlg->inputBlock[index]=(unsignedchar)0;

}

return(1);

}

7.4绑定一个密钥到一个密码对象

绑定一个密钥到一个密码对象的操作执行了密钥扩展。密钥扩展可能是在密钥上进

行的一个操作,但是当他们操作时修改扩展密钥将使之不能为正确的为密码工作。扩展密钥

后,这个操作必须用初始向量初始化CBC链接块并且为接受第一个字符预备缓冲区。C代

码的操作如下:

/*Initializetheencryptionobjectwiththegivenkey.

*Afterthisroutine,thecallerfreesthekeyobject.

*TheIVforthisCBCobjectcanbechangedbycalling

*theSetIVroutine.Theonlywaytochangethekeyis

*todestroytheCBCobjectandcreateanewone.

*Returnzeroifproblems.

*/

intRC5_CBC_Encrypt_Init(pAlg,pKey)

rc5CBCAlg*pAlg;

rc5UserKey*pKey;

{

if((pAlg==((rc5CBCAlg*)0))

(pKey==((rc5UserKey*)0)))

return(0);

RC5_Key_Expand(Key->keyLength,pKey->keyBytes,

pAlg->R,pAlg->S);

return(RC5_CBC_SetIV(pAlg,pAlg->I));

}

7.5消息的处理部分

此处的加密操作使用Init-Update-Final过程描述。Update操作被用于消息部分的一

个序列为了递增的产生密文。在最后部分被处理后,Final被调用获得任意的明文字节或填

充被缓存在密码对象内的明文字节。这个操作的一个合适的程序头如下:

/*Encryptabufferofplaintext.

*Theplaintextandciphertextbufferscanbethesame.

*Thebytelenoftheciphertextisputin*pCipherLen.

*Callthismultipletimespassingsuccessive

*partsofalargemessage.

*AfterthelastparthasbeenpassedtoUpdate,

*callFinal.

*Returnzeroifproblemslikeoutputbuffertoosmall.

*/

intRC5_CBC_Encrypt_Update(pAlg,N,P,

pCipherLen,maxCipherLen,C)

rc5CBCAlg*pAlg;/*Cipheralgorithmobject.*/

intN;/*BytelengthofP.*/

char*P;/*Plaintextbuffer.*/

int*pCipherLen;/*GetsbytelenofC.*/

intmaxCipherLen;/*SizeofC.*/

char*C;/*Ciphertextbuffer.*/

{

7.5.1输出缓冲区大小的检查

明文处理的第一步是确保输出缓冲区有足够大的空间存储密文。密文将以块大小的

倍数被产生依靠于被传递给这个操作的明文字符的个数加任意位于密码对象内部缓冲区的

字符。C代码如下:

intplainIndex,cipherIndex,j;

/*Checksizeoftheoutputbuffer.*/

if(maxCipherLen<(((pAlg->inputBlockIndex+N)/BB)*BB))

{

*pCipherLen=0;

return(0);

}

7.5.2将明文分成块

下一步是填充字符到内部的缓冲区直到一个块被填满。此时,缓冲区指针被复位输

入缓冲区和CBC链接密码块相异或。链接密码块的字节序和输入块相同。例如:第9个输

入字节和第一个密文字节相异或。结果然后被传递给先前描述的RC5块密码。为了减少数

据的移动和字节调整的问题,RC5的输出能被直接的写到CBC链接块。最后,这个输出被

拷贝到由用户提供的密文缓冲区。在返回前,密文的实际大小被传递给调用者。C代码如下:

plainIndex=cipherIndex=0;

while(plainIndex<N)

{

if(pAlg->inputBlockIndex<BB)

{

pAlg->inputBlock[pAlg->inputBlockIndex]

=P[plainIndex];

pAlg->inputBlockIndex++;

plainIndex++;

}

if(pAlg->inputBlockIndex==BB)

{/*Haveacompleteinputblock,processit.*/

pAlg->inputBlockIndex=0;

for(j=0;j<BB;j++)

{/*XORinthechainblock.*/

pAlg->inputBlock[j]=pAlg->inputBlock[j]

^pAlg->chainBlock[j];

}

RC5_Block_Encrypt(pAlg->S,pAlg->R

pAlg->inputBlock,

pAlg->chainBlock);

for(j=0;j<BB;j++)

{/*Outputtheciphertext.*/

C[cipherIndex]=pAlg->chainBlock[j];

cipherIndex++;

}

}

}

*pCipherLen=cipherIndex;

return(1);

}/*EndofRC5_CBC_Encrypt_Update*/

7.6最后块的处理

这一步处理明文的最后一个块。对于RC5-CBC,这一步只是做错误检查确保明文长

度确实是块长度的倍数。对于RC5-CBC-Pad,填充的字节被添加到明文。填充的字节都是

相同的其值被置为填充的字节数。例如假如填充了8个字节,填充的字节其值都为16进制

的0x08。将包含1到BB个填充字节。C代码如下:

/*ProducethefinalblocKOFciphertextincludingany

*padding,andthenresetthealgorithmobject.

*Returnzeroifproblems.

*/

intRC5_CBC_Encrypt_Final(pAlg,pCipherLen,maxCipherLen,C)

rc5CBCAlg*pAlg;

int*pCipherLen;/*GetsbytelenofC.*/

intmaxCipherLen;/*LenofCbuffer.*/

char*C;/*Ciphertextbuffer.*/

{

intcipherIndex,j;

intpadLength;

/*Fornon-padmodeerrorifinputbytesbuffered.*/

*pCipherLen=0;

if((pAlg->Pad==0)&&(pAlg->inputBlockIndex!=0))

return(0);

if(pAlg->Pad==0)

return(1);

if(maxCipherLen<BB)

return(0);

padLength=BB-pAlg->inputBlockIndex;

for(j=0;j<padLength;j++)

{

pAlg->inputBlock[pAlg->inputBlockIndex]

=(unsignedchar)padLength;

pAlg->inputBlockIndex++;

}

for(j=0;j<BB;j++)

{/*XORthechainblockintotheplaintextblock.*/

pAlg->inputBlock[j]=pAlg->inputBlock[j]

^pAlg->chainBlock[j];

}

RC5_Block_Encrypt(pAlg->S,pAlg->R,

pAlg->inputBlock,pAlg->chainBlock);

cipherIndex=0;

for(j=0;j<BB;j++)

{/*Outputtheciphertext.*/

C[cipherIndex]=pAlg->chainBlock[j];

cipherIndex++;

}

*pCipherLen=cipherIndex;

/*ResettheCBCalgorithmobject.*/

return(RC5_CBC_SetIV(pAlg,pAlg->I));

}/*EndofRC5_CBC_Encrypt_Final*/

8.RC5-CTS的描述

块密码的密码文本偷窃模式在Schneier的应用密码学的195和196页有叙述。这个

模式处理任意长度的明文并且产生于明文长度相匹配的密文。CTS模式除了明文的最后两个

块的处理不同外和CBC一致。下面几步描述了如何处理明文的最后两个块,称作Pn-1和Pn,

Pn-1的长度等于块大小,BB,最后一个块Pn长度是Ln字节。注重Ln从1到BB变化,因

此Pn实际上可以成为一个完整的块。

1、 异或Pn-1和以前的密文块,Cn-2,创建Xn-1。

2、 加密Xn-1得En-1。

3、 选择En-1的前Ln个字节创建Cn。

4、 在Pn末尾用0填充Pn创建长度为BB的P。

5、 异或En-1和P创建Dn。

6、 加密Dn得Cn-1。

7、 密文的最后两部分分别为Cn-1和Cn。

实现CTS加密,RC5-CTS对象必须拥有至多2*BB个字节的明文存储空间当

RC5_CTS_Encrypt_Final规则被调用时单独处理他们。

下面的步骤描述如何解密Cn-1和Cn。

1、 解密Cn得Dn。

2、 在末尾用0填充Cn创建长度为BB的C。

3、 将Dn和C相异或得Xn。

4、 选择Xn的前Ln个字节创建Pn。

5、 将Xn尾部的BB-Ln个字节添加到Cn得En。

6、 解密En得Pn-1。

7、 明文的最后两个部分分别是Pn-1和Pn。

9.测试程序和向量

帮助证实实现的正确性,这一部分提供了测试程序和一组测试向量的结果。

9.1测试程序和向量

下面用C写的测试程序从输入流中读测试向量结果写到输出流中。下面的子过程给

了一组测试向量用于输入和结果输出。

#include<stdio.h>

#defineBLOCK_LENGTH(8/*bytes*/)

#defineMAX_KEY_LENGTH(64/*bytes*/)

#defineMAX_PLAIN_LENGTH(128/*bytes*/)

#defineMAX_CIPHER_LENGTH(MAX_PLAIN_LENGTH+BLOCK_LENGTH)

#defineMAX_ROUNDS(20)

#defineMAX_S_LENGTH(2*(MAX_ROUNDS+1))

typedefstructtest_vector

{

intpadding_mode;

introunds;

charkeytext[2*MAX_KEY_LENGTH+1];

intkey_length;

charkey[MAX_KEY_LENGTH];

charivtext[2*BLOCK_LENGTH+1];

intiv_length;

chariv[BLOCK_LENGTH];

charplaintext[2*MAX_PLAIN_LENGTH+1];

intplain_length;

charplain[MAX_PLAIN_LENGTH];

charciphertext[2*MAX_CIPHER_LENGTH+1];

intcipher_length;

charcipher[MAX_CIPHER_LENGTH];

RC5_WORDS[MAX_S_LENGTH];

}test_vector;

voidshow_banner()

{

(void)printf("RC5CBCTester.\n");

(void)printf("Eachinputlineshouldcontainthefollowing\n");

(void)printf("testparametersseparatedbyasinglespace:\n");

(void)printf("-Paddingmodeflag.Use1forRC5_CBC_Pad,else

0.\n");

(void)printf("-NumberofroundsforRC5.\n");

(void)printf("-Keybytesinhexadecimal.Twocharactersper

bytelike'01'.\n");

(void)printf("-IVbytesinhexadecimal.Mustbe16hex

characters.\n");

(void)printf("-Plaintextbytesinhexadecimal.\n");

(void)printf("Anendoffileorformaterrorterminatesthe

tester.\n");

(void)printf("\n");

}

/*Convertabufferfromasciihextobytes.

*SetpTo_lengthtothebytelengthoftheresult.

*Return1ifeverythingwentOK.

*/

inthex_to_bytes(from,to,pTo_length)

char*from,*to;

int*pTo_length;

{

char*pHex;/*Ptrtonexthexcharacter.*/

char*pByte;/*Ptrtonextresultingbyte.*/

intbyte_length=0;

intvalue;

pByte=to;

for(pHex=from;*pHex!=0;pHex+=2){

if(1!=sscanf(pHex,"%02x",&value))

return(0);

*pByte++=((char)(value&0xFF));

byte_length++;

}

*pTo_length=byte_length;

return(1);

}

/*Convertabufferfrombytestoasciihex.

*Return1ifeverythingwentOK.

*/

intbytes_to_hex(from,from_length,to)

char*from,*to;

intfrom_length;

{

char*pHex;/*Ptrtonexthexcharacter.*/

char*pByte;/*Ptrtonextresultingbyte.*/

intvalue;

pHex=to;

for(pByte=from;from_length>0;from_length--){

value=*pByte++&0xFF;

(void)sprintf(pHex,"%02x",value);

pHex+=2;

}

return(1);

}

/*Return1ifgetavalidtestvector.*/

intget_test_vector(ptv)

test_vector*ptv;

{

if(1!=scanf("%d",&ptv->padding_mode))

return(0);

if(1!=scanf("%d",&ptv->rounds))

return(0);

if((ptv->rounds<0)(MAX_ROUNDS<ptv->rounds))

return(0);

if(1!=scanf("%s",&ptv->keytext))

return(0);

if(1!=hex_to_bytes(ptv->keytext,ptv->key,

&ptv->key_length))

return(0);

if(1!=scanf("%s",&ptv->ivtext))

return(0);

if(1!=hex_to_bytes(ptv->ivtext,ptv->iv,

&ptv->iv_length))

return(0);

if(BLOCK_LENGTH!=ptv->iv_length)

return(0);

if(1!=scanf("%s",&ptv->plaintext))

return(0);

if(1!=hex_to_bytes(ptv->plaintext,ptv->plain,

&ptv->plain_length))

return(0);

return(1);

}

voidrun_test(ptv)

test_vector*ptv;

{

rc5UserKey*pKey;

rc5CBCAlg*pAlg;

intnumBytesOut;

pKey=RC5_Key_Create();

RC5_Key_Set(pKey,ptv->key_length,ptv->key);

pAlg=RC5_CBC_Create(ptv->padding_mode,

ptv->rounds,

RC5_FIRST_VERSION,

BB,

ptv->iv);

(void)RC5_CBC_Encrypt_Init(pAlg,pKey);

ptv->cipher_length=0;

(void)RC5_CBC_Encrypt_Update(pAlg,

ptv->plain_length,ptv->plain,

&(numBytesOut),

MAX_CIPHER_LENGTH-ptv->cipher_length,

&(ptv->cipher[ptv->cipher_length]));

ptv->cipher_length+=numBytesOut;

(void)RC5_CBC_Encrypt_Final(pAlg,

&(numBytesOut),

MAX_CIPHER_LENGTH-ptv->cipher_length,

&(ptv->cipher[ptv->cipher_length]));

ptv->cipher_length+=numBytesOut;

bytes_to_hex(ptv->cipher,ptv->cipher_length,

ptv->ciphertext);

RC5_Key_Destroy(pKey);

RC5_CBC_Destroy(pAlg);

}

voidshow_results(ptv)

test_vector*ptv;

{

if(ptv->padding_mode)

printf("RC5_CBC_Pad");

else

printf("RC5_CBC");

printf("R=%2d",ptv->rounds);

printf("Key=%s",ptv->keytext);

printf("IV=%s",ptv->ivtext);

printf("P=%s",ptv->plaintext);

printf("C=%s",ptv->ciphertext);

printf("\n");

}

intmain(argc,argv)

intargc;

char*argv[];

{

test_vectortv;

test_vector*ptv=&tv;

show_banner();

while(get_test_vector(ptv)){

run_test(ptv);

show_results(ptv);

}

return(0);

}

9.2测试向量

下面的文本是前一节测试程序的输入文件。输出在下一节中给出。

0000000000000000000000000000000000000

000000000000000000000ffffffffffffffff

0000000000000000000010000000000000000

0000000000000000000000000000000000001

0000001020304050607081020304050607080

0011100000000000000000000000000000000

0020000000000000000000000000000000000

0020000000000000000000000000000000000000000

0080000000000000000000000000000000000

0080001020304050607081020304050607080

0120001020304050607081020304050607080

0160001020304050607081020304050607080

008010203040000000000000000ffffffffffffffff

012010203040000000000000000ffffffffffffffff

016010203040000000000000000ffffffffffffffff

01201020304050607080000000000000000ffffffffffffffff

008010203040506070801020304050607081020304050607080

012010203040506070801020304050607081020304050607080

016010203040506070801020304050607081020304050607080

00801020304050607081020304050607080

01020304050607081020304050607080

01201020304050607081020304050607080

01020304050607081020304050607080

01601020304050607081020304050607080

01020304050607081020304050607080

01201020304050000000000000000ffffffffffffffff

00801020304050000000000000000ffffffffffffffff

00801020304057875dbf6738c64780808080808080808

10801020304050000000000000000ffffffffffffffff

008010203040500000000000000000000000000000000

00801020304057cb3f1df34f948111122334455667701

10801020304050000000000000000

ffffffffffffffff7875dbf6738c647811223344556677

9.3测试结果

下面的文本是测试程序运行于前一节给定输入的输出文本。

RC5CBC测试器。

每个输入行应该包含下面用空格号分隔的测试参数:

-填充模式标志。使用1表示RC5-CBC-Pad,其余用0表示。

-RC5的轮数。

-16进制的密钥。每字节两个字符像‘01’。

-16进制的初始向量。必须是16进制的字节。

-16进制的明文字节。

到达文件末尾或格式错误终止测试器。

RC5_CBCR=0Key=00IV=0000000000000000

P=0000000000000000C=7a7bba4d79111d1e

RC5_CBCR=0Key=00IV=0000000000000000

P=ffffffffffffffffC=797bba4d78111d1e

RC5_CBCR=0Key=00IV=0000000000000001

P=0000000000000000C=7a7bba4d79111d1f

RC5_CBCR=0Key=00IV=0000000000000000

P=0000000000000001C=7a7bba4d79111d1f

RC5_CBCR=0Key=00IV=0102030405060708

P=1020304050607080C=8b9ded91ce7794a6

RC5_CBCR=1Key=11IV=0000000000000000

P=0000000000000000C=2f759fe7ad86a378

RC5_CBCR=2Key=00IV=0000000000000000

P=0000000000000000C=dca2694bf40e0788

RC5_CBCR=2Key=00000000IV=0000000000000000

P=0000000000000000C=dca2694bf40e0788

RC5_CBCR=8Key=00IV=0000000000000000

P=0000000000000000C=dcfe098577eca5ff

RC5_CBCR=8Key=00IV=0102030405060708

P=1020304050607080C=9646fb77638f9ca8

RC5_CBCR=12Key=00IV=0102030405060708

P=1020304050607080C=b2b3209db6594da4

RC5_CBCR=16Key=00IV=0102030405060708

P=1020304050607080C=545f7f32a5fc3836

RC5_CBCR=8Key=01020304IV=0000000000000000

P=ffffffffffffffffC=8285e7c1b5bc7402

RC5_CBCR=12Key=01020304IV=0000000000000000

P=ffffffffffffffffC=fc586f92f7080934

RC5_CBCR=16Key=01020304IV=0000000000000000

P=ffffffffffffffffC=cf270ef9717ff7c4

RC5_CBCR=12Key=0102030405060708IV=0000000000000000

P=ffffffffffffffffC=e493f1c1bb4d6e8c

RC5_CBCR=8Key=0102030405060708IV=0102030405060708

P=1020304050607080C=5c4c041e0f217ac3

RC5_CBCR=12Key=0102030405060708IV=0102030405060708

P=1020304050607080C=921f12485373b4f7

RC5_CBCR=16Key=0102030405060708IV=0102030405060708

P=1020304050607080C=5ba0ca6bbe7f5fad

RC5_CBCR=8Key=01020304050607081020304050607080

IV=0102030405060708

P=1020304050607080C=c533771cd0110e63

RC5_CBCR=12Key=01020304050607081020304050607080

IV=0102030405060708

P=1020304050607080C=294ddb46b3278d60

RC5_CBCR=16Key=01020304050607081020304050607080

IV=0102030405060708

P=1020304050607080C=dad6bda9dfe8f7e8

RC5_CBCR=12Key=0102030405IV=0000000000000000

P=ffffffffffffffffC=97e0787837ed317f

RC5_CBCR=8Key=0102030405IV=0000000000000000

P=ffffffffffffffffC=7875dbf6738c6478

RC5_CBCR=8Key=0102030405IV=7875dbf6738c6478

P=0808080808080808C=8f34c3c681c99695

RC5_CBC_PadR=8Key=0102030405IV=0000000000000000

P=ffffffffffffffffC=7875dbf6738c64788f34c3c681c99695

RC5_CBCR=8Key=0102030405IV=0000000000000000

P=0000000000000000C=7cb3f1df34f94811

RC5_CBCR=8Key=0102030405IV=7cb3f1df34f94811

P=1122334455667701C=7fd1a023a5bba217

RC5_CBC_PadR=8Key=0102030405IV=0000000000000000

P=ffffffffffffffff7875dbf6738c647811223344556677

C=7875dbf6738c64787cb3f1df34f948117fd1a023a5bba217

10.安全考虑

RC5密码相对来说是比较新的所以鉴定的评论仍在进行。然而,密码的简单结构使

它易于分析而且有希望更轻易的评定它的的强度。迄今为止的评论是有前途的。

早期的结果暗示12轮64位块大小的RC5将有足够的能力抗拒线性和差分密码分

析。128位的块版本还未像64位的块版本进行多次研究。但是明显的16轮是一个合适的最

小值。小于64位的块尺寸学术上的爱好但是不应被用于密码安全。更大的安全可以通过增

加轮数获得其代价是减少密码的吞吐量。

密钥的长度帮助决定密码对穷举攻击的反抗力。一个128位的密钥长度应该几十年

的时间里为抗拒资金雄厚的对手的穷举攻击提供保护。12轮的RC5,密钥的建立时间和数据

加密时间对于所有长度小于832位的密钥来说都是相同的。因此没有因为不需要为了性能要

求而选择短密钥。对于大的密钥,因为用户的密钥表,L,将比扩展密钥表,S,长所以密钥

扩展的步骤会运行的比较慢。然而,加密时间将不会改变因此它只是一个轮数的函数。

未了配合出口规则可能需要选择密钥只有40个未知位。进行这一步处理的简单方

式是选择一个简单的5个字节的密钥。这应该被避免因为对手可以轻易的预计算密钥搜索信

息。另一个一般的机制是选择128位的密钥出版头88位。这个方法揭示了大量的通往用户

密钥表,L,的路径。且是否RC5密钥扩展表在这种情况下提供了足够的安全还未进行研究。

尽管它可能是好的。一个与40位密钥限制一致的一种保守的方法是选择128位的种子值,

出版这个种子的前88位,通过像MD5的散列函数运行整个种子值,使用这个散列函数的128

位的输出作为RC5的密钥。

在有40位未知密钥和88位已知密钥的情况下,对于64位RC5块版本应该有12

轮或更高的轮数,否则增加给密钥的88位的值可能被丢失。

密钥的生存期也是影响安全的要害。对于高安全的应用,任何64位块密码的密钥

应该在加密了2**32个块后被改变(2**64个块对于128位的块密码)。这将帮助防范线性

和差分密码分析。对于64位的块,这个规则将推荐在2**40个字节被加密后改变密钥。进

一步的讨论见Schneier应用密码学183页。

11.ASN.1标识符

对于使用ASN.1描述的应用,有必要为这些与他们参数块格式相一致的密码定义算

法标识符。一个算法标识符的ASN.1的定义已经存在,以下列出作为参考。

AlgorithmIdentifier::=SEQUENCE{

algorithmOBJECTIDENTIFIER,

parametersANYDEFINEDBYalgorithmOPTIONAL

}

Thevaluesforthealgorithmfieldare:

RC5_CBCOBJECTIDENTIFIER::=

{iso(1)member-body(2)US(840)rsadsi(113549)

encryptionAlgorithm(3)RC5CBC(8)}

RC5_CBC_PadOBJECTIDENTIFIER::=

{iso(1)member-body(2)US(840)rsadsi(113549)

encryptionAlgorithm(3)RC5CBCPAD(9)}

Thestructureoftheparametersfieldforthesealgorithmsisgiven

below.NOTE:iftheivfieldisnotincluded,thenthe

initializationvectordefaultstoablockofzeroswhosesizedepends

ontheblockSizeInBitsfield.

RC5_CBC_Parameters::=SEQUENCE{

versionINTEGER(v1_0(16)),

roundsINTEGER(8..127),

blockSizeInBitsINTEGER(64,128),

ivOCTETSTRINGOPTIONAL

}

12.参考

[1]Kaliski,BurtonS.,andYinqunLisaYin,"OnDifferentialand

LinearCryptanalysisoftheRC5EncryptionAlgorithm",InAdvances

inCryptology-Crypto'95,pages171-184,Springer-Verlag,New

York,1995.

[2]Rivest,RonaldL.,"TheRC5EncryptionAlgorithm",In

ProceedingsoftheSecondInternationalWorkshoponFastSoftware

Encryption,pages86-96,LeuvenBelgium,December1994.

[3]Rivest,RonaldL.,"RC5EncryptionAlgorithm",InDr.Dobbs

Journal,number226,pages146-148,January1995.

[4]Rivest,RonaldL.,"TheMD5Message-DigestAlgorithm",RFC

1321.

[5]RSALaboratories,"PublicKeyCryptographyStandards(PKCS)",

RSADataSecurityInc.SeeFTP.rsa.com.

[6]Schneier,Bruce,"AppliedCryptography",SecondEdition,John

WileyandSons,NewYork,1996.Errata:onpage195,line13,the

referencenumbershouldbe[402].

[7]BusinessSoftwareAlliance,MattBlazeetal.,"MinimumKey

LengthforSymmetricCipherstoProvideAdequateCommercial

Security",http://www.bsa.org/bsa/cryptologists.Html.

[8]RSADataSecurityInc.,"RC5ReferenceCodeinC",Seetheweb

site:www.rsa.com,foravailability.Notavailablewiththefirst

draftofthisdocument.

13.作者地址

RobertW.Baldwin

RSADataSecurity,Inc.

100MarineParkway

RedwoodCity,CA94065

Phone:(415)595-8782

Fax:(415)595-1873

EMail:baldwin@rsa.com,orbaldwin@lcs.mit.edu

RonaldL.Rivest

MassachusettsInstituteofTechnology

LaboratoryforComputerScience

NE43-324

545TechnologySquare

Cambridge,MA02139-1986

Phone:(617)253-5880

EMail:rivest@theory.lcs.mit.edu

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有