??xml version="1.0" encoding="utf-8" standalone="yes"?>美女久久久久久,久久青青草原国产精品免费 ,国产精品久久国产精品99盘 http://www.shnenglu.com/bilicon/比你狂l学习中zh-cnThu, 08 May 2025 22:24:40 GMTThu, 08 May 2025 22:24:40 GMT60signaled ?nonsignaled 在互斥对象中和事件对象中的应?/title><link>http://www.shnenglu.com/bilicon/archive/2009/04/18/80327.html</link><dc:creator>bilicon</dc:creator><author>bilicon</author><pubDate>Sat, 18 Apr 2009 02:12:00 GMT</pubDate><guid>http://www.shnenglu.com/bilicon/archive/2009/04/18/80327.html</guid><wfw:comment>http://www.shnenglu.com/bilicon/comments/80327.html</wfw:comment><comments>http://www.shnenglu.com/bilicon/archive/2009/04/18/80327.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/bilicon/comments/commentRss/80327.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/bilicon/services/trackbacks/80327.html</trackback:ping><description><![CDATA[<p><font face=楷体_GB2312 color=#993300 size=4>signaled ?nonsignaled ֐思义是有信号和无信L对象? 一个对象在有信L状态下可以通过WaitForSingleObject函数来给它申请对? 对象一旦申? U程开始运?对象变ؓ无信号对?nonsignaled)直到释放了对?也就是变为有信号(signald)为止. </font></p> <img src ="http://www.shnenglu.com/bilicon/aggbug/80327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/bilicon/" target="_blank">bilicon</a> 2009-04-18 10:12 <a href="http://www.shnenglu.com/bilicon/archive/2009/04/18/80327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rijndael加密法的介l?http://www.shnenglu.com/bilicon/archive/2007/08/06/29454.htmlbiliconbiliconMon, 06 Aug 2007 14:45:00 GMThttp://www.shnenglu.com/bilicon/archive/2007/08/06/29454.htmlhttp://www.shnenglu.com/bilicon/comments/29454.htmlhttp://www.shnenglu.com/bilicon/archive/2007/08/06/29454.html#Feedback2http://www.shnenglu.com/bilicon/comments/commentRss/29454.htmlhttp://www.shnenglu.com/bilicon/services/trackbacks/29454.html 作?林祝?叶义?杨国?/span>

