当前位置:编程学习 > 网站相关 >>

md5算法实现

md5算法的具体步骤见RFC1321(http://www.ietf.org/rfc/rfc1321.txt)
这里说一下具体实现时,应该注意的地方:
1.注意数据存储格式
其实,在官方文档中已经提到过这个,但是没注意,现把它摘抄如下;
   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.
翻译过来,就是说在md5算法中一个字节内是按MSB存储的,在一个字内是按LSB存储的。
例如:00010111 11011001 11100011 10101100(msb)
按照文档中的规定,每个字节是按MSB存储的,则写成十六进制如下:
0x17 d9 e3 ac
而在一个字,即32位里,是按高字节序存储的,所以最终的存储值如下:
0xace3d917
另外,在填充长度时,两个字也是按LSB存储,每个字内是按上面所说的存储,具体原文如下:
   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.)
2.迭代时,数据存储格式
虽然官方文档规定了数据该怎样存储,但是在真正实现时,就连官方给的DEMO也没有完全遵守。以至于自己实现md5算法时,算出来的结果总是不对。
md5实现时,分3步:
第一步,分割输入数据,填充数据和长度。
在这一步,原生的数据和填充的数据(0x80 00 00 ...)是按高字节序存储的。而填充的长度须按上面所说的规定存储,即字节内MSB,字内LSB,双字LSB。
第二步,初始化4字缓存
文档中写的是按LSB存储,但是真正初始化是却是按MSB存储的。
第三步,4*16迭代
在迭代中,传进来的X[i]是需要进行LSB转换的,也就是把原来存储的MSB数据转换成LSB(第一步是原生数据加填充数据(MSB)+长度填充(LSB),现在需要把全部数据再次进行LSB转换,长度填充相当于转换了两次)
第四步,输出结果
输出的结构,需要进行LSB转换,就是把4字缓存中每个字进行LSB转换,然后输出的结果才是正确的。

还有,就是要注意T表的计算,虽然文档中给出了具体的计算公式(2^32*abs(sin(i))),但是还是建议直接通过一个数组预先给出,因为这个计算如果处理的不好,会有精度误差,导致最后结果错误,并且这个还与系统类型,编译器版本,CPU类型和所用语言有关。我想这也是官方的DEMO为了程序的可移植性和稳定性,采用的也是预先给出T表值,而没有现用现算的原因吧。像这次实现MD5,有一个人用Java实现的,结果没有碰到这个问题,而我用C语言实现,这个问题就出现了...

具体实现见github:http://github.com/wengpingbo/md5-demo

 


P.S.关于LSB,MSB,Big Endian,Little Endian

来源:http://www.eygle.com/digest/2007/01/whats_mean_endian.html


一、引子
  在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了
计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、
字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方
将无法进行正确的编/译码从而导致通信失败。目前在各种体系的计算机中通常采
用的字节存储机制主要有两种:
big-edian和little-endian。本文简要描述这两种存储机制的来历、特点和区别。
  
  为了叙述方便,下面先对本文中将要用到的两个术语做简单的定义。
  1、MSB
  MSB是Most Significant Bit/Byte的首字母缩写,通常译为最重要的位或者最
重要的字节。它通常用来表明在一个bit序列(如一个byte是8个bit组成的一个序
列)或者一个byte序列(如word是两个byte组成的一个序列)中对整个序列取值影
响最大的那个bit/byte。
  2、LSB
  LSB是Least Significant Bit/Byte的首字母缩写,通常译为最不重要的位或
者最不重要的字节。它通常用来表明在一个bit序列(如一个byte是8个bit组成的
一个序列)或者一个byte序列(如word是两个byte组成的一个序列)中对整个序
列取值影响最小的那个bit/byte。


二、endian的由来
  1、Definition
  endian: The ordering of bytes in a multi-byte number.
定义:在计算机系统体系结构中用来描述在多字节数中各个字节的存储顺序。


  2、Etymology
  The term comes from Swift's "Gulliver's Travels" via the famous paper
"On Holy Wars and a Plea for Peace" by Danny Cohen, USC/ISI IEN 137,
1980-04-01.
  The Lilliputians, being very small, had correspondingly small political
problems. The Big-Endian and Little-Endian parties debated over whether
soft-boiled eggs should be opened at the big end or the little end.[From:
Free On-Line Dictionary Of Computing or Jargon File]
  词源:据Jargon File记载,endian这个词来源于Jonathan
Swift在1726年写的讽刺小说 "Gulliver's Travels"(《格利佛游记》)。该小说
在描述Gulliver畅游小人国时碰到了如下的一个场景。在小人国里的小人因为非常
小(身高6英寸)所以总是碰到一些意想不到的问题。有一次因为对水煮蛋该从大的
一端(Big-End)剥开还是小的一端(Little-End)剥开的争论而引发了一场战争,
并形成了两支截然对立的队伍:支持从Big-End剥开的人Swift就称作Big-Endians
而支持从Little-End剥开的人就称作Little-Endians……(后缀ian表明的就是支持
某种观点的人:-)。Endian这个词由此而来。
  
  1980年,Danny Cohen在其著名的论文"On Holy Wars and a Plea for Peace"
中为了平息一场关于在消息中字节该以什么样的顺序进行传送的争论而引用了该词。
该文中,Cohen非常形象贴切地把支持从一个消息序列的MSB开始传送的那伙人叫做
Big-Endians,支持从LSB开始传送的相对应地叫做Little-Endians。此后Endian这
个词便随着这篇论文而被广为采用。


三、各种endian
  1、big-endian
  A computer architecture in which, within a given multi-byte numeric
representation, the most significant byte has the lowest address (the
word is stored "big-end-first").  
Most processors, including the IBM 370 family, the PDP-10, the
Motorola microprocessor families, and most of the various RISC designs
current in mid-1993, are big-endian. [From: Free On-Line Dictionary Of
Computing or Jargon File]
  big-endian:计算机体系结构中一种描述多字节存储顺序的术语,在这种机制
中最重要字节(MSB)存放在最低端的地址上。采用这种机制的处理器有IBM3700系
列、PDP-10、Mortolora微处理器系列和绝大多数的RISC处理器。


+----------+
| 0x34 |<-- 0x00000021
+----------+
| 0x12 |<-- 0x00000020
+----------+
图1:双字节数0x1234以big-endian的方式存在起始地址0x00000020中


  在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为
例):
bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+----------------------------------------+
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
+----------------------------------------+
^ 0x8B 0x8A ^
MSB LSB
图2:Big-Endian的bit序列编码方式


  注1:通常在TCP/IP协议栈所说的网络序(Network Order)就是遵循Big-Endian
规则。在TCP/IP网络通信中,通信双方把消息按照如图2的方式进行编码,然后按
从MSB(Bit0)到LSB的顺序在网络上传送。
  2、little-endian
   A computer architecture in which, within a given
16- or 32-bit word,bytes at lower addresses have lower significance (the
word is stored "little-end-first"). The PDP-11 and VAX families of
computers and Intel microprocessors and a lot of communications and
networking hardware are little-endian.
  The term is sometimes used to describe the ordering of units other

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,