本文针对Rijndael加密法的数学理景,法的架构,回合的{换,金钥的生,以及各种d破密法等{,做了一些简单的介绍?/span>

一、简?/span>

?/span>AES ( Advanced Encryption Standard ) 的选拔中,从最初的十五个算法,到十个、五个,逐步{选出适合用来作ؓ下一代加密算法的标准?/span>Rijndael在经q了一番时日的考验之后Q也一直名列前矛。直?st1:chsdate Year="2005" Month="10" Day="2" IsLunarDate="False" IsROCDate="False" w:st="on">十月二日Q?/span>Rijndael才脱颖而出Q这文章便是针?/span>Rijndael作简要的介绍?/span>

Rijndael是一个反复运的加密法Q它允许可变动的数据区块及金钥的长度。数据区块与金钥长度的变动是各自独立的?/span>

?/span>Rijndael法中定义了几个名词Q分q如下:

StateQ在q算q程中所产生的中间|是一?/span>4×Nb的矩阵,Nb可由数据长度除以32位求得,也就是把数据分割?/span>Nb个区块?/span>

Cipher KeyQ用来做加密q算的金钥,形式是一?/span>4×Nk的矩阵,Nk可由金钥长度除以32位求得,也就是把金钥分割?/span>Nk?/span>32位的子金钥?/span>

?/span>Rijndael法中,q算的回合数(Nr)是由Nb?/span>Nk所军_的,回合数的变动定义如下表?/span>

 

Nr

Nb=4

Nb=6

Nb=8

Nk=4

10

12

14

Nk=6

12

12

14

Nk=8

14

14

14

二?/span>Rijndael的数学背?/span>

?/span>Rijndael中用了许多字节层的运,而这些运是?/span>GF(28)为基架构。也有一些采用了4-byte的字l运。在q部分,我们介l这些基本的数学原理?/span>

(1)       GF(28)的定?/span>

假设一个字?/span>b?/span>b7b6b5b4b3b2b1b0l成Q我们可以把q些bi惌成一?/span>7ơ多式的系敎ͼ而这些系C?/span>01Q?/span>

b7 x7+ b6 x6+ b5 x5+ b4 x4+ b3 x3+ b2 x2+ b1 x + b0Q?/span>

例如Q?/span>(57)16的二q制表示法ؓ(0101,0111)2表示成多式Q则为:

x6+ x4+ x2+ x + 1 .

(2)       加法

两个多项式的加法Q则是定义ؓ相同指数的pL和再模余2Q简单的说就是作EXORq算(i.e., 1+1=0)。例如:

(57)16+(83)16=(01010111)2+(10000011)2 = (11010100)2 = (D4)16

       或是(x6+x4+x2+x+1) + (x7+x+1) = x7+x6+x4+x2

(3)       乘法

在乘法里面,多项式相乘之后的l果很容易造成溢位的问题,解决溢位的方式是把相乘的l果Q再模余一个不可分解的多项?/span>m(x)。在Rijndael中,定义一个这样子的多式?/span>

m(x)=x8+x4+x3+x+1或是(11B)16

例如Q?/span>

(57)16?/span>(83)16 = ( x6+ x4+ x2+ x + 1)?/span> ( x7+ x + 1) = x13+ x11+ x9+ x8+ x7+x7+ x5+ x3+ x2+x+x6+ x4+ x2+ x + 1

= (x13+ x11+ x9+ x8+ x6+ x5+ x4+ x3+ 1+x13+ x11+ x9+ x8+ x6+ x5+ x4+ x3+ 1) modulo (x8+ x4+ x3+ x + 1)

= x7+ x6+ 1=(C1)16

(4)       乘以x

若把b(x)乘上xQ得?/span>b7 x8+ b6 x7+ b5 x6+ b4 x5+ b3 x4+ b2 x3+ b1 x2 + b0x。若b7=0Q不会发生溢位问题,{案x正确的;?/span>b7=1Q发生溢位问题,必须减去m(x)。我们可以把q种q算表示?/span>xtime(x)Q其q算方式?/span>left shift(若溢位则?/span>(1B)16?/span>EXORq算)Q例如:‘57’ · ‘13’ = ‘FE’

57’ · ‘02’ = xtime(57) = ‘AE’

57’ · ‘04’ = xtime(AE) = ‘47’

57’ · ‘08’ = xtime(47) = ‘8E’

57’ · ‘10’ = xtime(8E) = ‘07’

57’ · ‘13’ = ‘57’ · (‘01’02’10’) = ‘57’ ‘AE’ 07’ = ‘FE’

 

三?/span>Rijndael的加密架?/span>

Rijndael加密法是由一?/span>initial Round Key additionQ?/span>Nr-1个回合运,及一?/span>final round所l成。加密过E以C语言伪码叙述如下Q?/span>

Rijndael(State, CipherKey)

//state表示输入的数据明文,

//CipherKey表示使用的加密金钥,

//ExpandedKey表示每个Round使用的子金钥?/span>

{

KeyExpansion(CipherKey, ExpandedKey);

AddRoundKey(State, ExpandedKey);

For ( i=1; i<Nr; i++)

Round(State, ExpandedKey+Nb×i);

FinalRound(State, ExpandedKey+Nb×Nr);

}

上述法中的Key ExpansionQ可以先行计出来,所以加密过E可以简化ؓQ?/span>

Rijndael(State,ExpandedKey)

//State表示输入的数据明文,

//ExpandedKey表示每个Round使用的子金钥?/span>

{

AddRoundKey(State,ExpandedKey);

For( i=1 ; i<Nr ; i++ )

{

Round(State,ExpandedKey + Nb×i) ;

}

FinalRound (State, ExpandedKey + Nb×Nr);

}

各个子运介l如下?/span>

回合转换(Round transformation)Q?/span>

回合转换包含四个不同的工作,其算法如下:

Round(State,RoundKey)

//State表示输入的数据明文,

//RoundKey表示每个Round使用的子金钥?/span>

{

ByteSub(State);

ShiftRow(State);

MixColumn(State);

AddRoundKey(State,RoundKey);

}

 

 

法中的l止回合(Final round)包含下列工作目Q?/span>

FinalRound(State,RoundKey)

//State表示输入的数据明文,

//RoundKey表示每个Round使用的子金钥?/span>

{

ByteSub(State) ;

ShiftRow(State) ;

AddRoundKey(State,RoundKey);

}

以下针对每个回合转换的运过E,作一个深入的介绍Q可以更清楚法的过E?/span>

1.            字节取代转换(ByteSub transformation)Q?/span>

字节转换是一个以字节为单位的非线性取代运,取代?/span>(S-Box)是经q两个运过E而徏立,q且是可逆的?/span>

首先扑և每个字节?/span>GF(28)中的乘法反元素;

接着l过一个仿?/span>(Affine)转换q算Q定义如下:

 

(本图摘录自参考文?/span>[1])

字节取代(ByteSub)q算?/span>State的媄响,如下图所C:

 

(本图摘录自参考文?/span>[1])

字节取代(ByteSub)转换的反q算Q?/span>

计算仿射对应之后的相反运可得到S-1-BoxQ以?/span>S-1-Box做字节取?/span>(ByteSub)卛_?/span>

2.            Ud转换( ShiftRow transformation )Q?/span>

在这个{换中Q?/span>State的每一列以不同的偏U量做环状位U,W?/span>0列不动,W一列位U?/span>C1个字节,W二列位U?/span>C2个字节,W三列位U?/span>C3个字节。位Uȝ偏移?/span>C1,C2,C3跟区块的数目(Nb)有关Q定义如下表Q?/span>

Nb

C1

C2

C3

4

1

2

3

6

1

2

3

8

1

3

4

Ud转换(ShiftRow)q算对于State的媄响,囄如下Q?/span>

(本图摘录自参考文?/span>[1])

Ud转换(ShiftRow)的反q算Q?/span>

对第二第三及W四列做Nb-C1,Nb-C2,Nb-C3个字节的环状位移卛_?/span>

3.            淯转换(MixColumn transformation)Q?/span>

在这个{换中Q把State当作一个存?/span>GF(28)中的多项式。ƈ且对一个固定的多项?/span>c(x)作乘法,如果发生溢位Q则再模?/span>x4+1。表C如下:

c(x) = ‘03’ x3 + ‘01’ x2 + ‘01’ x + ‘02’ .

c(x)?/span>x4+1互质Qob(x) = c(x) Ä a(x)Q以矩阵乘法表示如下Q?/span>

 

(本图摘录自参考文?/span>[1])

Statel过淯(MixColumn)q算之后的变化如下:

 

(本图摘录自参考文?/span>[1])

(MixColumn)转换的反q算Q则是乘上一个特D的多项?/span>d(x)Q?/span>

(‘03’x3 + ‘01’x2 + ‘01’x + ‘02’ ) Ä d(x) = ‘01’,

d(x) = ‘0B’x3 + ‘0D’x2 + ‘09’x + ‘0E’ .

4.            The Round Key AdditionQ?/span>

q个q算主要是把每一个回合金?/span>(Round Key)透过单的bitwise EXOR加入到每一?/span>State中,以图C如下:

 

(本图摘录自参考文?/span>[1])

四、金钥的排程(Key Schedule)

回合金钥(Round Key)是从加密金钥(Cipher Key)l过q算产生出来的。金钥排E?/span>(Key Schedule)是由金钥扩充(Key Expansion)及回合金钥的选择(Round Key Selection)l成的,基本的理论如下:

       所有回合金钥的M数是把区块长?/span>(block length)乘上回合数加1Q?/span>(?/span>Nr-1个回合,加上一个终止回?/span>(final round))Q例如,128个位的区块长度经q?/span>10个回合运,所需要用到的所有回合金钥的MCؓ1408个位?/span>

       加密金钥(Cipher Key)必须扩充为扩充金?/span>(Expanded Key)?/span>

       回合金钥是从扩充金钥中选出来的Q选择的方式如下:

       W一个回合金钥由?/span>Nb个字l组成,W二个回合金钥由接下来的Nb个字l组成,余此cL?/span>

(1)       金钥的扩?/span>( Key Expansion )Q?/span>

扩充后的金钥是一?/span>4-byte的线性数l,表示?/span>W[Nb×(Nr+1)]。前Nk个字l包含了加密金钥(Cipher Key)?/span>

       金钥扩充函式?/span>Nk是息息相关的Q分ZU情况运作,一是当Nk于或等?/span>6Q另外则是当Nk大于6Q以伪码叙述如下Q?/span>

?/span>Nk?/span>6Ӟ

KeyExpansion(byte Key[4×Nk] word W[Nb×(Nr+1)])

{

for(i = 0; i < Nk; i++)

W[i] = (Key[4×i], Key[4×i+1], Key[4×i+2], Key[4×i+3] );

for(i = Nk; i < Nb×(Nr + 1); i++)

{

temp = W[i - 1];

if (i % Nk == 0)

temp = SubByte(RotByte(temp)) ^ Rcon[i / Nk];

W[i] = W[i - Nk] ^ temp;

}

}

在上面的子程序中Q?/span>SubByte(W)传回一?/span>4-byte的字l,q些字组是输入的字组l过S-box的{换所产生的相对字l?/span>RotByte(W)则是传回l过旋{的字l?/span>

?/span>NkQ?/span>6Ӟ

KeyExpansion(byte Key[4×Nk] word W[Nb×(Nr+1)])

{

for(i = 0; i < Nk; i++)

W[i] =  (key[4×i],key[4×i+1], key[4×i+2], key[4×i+3] );

for(i = Nk; i < Nb×(Nr + 1); i++)

{

temp = W[i - 1];

if (i % Nk == 0)

temp = SubByte(RotByte(temp)) ^ Rcon[i / Nk];

else if (i % Nk == 4)

temp = SubByte(temp);

W[i] = W[i - Nk] ^ temp;

}

}

以上两种情况的相异处在于?/span>Nk?/span>6Ӟ(i-4)?/span>Nk的倍数Ӟ对于W[i-1]先执?/span>SubByteQ再执行EXOR?/span>

上述回合常数定义如下Q?/span>

Rcon[i] = (RC[i],‘00’,‘00’,‘00’)Q其?/span>RC[0]=’01’Q?/span>RC[i]=xtime(Rcon[i-1])?/span>

(2)       选择回合金钥(Round Key Selection)

W?/span>i个回合金钥是指在存在回合金钥~冲区的字组W[Nb*i]?/span>W[Nb*(i+1)]Q图C如下:

 

(本图摘录自参考文?/span>[1])

五、安全性分?/span>

       我们针对以下已知的攻L?/span>Rijndael的安全性分析作一要叙qͼ包括差分d?/span>(Differential Cryptanalysis)Q线性攻L(Linear Cryptanalysis)Q^ҎL(The Square Attack)Q内插攻L(Interpolation attacks){攻L式?/span>

(1)       差分d?/span>( Differential Cryptanalysis )

       此攻L是一U?/span>Chosen-plaintext attackQ利用大量已知的明文/密文对之间的差异Q据以推出金钥的位倹{在大部分的回合q算?/span>(回合数超q?/span>3)Q若存在过21-n(n指的是区块长?/span>)比例的可预测性的差异Q这个攻L可以推出金钥的位倹{在Rijndael中,已经证明在经q?/span>Rijndael四个回合的运后Q存在不过2-150比例的可预测性差异,在八个回合运中不超q?/span>2-300。详l证明过E,请参照参考文献?/span>

(2)       U性攻L( Linear Cryptanalysis )

       q是一U?/span>Known-plaintextd法,利用大量搜集到的明文/密文对的相关性,对加密法q行d。明?/span>/密文对的相关性由U性轨q?/span>(Linear trails)所l成Q由于线性轨q的相关pL?/span>Round keys的值有密切关系Q透过相关pL的正负号Q线性攻L可以找出金钥倹{要Ҏq种d法,有一个必要条件就是ɘq种相关pL大于2n/2的线性轨q不存在。在Rijndael中,已经证明出当执行四个回合Ӟ不存在相关系数大?/span>2-75的线性轨q;在执行八个回合时Q其相关pL大于2-150的相关系C不存在。详l证明过E请参照参考文献?/span>

(3)       qxd?/span>( The Square attack )

       q种d法是一U?/span>chosen- plaintext attackQ而且和字节取?/span>(ByteSub)Q؜?/span>(MixColumn)时的多项式乘法,金钥的排E?/span>(Key Schedule){运无兟뀂当Rijndael执行6个回合以上时Q此U方式比完全的金钥搜?/span>(exhaustive key search)来的更有效率。关于此U攻L式的详尽描述?/span>Rijndael如何延此种d方式Q请参照参考文献?/span>

(4)       内插d?/span>( Interpolation attacks )

       在这U攻L中,d者利用加密的输入及输出配对,建立一些多式。如果加密的lg有一个简z的代数展开式,q且和管理的复杂度结合在一hQ这U攻L便是可行的。基本的d方式是如果攻击者徏立的代数展开式的阶度(degree)很小Q只需要一些加密法的输入及输出配对可以得C数展开式的各项pL。然而,?/span>GF(28)中的取代矩阵(S-box)Q它的展开式ؓQ?/span>63+8fx127+b5x191+01x223+f4x239+25x247+f9x251+09x253+05x254。其余介l,请参照参考文献?/span>

(5)、弱金钥(Weak keys)

       关于弱金钥的发生Q基本上是因为加密法的非U性运与实际金钥值有密切关系。而这U问题不存在?/span>Rijndael之中Q因为在Rijndael中,金钥是以EXORq算Q而所有的非线性运都定义在取代矩?/span>(S-box)中。在Rijndael中,寚w钥的选择Q是没有限制的?/span>

六、结论:

       以上?/span>Rijndael作一要介l之后,我们?/span>Rijndael的优点与限制作ؓ我们的结论?/span>

(1)?/span>Rijndael有以下优?/span>?/span>

以实作观点而言

1.            Rijndael可以实作?/span>Pentium ( Pro ) {计机上,q已相当快的速度处理q算Q而在表格大小与效率之间是可以做取舍的?/span>

2.            Rijndael可以实作在智能卡(Smart Card)上,使用量?/span>RAMQ少量的E序代码Q在ROM与效率之间也是可以做取舍的?/span>

3.            在设计上Q回合的转换是可q处理的?/span>

4.            加密法不采用术q算Q不会因Z同处理器架构而有所偏差?/span>

设计单化Q?/span>

1.            设计上不引用其它加密lgQ如S-box?/span>

2.            安全度不建立在一些分析不够明的术q算之上?/span>

3.            加密法紧凑,不易藏入暗门{程序代码?/span>

除此之外Q?/span>Rijndael更允许可变动的区块长度及金钥长度Q其长度可由128位到256位之_所以回合数也是可变动的?/span>

(2)Rijndael的限Ӟ

在解密过E中有以下限?/span>

1.            实作在智慧卡Ӟ解密不如加密来的有效率,解密需要更多的E序代码?/span>cyclesQ但是跟其它法比v来,仍然是快速的?/span>

2.            以Y件而言Q加密和解密使用不同的程序和表格?/span>

3.            以硬件而言Q解密只能重用部分加密的电\?/span>



bilicon 2007-08-06 22:45 发表评论
]]>
MD5~RFC 1321http://www.shnenglu.com/bilicon/archive/2007/08/03/29263.htmlbiliconbiliconFri, 03 Aug 2007 04:35:00 GMThttp://www.shnenglu.com/bilicon/archive/2007/08/03/29263.htmlhttp://www.shnenglu.com/bilicon/comments/29263.htmlhttp://www.shnenglu.com/bilicon/archive/2007/08/03/29263.html#Feedback0http://www.shnenglu.com/bilicon/comments/commentRss/29263.htmlhttp://www.shnenglu.com/bilicon/services/trackbacks/29263.htmlNetwork Working Group R. Rivest Request for Comments: 1321 MIT Laboratory for Computer Science and RSA Data Security, Inc. April 1992 The MD5 Message-Digest Algorithm Status of this Memo This memo provides information for the Internet community. It does not specify an Internet standard. Distribution of this memo is unlimited. Acknowlegements We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, David Chaum, and Noam Nisan for numerous helpful comments and suggestions. Table of Contents 1. Executive Summary 1 2. Terminology and Notation 2 3. MD5 Algorithm Description 3 4. Summary 6 5. Differences Between MD4 and MD5 6 References 7 APPENDIX A - Reference Implementation 7 Security Considerations 21 Author's Address 21 1. Executive Summary This document describes the MD5 message-digest algorithm. The algorithm takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. The MD5 algorithm is intended for digital signature applications, where a large file must be "compressed" in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA. Rivest [Page 1] RFC 1321 MD5 Message-Digest Algorithm April 1992 The MD5 algorithm is designed to be quite fast on 32-bit machines. In addition, the MD5 algorithm does not require any large substitution tables; the algorithm can be coded quite compactly. The MD5 algorithm is an extension of the MD4 message-digest algorithm 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in design. MD5 was designed because it was felt that MD4 was perhaps being adopted for use more quickly than justified by the existing critical review; because MD4 was designed to be exceptionally fast, it is "at the edge" in terms of risking successful cryptanalytic attack. MD5 backs off a bit, giving up a little in speed for a much greater likelihood of ultimate security. It incorporates some suggestions made by various reviewers, and contains additional optimizations. The MD5 algorithm is being placed in the public domain for review and possible adoption as a standard. For OSI-based applications, MD5's object identifier is md5 OBJECT IDENTIFIER ::= iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5} In the X.509 type AlgorithmIdentifier [3], the parameters for MD5 should have type NULL. 2. Terminology and Notation In this document a "word" is a 32-bit quantity and a "byte" is an eight-bit quantity. A sequence of bits can be interpreted in a natural manner as a sequence of bytes, where each consecutive group of eight bits is interpreted as a byte with the high-order (most significant) bit of each byte listed first. Similarly, a sequence of bytes can be interpreted as a sequence of 32-bit words, where each consecutive group of four bytes is interpreted as a word with the low-order (least significant) byte given first. Let x_i denote "x sub i". If the subscript is an expression, we surround it in braces, as in x_{i+1}. Similarly, we use ^ for superscripts (exponentiation), so that x^i denotes x to the i-th power. Let the symbol "+" denote addition of words (i.e., modulo-2^32 addition). Let X <<< s denote the 32-bit value obtained by circularly shifting (rotating) X left by s bit positions. Let not(X) denote the bit-wise complement of X, and let X v Y denote the bit-wise OR of X and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY denote the bit-wise AND of X and Y. Rivest [Page 2] RFC 1321 MD5 Message-Digest Algorithm April 1992 3. MD5 Algorithm Description We begin by supposing that we have a b-bit message as input, and that we wish to find its message digest. Here b is an arbitrary nonnegative integer; b may be zero, it need not be a multiple of eight, and it may be arbitrarily large. We imagine the bits of the message written down as follows: m_0 m_1 ... m_{b-1} The following five steps are performed to compute the message digest of the message. 3.1 Step 1. Append Padding Bits The message is "padded" (extended) so that its length (in bits) is congruent to 448, modulo 512. That is, the message is extended so that it is just 64 bits shy of being a multiple of 512 bits long. Padding is always performed, even if the length of the message is already congruent to 448, modulo 512. Padding is performed as follows: a single "1" bit is appended to the message, and then "0" bits are appended so that the length in bits of the padded message becomes congruent to 448, modulo 512. In all, at least one bit and at most 512 bits are appended. 3.2 Step 2. Append Length A 64-bit representation of b (the length of the message before the padding bits were added) is appended to the result of the previous step. In the unlikely event that b is greater than 2^64, then only the low-order 64 bits of b are used. (These bits are appended as two 32-bit words and appended low-order word first in accordance with the previous conventions.) At this point the resulting message (after padding with bits and with b) has a length that is an exact multiple of 512 bits. Equivalently, this message has a length that is an exact multiple of 16 (32-bit) words. Let M[0 ... N-1] denote the words of the resulting message, where N is a multiple of 16. 3.3 Step 3. Initialize MD Buffer A four-word buffer (A,B,C,D) is used to compute the message digest. Here each of A, B, C, D is a 32-bit register. These registers are initialized to the following values in hexadecimal, low-order bytes first): Rivest [Page 3] RFC 1321 MD5 Message-Digest Algorithm April 1992 word A: 01 23 45 67 word B: 89 ab cd ef word C: fe dc ba 98 word D: 76 54 32 10 3.4 Step 4. Process Message in 16-Word Blocks We first define four auxiliary functions that each take as input three 32-bit words and produce as output one 32-bit word. F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z) H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z)) In each bit position F acts as a conditional: if X then Y else Z. The function F could have been defined using + instead of v since XY and not(X)Z will never have 1's in the same bit position.) It is interesting to note that if the bits of X, Y, and Z are independent and unbiased, the each bit of F(X,Y,Z) will be independent and unbiased. The functions G, H, and I are similar to the function F, in that they act in "bitwise parallel" to produce their output from the bits of X, Y, and Z, in such a manner that if the corresponding bits of X, Y, and Z are independent and unbiased, then each bit of G(X,Y,Z), H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that the function H is the bit-wise "xor" or "parity" function of its inputs. This step uses a 64-element table T[1 ... 64] constructed from the sine function. Let T[i] denote the i-th element of the table, which is equal to the integer part of 4294967296 times abs(sin(i)), where i is in radians. The elements of the table are given in the appendix. Do the following: /* Process each 16-word block. */ For i = 0 to N/16-1 do /* Copy block i into X. */ For j = 0 to 15 do Set X[j] to M[i*16+j]. end /* of loop on j */ /* Save A as AA, B as BB, C as CC, and D as DD. */ AA = A BB = B Rivest [Page 4] RFC 1321 MD5 Message-Digest Algorithm April 1992 CC = C DD = D /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ /* Do the following 16 operations. */ [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4] [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ /* Do the following 16 operations. */ [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24] [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32] /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ /* Do the following 16 operations. */ [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36] [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40] [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44] [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ /* Do the following 16 operations. */ [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52] [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56] [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60] [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64] /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ A = A + AA B = B + BB C = C + CC D = D + DD end /* of loop on i */ Rivest [Page 5] RFC 1321 MD5 Message-Digest Algorithm April 1992 3.5 Step 5. Output The message digest produced as output is A, B, C, D. That is, we begin with the low-order byte of A, and end with the high-order byte of D. This completes the description of MD5. A reference implementation in C is given in the appendix. 4. Summary The MD5 message-digest algorithm is simple to implement, and provides a "fingerprint" or message digest of a message of arbitrary length. It is conjectured that the difficulty of coming up with two messages having the same message digest is on the order of 2^64 operations, and that the difficulty of coming up with any message having a given message digest is on the order of 2^128 operations. The MD5 algorithm has been carefully scrutinized for weaknesses. It is, however, a relatively new algorithm and further security analysis is of course justified, as is the case with any new proposal of this sort. 5. Differences Between MD4 and MD5 The following are the differences between MD4 and MD5: 1. A fourth round has been added. 2. Each step now has a unique additive constant. 3. The function g in round 2 was changed from (XY v XZ v YZ) to (XZ v Y not(Z)) to make g less symmetric. 4. Each step now adds in the result of the previous step. This promotes a faster "avalanche effect". 5. The order in which input words are accessed in rounds 2 and 3 is changed, to make these patterns less like each other. 6. The shift amounts in each round have been approximately optimized, to yield a faster "avalanche effect." The shifts in different rounds are distinct. Rivest [Page 6] RFC 1321 MD5 Message-Digest Algorithm April 1992 References [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and RSA Data Security, Inc., April 1992. [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90 Proceedings, pages 303-311, Springer-Verlag, 1991. [3] CCITT Recommendation X.509 (1988), "The Directory - Authentication Framework." APPENDIX A - Reference Implementation This appendix contains the following files taken from RSAREF: A Cryptographic Toolkit for Privacy-Enhanced Mail: global.h -- global header file md5.h -- header file for MD5 md5c.c -- source code for MD5 For more information on RSAREF, send email to <rsaref@rsa.com>. The appendix also includes the following file: mddriver.c -- test driver for MD2, MD4 and MD5 The driver compiles for MD5 by default but can compile for MD2 or MD4 if the symbol MD is defined on the C compiler command line as 2 or 4. The implementation is portable and should work on many different plaforms. However, it is not difficult to optimize the implementation on particular platforms, an exercise left to the reader. For example, on "little-endian" platforms where the lowest-addressed byte in a 32- bit word is the least significant and there are no alignment restrictions, the call to Decode in MD5Transform can be replaced with a typecast. A.1 global.h /* GLOBAL.H - RSAREF types and constants */ /* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already Rivest [Page 7] RFC 1321 MD5 Message-Digest Algorithm April 1992 been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ typedef unsigned long int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif A.2 md5.h /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. Rivest [Page 8] RFC 1321 MD5 Message-Digest Algorithm April 1992 These notices must be retained in any copies of any part of this documentation and/or software. */ /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); A.3 md5c.c /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "global.h" #include "md5.h" /* Constants for MD5Transform routine. */ Rivest [Page 9] RFC 1321 MD5 Message-Digest Algorithm April 1992 #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ Rivest [Page 10] RFC 1321 MD5 Message-Digest Algorithm April 1992 (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void MD5Update (context, input, inputLen) MD5_CTX *context; /* context */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((UINT4)inputLen << 3)) Rivest [Page 11] RFC 1321 MD5 Message-Digest Algorithm April 1992 < ((UINT4)inputLen << 3)) context->count[1]++; context->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ void MD5Final (digest, context) unsigned char digest[16]; /* message digest */ MD5_CTX *context; /* context */ { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen); /* Append length (before padding) */ MD5Update (context, bits, 8); Rivest [Page 12] RFC 1321 MD5 Message-Digest Algorithm April 1992 /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset ((POINTER)context, 0, sizeof (*context)); } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform (state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ Rivest [Page 13] RFC 1321 MD5 Message-Digest Algorithm April 1992 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. Rivest [Page 14] RFC 1321 MD5 Message-Digest Algorithm April 1992 */ MD5_memset ((POINTER)x, 0, sizeof (x)); } /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode (output, input, len) unsigned char *output; UINT4 *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ static void Decode (output, input, len) UINT4 *output; unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD5_memcpy (output, input, len) POINTER output; POINTER input; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) Rivest [Page 15] RFC 1321 MD5 Message-Digest Algorithm April 1992 output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset (output, value, len) POINTER output; int value; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } A.4 mddriver.c /* MDDRIVER.C - test driver for MD2, MD4 and MD5 */ /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ /* The following makes MD default to MD5 if it has not already been defined with C compiler flags. */ #ifndef MD #define MD MD5 #endif #include <stdio.h> #include <time.h> #include <string.h> #include "global.h" #if MD == 2 #include "md2.h" #endif #if MD == 4 Rivest [Page 16] RFC 1321 MD5 Message-Digest Algorithm April 1992 #include "md4.h" #endif #if MD == 5 #include "md5.h" #endif /* Length of test block, number of test blocks. */ #define TEST_BLOCK_LEN 1000 #define TEST_BLOCK_COUNT 1000 static void MDString PROTO_LIST ((char *)); static void MDTimeTrial PROTO_LIST ((void)); static void MDTestSuite PROTO_LIST ((void)); static void MDFile PROTO_LIST ((char *)); static void MDFilter PROTO_LIST ((void)); static void MDPrint PROTO_LIST ((unsigned char [16])); #if MD == 2 #define MD_CTX MD2_CTX #define MDInit MD2Init #define MDUpdate MD2Update #define MDFinal MD2Final #endif #if MD == 4 #define MD_CTX MD4_CTX #define MDInit MD4Init #define MDUpdate MD4Update #define MDFinal MD4Final #endif #if MD == 5 #define MD_CTX MD5_CTX #define MDInit MD5Init #define MDUpdate MD5Update #define MDFinal MD5Final #endif /* Main driver. Arguments (may be any combination): -sstring - digests string -t - runs time trial -x - runs test script filename - digests file (none) - digests standard input */ int main (argc, argv) int argc; Rivest [Page 17] RFC 1321 MD5 Message-Digest Algorithm April 1992 char *argv[]; { int i; if (argc > 1) for (i = 1; i < argc; i++) if (argv[i][0] == '-' && argv[i][1] == 's') MDString (argv[i] + 2); else if (strcmp (argv[i], "-t") == 0) MDTimeTrial (); else if (strcmp (argv[i], "-x") == 0) MDTestSuite (); else MDFile (argv[i]); else MDFilter (); return (0); } /* Digests a string and prints the result. */ static void MDString (string) char *string; { MD_CTX context; unsigned char digest[16]; unsigned int len = strlen (string); MDInit (&context); MDUpdate (&context, string, len); MDFinal (digest, &context); printf ("MD%d (\"%s\") = ", MD, string); MDPrint (digest); printf ("\n"); } /* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. */ static void MDTimeTrial () { MD_CTX context; time_t endTime, startTime; unsigned char block[TEST_BLOCK_LEN], digest[16]; unsigned int i; Rivest [Page 18] RFC 1321 MD5 Message-Digest Algorithm April 1992 printf ("MD%d time trial. Digesting %d %d-byte blocks ...", MD, TEST_BLOCK_LEN, TEST_BLOCK_COUNT); /* Initialize block */ for (i = 0; i < TEST_BLOCK_LEN; i++) block[i] = (unsigned char)(i & 0xff); /* Start timer */ time (&startTime); /* Digest blocks */ MDInit (&context); for (i = 0; i < TEST_BLOCK_COUNT; i++) MDUpdate (&context, block, TEST_BLOCK_LEN); MDFinal (digest, &context); /* Stop timer */ time (&endTime); printf (" done\n"); printf ("Digest = "); MDPrint (digest); printf ("\nTime = %ld seconds\n", (long)(endTime-startTime)); printf ("Speed = %ld bytes/second\n", (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime)); } /* Digests a reference suite of strings and prints the results. */ static void MDTestSuite () { printf ("MD%d test suite:\n", MD); MDString (""); MDString ("a"); MDString ("abc"); MDString ("message digest"); MDString ("abcdefghijklmnopqrstuvwxyz"); MDString ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); MDString ("1234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890"); } /* Digests a file and prints the result. Rivest [Page 19] RFC 1321 MD5 Message-Digest Algorithm April 1992 */ static void MDFile (filename) char *filename; { FILE *file; MD_CTX context; int len; unsigned char buffer[1024], digest[16]; if ((file = fopen (filename, "rb")) == NULL) printf ("%s can't be opened\n", filename); else { MDInit (&context); while (len = fread (buffer, 1, 1024, file)) MDUpdate (&context, buffer, len); MDFinal (digest, &context); fclose (file); printf ("MD%d (%s) = ", MD, filename); MDPrint (digest); printf ("\n"); } } /* Digests the standard input and prints the result. */ static void MDFilter () { MD_CTX context; int len; unsigned char buffer[16], digest[16]; MDInit (&context); while (len = fread (buffer, 1, 16, stdin)) MDUpdate (&context, buffer, len); MDFinal (digest, &context); MDPrint (digest); printf ("\n"); } /* Prints a message digest in hexadecimal. */ static void MDPrint (digest) unsigned char digest[16]; { Rivest [Page 20] RFC 1321 MD5 Message-Digest Algorithm April 1992 unsigned int i; for (i = 0; i < 16; i++) printf ("%02x", digest[i]); } A.5 Test suite The MD5 test suite (driver option "-x") should print the following results: MD5 test suite: MD5 ("") = d41d8cd98f00b204e9800998ecf8427e MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f MD5 ("123456789012345678901234567890123456789012345678901234567890123456 78901234567890") = 57edf4a22be3c955ac49da2e2107b67a Security Considerations The level of security discussed in this memo is considered to be sufficient for implementing very high security hybrid digital- signature schemes based on MD5 and a public-key cryptosystem. Author's Address Ronald L. Rivest Massachusetts Institute of Technology Laboratory for Computer Science NE43-324 545 Technology Square Cambridge, MA 02139-1986 Phone: (617) 253-5880 EMail: rivest@theory.lcs.mit.edu Rivest [Page 21]

bilicon 2007-08-03 12:35 发表评论
]]>
[zt]MD5法原理 http://www.shnenglu.com/bilicon/archive/2007/08/03/29262.htmlbiliconbiliconFri, 03 Aug 2007 04:34:00 GMThttp://www.shnenglu.com/bilicon/archive/2007/08/03/29262.htmlhttp://www.shnenglu.com/bilicon/comments/29262.htmlhttp://www.shnenglu.com/bilicon/archive/2007/08/03/29262.html#Feedback0http://www.shnenglu.com/bilicon/comments/commentRss/29262.htmlhttp://www.shnenglu.com/bilicon/services/trackbacks/29262.htmllD
    
    md5的全U是message-digest algorithm 5Q信?摘要法Q,?0q代初由mit laboratory for computer science和rsa data security inc的ronald l. rivest开发出来,lmd2、md3和md4发展而来。它的作用是让大定w信息在用数字{֐软g{vUh密匙前被"压羃"成一U保密的格式Q就是把一个Q意长度的字节串变换成一定长的大整数Q。不是md2、md4q是md5Q它们都需要获得一个随机长度的信息q生一?28位的信息摘要。虽然这些算法的l构或多或少有些怼Q但md2的设计与md4和md5完全不同Q那是因为md2是ؓ8位机器做q设计优化的Q而md4和md5却是面向32位的电脑。这三个法的描q和c语言源代码在internet rfcs 1321中有详细的描qͼhttp://www.ietf.org/rfc/rfc1321.txtQ,q是一份最权威的文档,由ronald l. rivest?992q?月向ieft提交?
    
    rivest?989q开发出md2法。在q个法中,首先对信息进行数据补位,使信息的字节长度?6的倍数。然后,以一?6位的验和q加C息末。ƈ且根据这个新产生的信息计出散列倹{后来,rogier和chauvaud发现如果忽略了检验和生md2冲突。md2法的加密后l果是唯一?-既没有重复?
    
    Z加强法的安全性,rivest?990q又开发出md4法。md4法同样需要填补信息以保信息的字节长度加?48后能?12整除Q信息字节长度mod 512 = 448Q。然后,一个以64位二q制表示的信息的最初长度被dq来。信息被处理?12位damg?rd/merkleq代l构的区块,而且每个区块要通过三个不同步骤的处理。den boer和bosselaers以及其他人很快的发现了攻击md4版本中第一步和W三步的漏洞。dobbertin向大家演CZ如何利用一部普通的个h电脑在几分钟内找到md4完整版本中的冲突Q这个冲H实际上是一U漏z,它将D对不同的内容q行加密却可能得到相同的加密后结果)。毫无疑问,md4此被淘汰掉了?
    
    管md4法在安全上有个q么大的漏洞Q但它对在其后才被开发出来的好几U信息安全加密算法的出现却有着不可忽视的引g用。除了md5以外Q其中比较有名的q有sha-1、ripe-md以及haval{?
    
    一q以后,?991q_rivest开发出技术上更ؓ近成熟的md5法。它在md4的基上增加了"安全-带子"Qsafety-beltsQ的概念。虽然md5比md4E微慢一些,但却更ؓ安全。这个算法很明显的由四个和md4设计有少怸同的步骤l成。在md5法中,信息-摘要的大和填充的必要条件与md4完全相同。den boer和bosselaers曑֏现md5法中的假冲H(pseudo-collisionsQ,但除此之外就没有其他被发现的加密后结果了?
    
    van oorschot和wiener曄考虑q一个在散列中暴力搜dH的函数Qbrute-force hash functionQ,而且他们猜测一个被设计专门用来搜烦md5冲突的机器(q台机器?994q的刉成本大U是一百万元Q可以^均每24天就扑ֈ一个冲H。但单从1991q到2001q这10q间Q竟没有出现替代md5法的md6或被叫做其他什么名字的新算法这一点,我们可以看个瑕疵ƈ没有太多的媄响md5的安全性。上面所有这些都不以成为md5的在实际应用中的问题。ƈ且,׃md5法的用不需要支付Q何版权费用的Q所以在一般的情况下(非绝密应用领域。但即便是应用在l密领域内,md5也不׃ؓ一U非怼U的中间技术)Qmd5怎么都应该算得上是非常安全的了?nbsp;
    
法的应?/strong>
    
    md5的典型应用是对一D信息(messageQ生信息摘要(message-digestQ,以防止被改。比如,在unix下有很多软g在下载的时候都有一个文件名相同Q文件扩展名?md5的文Ӟ在这个文件中通常只有一行文本,大致l构如:
    
    md5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461
    
    q就是tanajiya.tar.gz文g的数字签名。md5整个文件当作一个大文本信息Q通过其不可逆的字符串变换算法,产生了这个唯一的md5信息摘要。如果在以后传播q个文g的过E中Q无论文件的内容发生了Q何Ş式的改变Q包括hZҎ者下载过E中U\不稳定引L传输错误{)Q只要你对这个文仉新计md5时就会发C息摘要不相同Q由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用md5q可以防止文件作者的"抵赖"Q这是所谓的数字{֐应用?
    
    md5q广泛用于加密和解密技术上。比如在unixpȝ中用L密码是以md5Q或其它cM的算法)l加密后存储在文件系l中。当用户d的时候,pȝ把用戯入的密码计算成md5|然后再去和保存在文gpȝ中的md5D行比较,q而确定输入的密码是否正确。通过q样的步骤,pȝ在ƈ不知道用户密码的明码的情况下可以确定用L录系l的合法性。这不但可以避免用户的密码被hpȝ理员权限的用户知道Q而且q在一定程度上增加了密码被破解的难度?
    
    正是因ؓq个原因Q现在被黑客使用最多的一U破译密码的Ҏ是一U被UCؓ"跑字?的方法。有两种Ҏ得到字典Q一U是日常搜集的用做密码的字符串表Q另一U是用排列组合方法生成的Q先用md5E序计算些字兔R的md5|然后再用目标的md5值在q个字典中检索。我们假讑֯码的最大长度ؓ8位字节(8 bytesQ,同时密码只能是字母和数字Q共26+26+10=62个字W,排列l合出的字典的项数则是p(62,1)+p(62,2)….+p(62,8)Q那也已l是一个很天文的数字了Q存储这个字典就需要tbU的盘阵列Q而且q种Ҏq有一个前提,是能获得目标̎L密码md5值的情况下才可以。这U加密技术被q泛的应用于unixpȝ中,q也是ؓ什么unixpȝ比一般操作系l更为坚Z个重要原因?nbsp;
    
法描述
    
    对md5法要的叙述可以为:md5?12位分l来处理输入的信息,且每一分组又被划分?6?2位子分组Q经q了一pd的处理后Q算法的输出由四?2位分l组成,这四个32位分l联后生成一?28位散列倹{?
    
    在md5法中,首先需要对信息q行填充Q其字节长度对512求余的结果等?48。因此,信息的字节长度(bits lengthQ将被扩展至n*512+448Q即n*64+56个字节(bytesQ,nZ个正整数。填充的Ҏ如下Q在信息的后面填充一?和无C0Q直到满上面的条g时才停止?对信息的填充。然后,在在q个l果后面附加一个以64位二q制表示的填充前信息长度。经q这两步的处理,现在的信息字节长?n*512+448+64=(n+1)*512Q即长度恰好?12的整数倍。这样做的原因是为满_面处理中对信息长度的要求?
    
    md5中有四个32位被UC链接变量Qchaining variableQ的整数参数Q他们分别ؓQa=0x01234567Qb=0x89abcdefQc=0xfedcba98Qd=0x76543210?
    
    当设|好q四个链接变量后Q就开始进入算法的四轮循环q算。@环的ơ数是信息中512位信息分l的数目?
    
    上面四个链接变量复制到另外四个变量中:a到aQb到bQc到cQd到d?
    
    d@环有四轮Qmd4只有三轮Q,每轮循环都很怼。第一轮进?6ơ操作。每ơ操作对a、b、c和d中的其中三个作一ơ非U性函数运,然后所得结果加上第四个变量Q文本的一个子分组和一个常数。再所得结果向右环UM个不定的敎ͼq加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一?
    以一下是每次操作中用到的四个非线性函敎ͼ每轮一个)?
    
    f(x,y,z) =(x&y)|((~x)&z)
    g(x,y,z) =(x&z)|(y&(~z))
    h(x,y,z) =x^y^z
    i(x,y,z)=y^(x|(~z))
    Q?amp;是与Q|是或Q~是非Q^是异或)
    
    q四个函数的说明Q如果x、y和z的对应位是独立和均匀的,那么l果的每一位也应是独立和均匀的?
    f是一个逐位q算的函数。即Q如果xQ那么yQ否则z。函数h是逐位奇偶操作W?
    
    假设mj表示消息的第j个子分组Q从0?5Q,<<
    ff(a,b,c,d,mj,s,ti)表示a=b+((a+(f(b,c,d)+mj+ti)<< gg(a,b,c,d,mj,s,ti)表示a=b+((a+(g(b,c,d)+mj+ti)<< hh(a,b,c,d,mj,s,ti)表示a=b+((a+(h(b,c,d)+mj+ti)<< ii(a,b,c,d,mj,s,ti)表示a=b+((a+(i(b,c,d)+mj+ti)<<
    q四轮(64步)是:
    
    W一?
    
    ff(a,b,c,d,m0,7,0xd76aa478)
    ff(d,a,b,c,m1,12,0xe8c7b756)
    ff(c,d,a,b,m2,17,0x242070db)
    ff(b,c,d,a,m3,22,0xc1bdceee)
    ff(a,b,c,d,m4,7,0xf57c0faf)
    ff(d,a,b,c,m5,12,0x4787c62a)
    ff(c,d,a,b,m6,17,0xa8304613)
    ff(b,c,d,a,m7,22,0xfd469501)
    ff(a,b,c,d,m8,7,0x698098d8)
    ff(d,a,b,c,m9,12,0x8b44f7af)
    ff(c,d,a,b,m10,17,0xffff5bb1)
    ff(b,c,d,a,m11,22,0x895cd7be)
    ff(a,b,c,d,m12,7,0x6b901122)
    ff(d,a,b,c,m13,12,0xfd987193)
    ff(c,d,a,b,m14,17,0xa679438e)
    ff(b,c,d,a,m15,22,0x49b40821)
    
    W二?
    
    gg(a,b,c,d,m1,5,0xf61e2562)
    gg(d,a,b,c,m6,9,0xc040b340)
    gg(c,d,a,b,m11,14,0x265e5a51)
    gg(b,c,d,a,m0,20,0xe9b6c7aa)
    gg(a,b,c,d,m5,5,0xd62f105d)
    gg(d,a,b,c,m10,9,0x02441453)
    gg(c,d,a,b,m15,14,0xd8a1e681)
    gg(b,c,d,a,m4,20,0xe7d3fbc8)
    gg(a,b,c,d,m9,5,0x21e1cde6)
    gg(d,a,b,c,m14,9,0xc33707d6)
    gg(c,d,a,b,m3,14,0xf4d50d87)
    gg(b,c,d,a,m8,20,0x455a14ed)
    gg(a,b,c,d,m13,5,0xa9e3e905)
    gg(d,a,b,c,m2,9,0xfcefa3f8)
    gg(c,d,a,b,m7,14,0x676f02d9)
    gg(b,c,d,a,m12,20,0x8d2a4c8a)
    
    W三?
    
    hh(a,b,c,d,m5,4,0xfffa3942)
    hh(d,a,b,c,m8,11,0x8771f681)
    hh(c,d,a,b,m11,16,0x6d9d6122)
    hh(b,c,d,a,m14,23,0xfde5380c)
    hh(a,b,c,d,m1,4,0xa4beea44)
    hh(d,a,b,c,m4,11,0x4bdecfa9)
    hh(c,d,a,b,m7,16,0xf6bb4b60)
    hh(b,c,d,a,m10,23,0xbebfbc70)
    hh(a,b,c,d,m13,4,0x289b7ec6)
    hh(d,a,b,c,m0,11,0xeaa127fa)
    hh(c,d,a,b,m3,16,0xd4ef3085)
    hh(b,c,d,a,m6,23,0x04881d05)
    hh(a,b,c,d,m9,4,0xd9d4d039)
    hh(d,a,b,c,m12,11,0xe6db99e5)
    hh(c,d,a,b,m15,16,0x1fa27cf8)
    hh(b,c,d,a,m2,23,0xc4ac5665)
    
    W四?
    
    ii(a,b,c,d,m0,6,0xf4292244)
    ii(d,a,b,c,m7,10,0x432aff97)
    ii(c,d,a,b,m14,15,0xab9423a7)
    ii(b,c,d,a,m5,21,0xfc93a039)
    ii(a,b,c,d,m12,6,0x655b59c3)
    ii(d,a,b,c,m3,10,0x8f0ccc92)
    ii(c,d,a,b,m10,15,0xffeff47d)
    ii(b,c,d,a,m1,21,0x85845dd1)
    ii(a,b,c,d,m8,6,0x6fa87e4f)
    ii(d,a,b,c,m15,10,0xfe2ce6e0)
    ii(c,d,a,b,m6,15,0xa3014314)
    ii(b,c,d,a,m13,21,0x4e0811a1)
    ii(a,b,c,d,m4,6,0xf7537e82)
    ii(d,a,b,c,m11,10,0xbd3af235)
    ii(c,d,a,b,m2,15,0x2ad7d2bb)
    ii(b,c,d,a,m9,21,0xeb86d391)
    
    常数ti可以如下选择Q?
    
    在第i步中Qti?294967296*abs(sin(i))的整数部分,i的单位是弧度?4294967296{于2?2ơ方)
    所有这些完成之后,a、b、c、d分别加上a、b、c、d。然后用下一分组数据l箋q行法Q最后的输出是a、b、c和d的联?
    
    当你按照我上面所说的Ҏ实现md5法以后Q你可以用以下几个信息对你做出来的程序作一个简单的试Q看看程序有没有错误?
    
    md5 ("") = d41d8cd98f00b204e9800998ecf8427e
    md5 ("a") = 0cc175b9c0f1b6a831c399e269772661
    md5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
    md5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
    md5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
    md5 ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789") =
    d174ab98d277d9f5a5611c2c9f419d9f
    md5 ("123456789012345678901234567890123456789012345678901234567890123456789
    01234567890") = 57edf4a22be3c955ac49da2e2107b67a
    
    如果你用上面的信息分别对你做的md5法实例做测试,最后得出的l论和标准答案完全一P那我p在这里象你道一声祝Z。要知道Q我的程序在W一ơ编译成功的时候是没有得出和上面相同的l果的?nbsp;
    
    
md5的安全?/strong>
    
    md5相对md4所作的改进Q?nbsp;    
    1. 增加了第四轮Q?nbsp;    
    2. 每一步均有唯一的加法常敎ͼ    
    3. 为减q二轮中函数g的对U性从(x&y)|(x&z)|(y&z)变ؓ(x&z)|(y&(~z))Q?nbsp;   
    4. W一步加上了上一步的l果Q这引h快的雪崩效应Q?nbsp;    
    5. 改变了第二轮和第三轮中访问消息子分组的次序,使其更不怼Q?nbsp;    
    6. q似优化了每一轮中的@环左UMU量以实现更快的雪崩效应。各轮的位移量互不相同?nbsp;


bilicon 2007-08-03 12:34 发表评论
]]>
[转]使用CPU旉戌行高_ֺ计时http://www.shnenglu.com/bilicon/archive/2007/07/26/28807.htmlbiliconbiliconThu, 26 Jul 2007 02:57:00 GMThttp://www.shnenglu.com/bilicon/archive/2007/07/26/28807.htmlhttp://www.shnenglu.com/bilicon/comments/28807.htmlhttp://www.shnenglu.com/bilicon/archive/2007/07/26/28807.html#Feedback0http://www.shnenglu.com/bilicon/comments/commentRss/28807.htmlhttp://www.shnenglu.com/bilicon/services/trackbacks/28807.html

对关注性能的程序开发h员而言Q一个好的计旉件既是益友,也是良师。计时器既可以作为程序组件帮助程序员_的控制程序进E,又是一件有力的调试武器Q在有经验的E序员手里可以尽快的定E序的性能瓉Q或者对不同的算法作出有说服力的性能比较?/span>
?/span>Windowsq_下,常用的计时器有两U,一U是timeGetTime多媒体计时器Q它可以提供毫秒U的计时。但q个_ֺ对很多应用场合而言q是太粗p了。另一U是QueryPerformanceCount计数器,随系l的不同可以提供微秒U的计数。对于实时图形处理、多媒体数据处理、或者实时系l构造的E序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一基本功?/span>
本文要介l的Q是另一U直接利?/span>Pentium CPU内部旉戌行计时的高精度计时手Dc以下讨Z要得益于?/span>Windows囑Ş~程》一书,W?/span>1517,有兴的读者可以直接参考该书。关?/span>RDTSC指o的详l讨论,可以参?/span>Intel产品手册。本文仅仅作抛砖之用?/span>

?/span>Intel Pentium以上U别?/span>CPU中,有一个称?/span>旉戻ITime StampQ?/span>的部Ӟ它以64位无W号整型数的格式Q记录了?/span>CPU上电以来所l过的时钟周期数。由于目前的CPU主频都非帔RQ因此这个部件可以达到纳U的计时精度。这个精性是上述两种Ҏ所无法比拟的?/span>
?/span>Pentium以上?/span>CPU中,提供了一条机器指?/span>RDTSCQ?/span>Read Time Stamp CounterQ来dq个旉戳的数字Qƈ其保存?/span>EDX:EAX寄存器对中。由?/span>EDX:EAX寄存器对恰好?/span>Win32q_?/span>C++语言保存函数q回值的寄存器,所以我们可以把q条指o看成是一个普通的函数调用。像q样Q?/span>

inline unsigned __int64 GetCycleCount()
{
__asm RDTSC
}

但是不行Q因?/span>RDTSC不被C++的内嵌汇~器直接支持Q所以我们要?/span>_emit伪指令直接嵌入该指o的机器码形式0X0F?/span>0X31Q如下:

inline unsigned __int64 GetCycleCount()
{
__asm _emit 0x0F
__asm _emit 0x31
}

以后在需要计数器的场合,可以像用普通的Win32 API一P调用两次GetCycleCount函数Q比较两个返回值的差,像这P

unsigned long t;
t = (unsigned long)GetCycleCount();
//Do Something time-intensive ...
t -= (unsigned long)GetCycleCount();

?/span>Windows囑Ş~程》第15늼写了一个类Q把q个计数器封装v来。有兴趣的读者可以去参考那个类的代码。作者ؓ了更_的定Ӟ做了一点小的改进Q把执行RDTSC指o的时_通过q箋两次调用GetCycleCount函数计算出来q保存了hQ以后每ơ计时结束后Q都从实际得到的计数中减掉这一段旉Q以得到更准的计时数字。但我个得这一点点改进意义不大。在我的机器上实,q条指o大概花掉了几十到100多个周期Q在Celeron 800MHz的机器上Q这不过是十分之一微秒的时间。对大多数应用来_q点旉完全可以忽略不计Q而对那些实要精到U秒数量U的应用来说Q这个补偿也q于_糙了?/span>

q个Ҏ的优ҎQ?/span>
1.
高精度。可以直接达到纳U的计时精度(?/span>1GHz?/span>CPU上每个时钟周期就是一U秒Q,q是其他计时Ҏ所难以企及的?/span>
2.
成本低?/span>timeGetTime 函数需要链接多媒体?/span>winmm.libQ?/span>QueryPerformance* 函数ҎMSDN的说明,需要硬件的支持Q虽然我q没有见q不支持的机器)?/span>KERNEL库的支持Q所以二者都只能?/span>Windowsq_下用(关于DOSq_下的高精度计旉题,可以参考《图形程序开发h员指南》,里面有关于控制定时器8253的详l说明)。但RDTSC指o是一?/span>CPU指oQ凡?/span>i386q_?/span>Pentium以上的机器均支持Q甚x有^台的限制Q我怿i386版本UNIX?/span>Linux下这个方法同样适用Q但没有条g试验Q,而且函数调用的开销是最的?/span>
3.
h?/span>CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz?/span>)U,q样只要知道?/span>CPU的主频,可以直接计算出时间。这?/span>QueryPerformanceCount不同Q后者需要通过QueryPerformanceFrequency获取当前计数器每U的计数ơ数才能换算成时间?/span>

q个Ҏ的缺ҎQ?/span>
1.
现有?/span>C/C++~译器多C直接支持使用RDTSC指oQ需要用直接嵌入机器码的方式~程Q比较麻烦?/span>
2.
数据抖动比较厉害。其实对M计量手段而言Q精度和E_性永q是一对矛盾。如果用低精度的timeGetTime来计Ӟ基本上每ơ计时的l果都是相同的;?/span>RDTSC指o每次l果都不一Pl常有几癄至上千的差距。这是这U方法高_ֺ本n固有的矛盾?/span>

关于q个Ҏ计时的最大长度,我们可以单的用下列公式计:

?/span>CPU上电以来的秒?/span> = RDTSCd的周期数 / CPU主频速率Q?/span>HzQ?/span>

64位无W号整数所能表辄最大数字是1.8×10^19Q在我的Celeron 800上可以计时大U?/span>700q_书中说可以在200MHz?/span>Pentium上计?/span>117q_q个数字不知道是怎么得出来的Q与我的计算有出入)。无论如何,我们大可不必兛_溢出的问题?/span>

下面是几个小例子Q简要比较了三种计时Ҏ的用法与_ֺ
//Timer1.cpp
使用?/span>RDTSC指o?/span>Timerc?/span>//KTimercȝ定义可以参见?/span>Windows囑Ş~程?/span>P15
//
~译行:CL Timer1.cpp /link USER32.lib
#include <stdio.h>
#include "KTimer.h"
main()
{
unsigned t;
KTimer timer;
timer.Start();
Sleep(1000);
t = timer.Stop();
printf("Lasting Time: %d\n",t);
}

//Timer2.cpp 使用?/span>timeGetTime函数
//
需包含<mmsys.h>Q但׃Windows头文仉l复杂的关系
//
单包?/span><windows.h>比较hQ)
//
~译行:CL timer2.cpp /link winmm.lib
#include <windows.h>
#include <stdio.h>

main()
{
DWORD t1, t2;
t1 = timeGetTime();
Sleep(1000);
t2 = timeGetTime();
printf("Begin Time: %u\n", t1);
printf("End Time: %u\n", t2);
printf("Lasting Time: %u\n",(t2-t1));
}

//Timer3.cpp 使用?/span>QueryPerformanceCounter函数
//
~译行:CL timer3.cpp /link KERNEl32.lib
#include <windows.h>
#include <stdio.h>

main()
{
LARGE_INTEGER t1, t2, tc;
QueryPerformanceFrequency(&tc);
printf("Frequency: %u\n", tc.QuadPart);
QueryPerformanceCounter(&t1);
Sleep(1000);
QueryPerformanceCounter(&t2);
printf("Begin Time: %u\n", t1.QuadPart);
printf("End Time: %u\n", t2.QuadPart);
printf("Lasting Time: %u\n",( t2.QuadPart- t1.QuadPart));
}

////////////////////////////////////////////////
//
以上三个CZE序都是试1U钟休眠所耗费的时?/span>



bilicon 2007-07-26 10:57 发表评论
]]>
[zt]P2P之UDPIKNAT的原理与实现(shootingstars)--增强?附源代码)http://www.shnenglu.com/bilicon/archive/2007/04/13/21781.htmlbiliconbiliconFri, 13 Apr 2007 04:00:00 GMThttp://www.shnenglu.com/bilicon/archive/2007/04/13/21781.htmlhttp://www.shnenglu.com/bilicon/comments/21781.htmlhttp://www.shnenglu.com/bilicon/archive/2007/04/13/21781.html#Feedback0http://www.shnenglu.com/bilicon/comments/commentRss/21781.htmlhttp://www.shnenglu.com/bilicon/services/trackbacks/21781.html 

源码下蝲: http://www.ppcn.net/upload/2005_08/05080112299104.rar 参考: http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt

P2P之UDPIKNAT的原理与实现(shootingstars)

文章说明:

关于UDPIKNAT的中文资料在|络上是很少的,仅有<<P2P之UDPIKNAT的原理与实现(shootingstars)>>q篇文章有实际的参考h倹{本两年来也一直从事P2P斚w的开发工作,比较有代表性的是个人开发的BitTorrent下蝲软g - FlashBT(变态快?. 对P2P下蝲或者P2P的开发感兴趣的朋友可以访问Y件的官方主页: http://www.hwysoft.com/chs/ 下蝲看看Q说不定有收莗写q篇文章的主要目的是懒的再每ơ单独回{一些网友的提问, 一ơ性写下来, 卌省了自己的时_也方便了对于P2P的UDPIK感兴趣的网?wbr>阅读和理解。对此有兴趣和经验的朋友可以l我发邮件或者访问我的个人Blog留言: http://hwycheng.blogchina.com. 您可以自p{载此文章,但是请保留此说明?

再次感谢shootingstars|友的早期A? 表示谢意?


NAT(The IP Network Address Translator) 的概念和意义是什?

NAT, 中文译为网l地址转换。具体的详细信息可以讉KRFC 1631 - http://www.faqs.org/rfcs/rfc1631.html, q是对于NAT的定义和解释的最权威的描q。网l术语都是很抽象?wbr>艰ӆ的,除非是专业h士,否则很难从字面中来准理解NAT的含?wbr>?

要想完全明白NAT 的作用,我们必须理解IP地址的两大分c,一cLU有IP地址Q在q里我们UC内网IP地址。一cL非私有的IP地址Q在q里我们UC公网IP地址。关于IP地址的概念和作用的介l参见我的另一文? http://hwycheng.blogchina.com/2402121.html

内网IP地址: 是指使用A/B/CcM的私有地址, 分配的IP地址在全球不惧有唯一性,也因此无法被其它外网L直接讉K。公|IP地址: 是指h全球唯一的IP地址Q能够直接被其它L讉K的?

NAT 最初的目的是ؓ使用内网IP地址的计机提供通过数几台h公网的IP地址的计机讉K外部|络的功能。NAT 负责某些内|IP地址的计机向外部网l发出的IP数据包的源IP地址转换为NAT自己的公|的IP地址Q目的IP地址不变, q将IP数据包{发给路由器,最l到辑֤部的计算?wbr>。同时负责将外部的计机q回的IP数据包的目的IP地址转换为内|的IP地址Q源IP地址不变Qƈ最l送达到内|中的计机?


图一: NAT 实现了私有IP的计机分n几个公网IP地址讉KInternet的功能?

随着|络的普及,IPv4的局限性暴露出来。公|IP地址成ؓ一U?wbr>E~的资源Q此时NAT 的功能局限也暴露出来Q同一个公|的IP地址Q某个时间只能由一?wbr>U有IP地址的计机使用。于是NAPT(The IP Network Address/Port Translator)应运而生QNAPT实现了多台私有IP地址的计机可以同时通过一个公|IP地址来访问Internet的功能。这在很大程度上暂时~解了IPv4地址资源的紧张?

NAPT 负责某些内|IP地址的计机向外部网l发出的TCP/UDP数据包的源IP地址转换为NAPT自己的公|的IP地址Q源端口转ؓNAPT自己的一个端口。目的IP地址和端口不? q将IP数据包发l\由器Q最l到辑֤部的计算?wbr>。同时负责将外部的计机q回的IP数据包的目的IP地址转换内网的IP地址Q目的端口{为内|计机的端口,源IP地址和源端口?wbr>变,q最l送达到内|中的计机?

图二: NAPT 实现了私有IP的计机分n一个公|IP地址讉KInternet的功能?

在我们的工作和生zM, NAPT的作用随处可见,l大部分公司的网l架?wbr>Q都是通过1至N台支持NAPT的\由器来实现公司的所有计机q?wbr>接外部的Internet|络的。包括本人在写这文章的时?wbr>Q也是在家中使用一台IBMW记本通过一台宽带连接的台式机来讉KInternet的。我们本文章主要讨论的NAPT的问题?

NAPT(The IP Network Address/Port Translator) Zȝ了P2P软g的应?

通过NAPT 上网的特点决定了只能由NAPT内的计算Z动向NAPT外部的主机发赯接,外部的主机想直接和NAPT内的计算机直接徏立连接是不被允许的。IM(x通讯)而言Q这意味着׃NAPT内的计算机和NAPT外的计算机只能通过服务器中转数据来q行通讯。对于P2P方式的下载程序而言Q意味着NAPT内的计算Z能接收到NAPT外部的连接,Dq接数用q少Q下载速度很难上去。因此P2P软g必须要解决的一个问题就是要能够在一定的E度上解决NAPT内的计算Z能被外部q接的问题?

NAT(The IP Network Address Translator) q行UDPIK的原理是什?

TCP/IP传输时主要用到TCP和UDP协议。TCP协议是可?wbr>的,面向q接的传输协议。UDP是不可靠的,无连接的协议。根据TCP和UDP协议的实现原理,对于NAPT来进行穿?wbr>Q主要是指的UDP协议。TCP协议也有可能Q但是可行性非常小Q要求更高,我们此处不作讨论Q如果感兴趣可以到Google上搜索,有些文章对这个问题做了探讨性的描述。下面我们来看看利用UDP协议来穿透NAPT的原理是什?


图三: NAPT 是如何将U有IP地址的UDP数据包与公网Lq行透明传输的?

UDP协议包经NAPT透明传输的说?

NAPT为每一个Session分配一个NAPT自己的端口号Q依据此端口h判断收到的公网IPLq回的TCP/IP数据包{发给那台内网IP地址的计机。在q里Session是虚拟的QUDP通讯q不需要徏立连接,但是对于NAPT而言Q的要有一个Session的概念存在。NAPT对于UDP协议 包的透明传输面的一个重要的问题是如何处理q个虚拟的Session。我们都知道TCPq接的Session以SYN包开?wbr>Q以FIN包结束,NAPT可以很容易的获取到TCP Session的生命周期,q进行处理。但是对于UDP而言Q就ȝ了,NAPTq不知道转发出去的UDP协议包是否到达了?wbr>的主机,也没有办法知道。而且鉴于UDP协议的特点,可靠很差Q因此NAPT必须强制l持Session的存?wbr>Q以便等待将外部送回来的数据q{发给曄发vh的内|IP地址的计机。NAPT具体如何处理UDP Session的超时呢Q不同的厂商提供的设备对于NAPT的实?wbr>不近相同Q也许几分钟Q也许几个小Ӟ些NAPT的实现还会根据设备的忙碌状态进行智能计超时时间的长短?


囑֛: NAPT 内部发出的UDP协议包的源地址和源端口改变传输l公|IPL?

图五: NAPT 收到的公网IPLq回的UDP协议包的目的地址和目的端口改?wbr>传输l内|IP计算机现在我们大概明白了NAPT如何实现内网计算机和外网L间的透明通讯。现在来看一下我们最兛_的问?wbr>Q就是NAPT是依据什么策略来判断是否要ؓ一个请求发出的UDP数据包徏立Session的呢Q主要有一下几个策?

A. 源地址(内网IP地址)不同Q忽略其它因? 在NAPT上肯定对应不同的Session B. 源地址(内网IP地址)相同Q源端口不同Q忽略其它的因素Q则在NAPT上也肯定对应不同的Session C. 源地址(内网IP地址)相同Q源端口相同Q目的地址(公网IP地址)相同Q目的端口不同,则在NAPT上肯定对应同一个Session D. 源地址(内网IP地址)相同Q源端口相同Q目的地址(公网IP地址)不同Q忽略目的端口,则在NAPT上是如何处理Session的呢Q?

D的情冉|式我们关心和要讨论的问题。依据目的地址(公网IP地址)对于Session的徏立的军_方式我们NAPT讑֤划分Z大类:

Symmetric NAPT: 对于到同一个IP地址QQ意端口的q接分配使用同一个Session; 对于C同的IP地址, L端口的连接用不同的Session. 我们U此UNAPT?Symmetric NAPT. 也就是只要本地绑定的UDP端口相同Q?发出的目的IP地址不同Q则会徏立不同的Session.


囑օ: Symmetric 的英文意思是对称。多个端口对应多个主机,q的,对称?

Cone NAPT: 对于到同一个IP地址QQ意端口的q接分配使用同一个Session; 对于C同的IP地址QQ意端口的q接也用同一个Session. 我们U此UNAPT?Cone NAPT. 也就是只要本地绑定的UDP端口相同Q?发出的目的地址不管是否相同Q?都用同一个Session.


图七: Cone 的英文意思是锥。一个端口对应多个主机,是不是像个锥?

现在l大多数的NAPT属于后者,即Cone NAT。本人在试的过E中Q只好用了一台日本的Symmetric NAT。还好不是自q买的Q我从不买日? 希望看这文章的朋友也自觉的不要购买日本的东ѝWin9x/2K/XP/2003pȝ自带的NAPT也是属于 Cone NAT的。这是值的庆幸的,因ؓ我们要做的UDPIK只能在Cone NAT间进行,只要有一C是Cone NATQ对不vQUDPIK没有希望了Q服务器转发?wbr>。后面会做详l分?

下面我们再来分析一下NAPT 工作时的一些数据结构,在这里我们将真正说明UDP可以IKCone NAT的依据。这里描q的数据l构只是Z说明原理Q不h实际参考h|真正感兴可以阅读Linux的中关于NAT实现部分的源码。真正的NAT实现也没有利用数据库的,呵呵Qؓ了速度Q?

Symmetric NAPT 工作时的端口映射数据l构如下:

内网信息?

[NAPT 分配端口] [ 内网IP地址 ] [ 内网端口 ] [ 外网IP地址 ] [ SessionTime 开始时?]

PRIMARY KEY( [NAPT 分配端口] ) -> 表示依据[NAPT 分配端口]建立主键Q必d一且徏立烦引,加快查找. UNIQUE( [ 内网IP地址 ], [ 内网端口 ] ) -> 表示q两个字D联合v来不能重? UNIQUE( [ 内网IP地址 ], [ 内网端口 ], [ 外网IP地址 ] ) -> 表示q三个字D联合v来不能重?

映射?

[NAPT 分配端口] [ 外网端口 ]

UNIQUE( [NAPT 分配端口], [ 外网端口 ] ) -> 表示q两个字D联合v来不能重?

Cone NAPT 工作时的端口映射数据l构如下:

内网信息?

[NAPT 分配端口] [ 内网IP地址 ] [ 内网端口 ] [ SessionTime 开始时?]

PRIMARY KEY( [NAPT 分配端口] ) -> 表示依据[NAPT 分配端口]建立主键Q必d一且徏立烦引,加快查找. UNIQUE( [ 内网IP地址 ], [ 内网端口 ] ) -> 表示q两个字D联合v来不能重?

外网信息?

[ wid 主键标识 ] [ 外网IP地址 ] [ 外网端口 ]

PRIMARY KEY( [ wid 主键标识 ] ) -> 表示依据[ wid 主键标识 ]建立主键Q必d一且徏立烦引,加快查找. UNIQUE( [ 外网IP地址 ], [ 外网端口 ] ) -> 表示q两个字D联合v来不能重?

映射? 实现一对多Q的

[NAPT 分配端口] [ wid 主键标识 ]

UNIQUE( [NAPT 分配端口], [ wid 主键标识 ] ) -> 表示q两个字D联合v来不能重? UNIQUE( [ wid 主键标识 ] ) -> 标识此字D不能重?

看完了上面的数据l构是更明白了还是更晕了Q?呵呵! 多想一会儿׃明白了。通过NAT,内网计算机向外q结是很Ҏ的,NAPT会自动处理,我们的应用程序根本不必关心它是如?wbr>处理的。那么外部的计算机想讉K内网中的计算机如何实现呢Q我们来看一下下面的程Q?

c 是一台在NAPT后面的内|计机Qs是一台有外网IP地址的计?wbr>机。c d?s 发vq接hQNAPT依据上面描述的规则在自己的数据结构中记录下来Q徏立一个Session. 然后 c ?s 之间可以实现双向的透明的数据传输了。如下面所C?

  c[192.168.0.6:1827] <-> [priv ip: 
192.168.0.1]NAPT[pub ip: 61.51.99.86:9881] <-> s[61.51.76.102:8098]

由此可见Q一台外|IP地址的计机惛_NAPT后面的内|计机通讯的条件就是要求NAPT后面的内|计机d向外|IP地址?wbr>计算机发起一个UDP数据包。外|IP地址的计机利用收到的UDP数据包获取到NAPT的外|IP地址和映的端口Q以后就可以和内|IP的计机透明的进行通讯了?

现在我们再来分析一下我们最兛_的两个NAPT后面的内|计机?wbr>何实现直接通讯? 两者都无法d发出q接hQ谁也不知道Ҏ的NAPT的公|IP地址和NAPT上面映射的端口号。所以我们要靠一个公|IP地址?wbr>服务器帮助两者来建立q接。当两个NAPT后面的内|计机分别q?wbr>接了公网IP地址的服务器后,服务器可以从收到的UDP数据包中?wbr>取到q两个NAPT讑֤的公|IP地址和这两个q接建立的Session的映端口。两个内|计机可以从服务器上获取到Ҏ的NAPT讑֤公网IP地址和映的端口了?

我们假设两个内网计算机分别ؓA和BQ对应的NAPT分别为AN?BNQ?如果A在获取到B对应的BN的IP地址和映的端口?wbr>Q迫不急待的向q个IP 地址和映的端口发送了个UDP数据包,会有什么情况发生呢Q依据上面的原理和数据结构我们会知道QAN会在自己的数据结构中生成一条记录,标识一个新Session的存在。BN在收到数据包后,从自q数据l构中查询,没有扑ֈ相关记录Q因此将包丢?wbr>。B是个慢性子Q此时才慢吞吞的向着AN的IP地址和映的端口?wbr>送了一个UDP数据包,l果如何呢?当然是我们期望的l构?wbr>QAN在收到数据包后,从自q数据l构中查扑ֈ了记?wbr>Q所以将数据包进行处理发送给了A。A 再次向B发送数据包Ӟ一切都时畅通无M。OK, 大工告成Q且慢,q时对于Cone NAPT而言Q对于Symmetric NAPT呢?呵呵Q自己分析一下吧...

NAPT(The IP Network Address/Port Translator) q行UDPIK的具体情况分析!

首先明确的将NAPT讑֤按照上面的说明分? Symmetric NAPT ?Cone NAPT, Cone NAPT 是我们需要的。Win9x/2K/XP/2003 自带的NAPT也ؓCone NAPT?

W一U情? 双方都是Symmetric NAPT:

此情况应l不存在什么问题,肯定是不支持UDPIK?

W二U情? 双方都是Cone NAPT:

此情冉|我们需要的Q可以进行UDPIK?

W三U情? 一个是Symmetric NAPT, 一个是Cone NAPT:

此情冉|较复杂,但我们按照上面的描述和数据机构进行一下分析也?wbr>Ҏ׃明白? 分析如下,

假设: A -> Symmetric NAT, B -> Cone NAT

1. A 惌?B, A 从服务器那儿获取?B 的NAT地址和映端? A 通知服务器,服务器告?B A的NAT地址和映端? B ?A 发vq接QA 肯定无法接收到。此?A ?B 发vq接Q?A 对应的NAT建立了一个新的SessionQ分配了一个新的映端口, B ?NAT 接收到UDP包后Q在自己的映表中查询,无法扑ֈ映射?wbr>Q因此将包丢弃了?

2. B 惌?A, B 从服务器那儿获取?A 的NAT地址和映端? B 通知服务? 服务器告?A B的NAT地址和映端?A ?B 发vq接, A 对应的NAT建立了一个新的SessionQ分配了一个新的映端口B肯定无法接收到。此?B ?A 发vq接, ׃ B 无法获取 A 建立的新的Session的映端口,仍是使用服务器上获取的映?wbr>端口q行q接Q?因此 A 的NAT在接收到UDP包后Q在自己的映表中查?wbr>Q无法找到映项, 因此包丢弃了?

Ҏ以上分析Q只有当q接的两端的NAT都ؓCone NAT的情况下Q才能进行UDP的内|穿透互联?


NAPT(The IP Network Address/Port Translator) q行UDPIK如何进行现实的验证和分?

需要的|络l构如下:

三个NAT后面的内|机器,两个外网服务器。其中两台Cone NAPTQ一?Symmetric NAPT?

验证Ҏ:

可以使用本程序提供的源码Q编译,然后分别q行服务器程序和客户?wbr>。修改过后的源码增加了客L之间直接通过IP地址和端口发送消?wbr>的命令,利用此命令,你可以手动的验证NAPT的穿透情?wbr>。ؓ了方便操作,推荐你用一个远E登陆YӞ可以直接在一台机?wbr>上操作所有的相关的计机Q这样很方便Q一个h可以完成所有的?wbr>作了。呵呵,本h是q么完成的。欢q有兴趣和经验的朋友来信批评指正Q共同进步?/p>

bilicon 2007-04-13 12:00 发表评论
]]>
777þµַ| þAV| þۺϾɫۺŷȥ| ƷѾþþþõӰ| ձƷһþþ| ޹Ʒþһ| Ʒžžžþþž | þþþùһ| þùŮѹۿƷ| þˬˬˬ | þۺϸۺϾþ| þþwww| þþþù| ٸ߳ҽоþþ| ŷҹAŴƬþ| þ91Ʒ91þû| ŷպƷþ| 72ŷþþþôƽ | þþþùƷ۲ӰԺ| ھƷþþþӰԺ| ƷþþĻ| þþƷ18| ƷVIDEOSSEXþ÷| ޾Ʒþǧն| ҹƷþþþó| һձȾþۺ| Ʒþۺ| þþƷһAV| þþþþþþ| þþƷһӰ| ˾þô߽槼| þþƷAVũ帾Ů| þĻavŮ| պþþþĻ| þþþAVȥ| ˾þþƷ| þþۺϾɫ۹| ȾþֻоƷ| ھƷ˾þþþվ| 뾫Ʒþþþ| һձþþ|