Вы находитесь на странице: 1из 41

MD5

MD5. -, ,
.
" MD4" .

MD5
1991 , MD4,
MD5, ""
MD4 ( "" ).
,
MD4.
. , :
MD5("MD5") = 7F138A09169B250E9DCB378140907378
MD5(WinWord.EXE) = B9D86A2E86028000B500B498FE71C299
MD5 16 16*8 = 128 .

MD5
MD5 . A,
B, C D,
. " " MD5 16 32- ,

. " " ,
" " , . "
" ,
, ;
.
" " " " , ,
.
MD5 1.



A
B
C
D

MD5

1. MD5 .

, .
RFC 1321. MD5
:

NULL

67452301

EFCDAB89

98BADCFE

10325476
00000000 00000000 [0]

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

00000000

MD5

3. MD5 .
, , MD5
MD4 . .


MD5 ,
. :
F(x,y,z) = (x AND y) OR (NOT x AND z)1
G(x,y,z) = (x AND z) OR (y AND NOT z)2
H(x,y,z) = x XOR y XOR z
I(x,y,z) = y XOR (x OR NOT z)3
:
x
0
0
0
0
1
1
2
3

y
0
0
1
1
0

z
0
1
0
1
0

F
0
1
0
1
0

x
0
0
0
0
1

y
0
0
1
1
0

NOT x AND z = (NOT x) AND z


y AND NOT z = y AND (NOT z)
x OR NOT z = x OR (NOT z)

Z
0
1
0
1
0

G
0
0
1
0
0

X
0
0
0
0
1

y
0
0
1
1
0

z
0
1
0
1
0

H
0
1
1
0
1

x
0
0
0
0
1

y
0
0
1
1
0

z
0
1
0
1
0

I
1
0
0
1
1

1
1
1

0
1
1

1
0
1

0
1
1

1
1
1

0
1
1

1
0
1

1
1
1

1
1
1

0
1
1

1
0
1

0
0
1

1
1
1

0
1
1

1
0
1

1
0
0

#define
#define
#define
#define

F(x,y,z)
G(x,y,z)
H(x,y,z)
I(x,y,z)

((x & y) | (~x & z))


((x & z) | (y & ~z))
(x ^ y ^ z)
(y ^ (x | ~z))

OpenSSL
!
, :

#define
#define
#define
#define

F(b,c,d)
G(b,c,d)
H(b,c,d)
I(b,c,d)

((((c) ^ (d)) & (b)) ^ (d))


((((b) ^ (c)) & (d)) ^ (c))
((b) ^ (c) ^ (d))
(((~(d)) | (b)) ^ (c))

, (x AND y) OR (NOT x AND z) = ((y XOR z) AND z) XOR z.


. :
AND, OR, NOT, AND, XOR, AND, XOR. ,
.
FORTH
WinForth32.

\
:
\
:

-------------------------------------------------------------------------.= ( x -- x ) ?PRINT IF DUP SPACE ." = " 8 HEX U.R THEN ;


-------------------------------------------------------------------------D-FF-BC ( c b -- x )
?PRINT IF 2DUP CR ." X & Y = " 8 HEX U.R SPACE ." & " 8 HEX U.R THEN
AND .=
;
: D-FF-~B ( b -- ~b )
?PRINT IF DUP CR ." ~X = ~" 8 HEX U.R THEN
INVERT .=
;
: D-FF-~BD ( ~b d -- x )
?PRINT IF 2DUP SWAP CR ." ~X & Z = " 8 HEX U.R SPACE ." & " 8 HEX U.R
THEN
AND .=
;
: D-FF-F ( x1 x2 -- x3 )
?PRINT IF 2DUP SWAP CR ." . | .. = " 8 HEX U.R SPACE ." | " 8 HEX U.R
THEN
OR .=
;
: D-FF ( b-addr c-addr d-addr -- f )
@ ROT @ ROT @ ( d b c )
OVER
( d b c b )
D-FF-BC ( d b xi )
SWAP
( d xi b )
D-FF-~B ( d xi ~b )

\
:

\
:

\
:

ROT
( xi ~b d )
D-FF-~BD ( xi xii )
D-FF-F
( f )
;
-------------------------------------------------------------------------D-FG-~D ( d -- ~d )
?PRINT IF DUP CR ." ~Z = ~" 8 HEX U.R THEN
INVERT .=
;
D-FG-~DC ( ~d c -- x )
?PRINT IF 2DUP CR ." Y & ~Z = " 8 U.R SPACE ." & " 8 U.R THEN
AND .=
;
D-FG-BD ( b d -- x )
?PRINT IF 2DUP CR ." X & Z = " SWAP 8 U.R SPACE ." & " 8 U.R THEN
AND .=
;
D-FG-BDv~DC ( bd ~dc -- x )
?PRINT IF 2DUP CR ." XZ | ~ZY = " SWAP 8 U.R SPACE ." | " 8 U.R THEN
OR .=
;
D-FG ( b-addr c-addr d-addr -- g )
@ ROT @ ROT @ ROT ( b c d )
DUP
( b c d d )
D-FG-~D
( b c d xi )
ROT
( b d xi c )
D-FG-~DC
( b d xii )
-ROT
( xii b d )
D-FG-BD
( xii xiii )
D-FG-BDv~DC ( g )
;
-------------------------------------------------------------------------D-FH-B^C ( b c -- x )
?PRINT IF 2DUP CR ." X ^ Y = " SWAP 8 U.R SPACE ." ^ " 8 U.R THEN
XOR .=
;
D-FH-^D ( d x1 -- x2 )
?PRINT IF 2DUP CR ." . ^ Z = " 8 U.R SPACE ." ^ " 8 U.R THEN
XOR .=
;
D-FH ( b-addr c-addr d-addr -- h )
@ ROT @ ROT @ ( d b c )
D-FH-B^C ( d xi )
D-FH-^D ( h )
;
-------------------------------------------------------------------------D-FI-~D ( d -- ~d )
?PRINT IF DUP CR ." ~Z = ~" 8 HEX U.R THEN
INVERT .=
;
D-FI-Bv~D ( ~d b -- x )
?PRINT IF 2DUP CR ." X | ~Z = " 8 HEX U.R SPACE ." | " 8 HEX U.R THEN
OR .=
;
D-FI-^C ( c x1 -- x2 )
?PRINT IF 2DUP SWAP CR ." C ^ . = " 8 U.R SPACE ." ^ " 8 U.R THEN
XOR .=
;
D-FI ( b-addr c-addr d-addr -- i )
@ ROT @ ROT @ ROT ( b c d )
D-FI-~D
( b c xi )
ROT
( c xi b )
D-FI-Bv~D ( c xii )
D-FI-^C
( i )
;
--------------------------------------------------------------------------


: FF (
AND OR
: FG (
AND OR
: FH (
: FI (

b-addr
;
b-addr
;
b-addr
b-addr

c-addr d-addr -- f ) @ ROT @ ROT @ OVER AND SWAP INVERT ROT


c-addr d-addr -- g ) @ ROT @ ROT @ ROT DUP INVERT ROT AND -ROT
c-addr d-addr -- h ) @ ROT @ ROT @ XOR XOR ;
c-addr d-addr -- i ) @ ROT @ ROT @ ROT INVERT ROT OR XOR ;

,
:
A B C D-FF
.
, ,
HEX BINARY.


,
MD5 .

.
:
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s).
:
A, b, c, d MD5 ;
F F, G, H I;
X[k] k- ;
T[I] I- ( );
<<< -- ;
S .
OpenSSL
:
#define R0(a,b,c,d,k,s,t) { \
a+=((k)+(t)+F((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };\
#define R1(a,b,c,d,k,s,t) { \
a+=((k)+(t)+G((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
#define R2(a,b,c,d,k,s,t) { \
a+=((k)+(t)+H((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };

#define R3(a,b,c,d,k,s,t) { \
a+=((k)+(t)+I((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };


:
: D-TRANSFORM-F+XK ( f k -- x )
?PRINT IF 2DUP CR ." F + X[" 2 DECIMAL .R ." ]
CELLS ( f ki )
MD5_CTX_DATA
+
( f a-ki )
@
( f xi )
?PRINT IF DUP SPACE ." + " 8 HEX U.R THEN
+
( x )
.=
;
: D-TRANSFORM-+TI ( i x1 -- x2 )
?PRINT IF 2DUP CR ." . + T[" SWAP 2 DECIMAL .R
SWAP
( x1 i )
1CELLS ( x1 ii )
MD5_T ( x1 ii a-t )
+
( x1 a-ii )
@
( x1 xi )
?PRINT IF DUP SPACE ." + " 8 HEX U.R THEN
+
( x2 )
.=
;
: D-TRANSFORM-+A ( a-addr x1 -- x2 )
SWAP
( x1 a-addr )
@
( x1 a )
?PRINT IF 2DUP CR ." A + . = " 8 HEX U.R SPACE
+ .=
;
: D-TRANSFORM-ROL ( s x1 -- x2 )
?PRINT IF 2DUP CR ." . <<< " OVER 2 DECIMAL .R
SPACE ." <<< " 2 DECIMAL .R THEN
SWAP
LROTATE .=
;
: D-TRANSFORM-+B ( b-addr x1 -- x2 )
SWAP
( x1 b-addr )
@
( x1 b )
?PRINT IF 2DUP CR ." B + . = " 8 HEX U.R SPACE
+ .=
;
\ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
: D-TRANSFORM ( b-addr s a-addr i f k -- ai )
D-TRANSFORM-F+XK ( b-addr s a-addr i xi ) \ (
D-TRANSFORM-+TI ( b-addr s a-addr xii )
\ (
D-TRANSFORM-+A
( b-addr s xiii )
\ (
D-TRANSFORM-ROL ( b-addr xiv )
\ (
D-TRANSFORM-+B
( ai )
\ (
;

= " 8 HEX U.R THEN

." ] = " 8 HEX U.R THEN

." + " 8 HEX U.R THEN

SPACE ." = " 8 HEX U.R

." + " 8 HEX U.R THEN

F(b,c,d) + X[k] )
+ T[i] )
a + )
<<< s )
b + )


: TRANSFORM ( a-addr b-addr s a-addr i f k -- ai )
CELLS MD5_CTX_DATA + @ + SWAP CELLS MD5_T + @ + SWAP @ +

SWAP LROTATE SWAP @ +


;

,
,
MD4, T 64 .
""
. , i-
4,294,967,296 * abs(sin(i)). "" MD5
MD4,
.
A.
:
A = B + ((A + F(B,C,D) + X[0] + T[1]) <<< 7)
4.

67452301

61626380

00000000

00000000

00000000

EFCDAB89

00000000

00000000

00000000

00000000

98BADCFE

00000000

00000000

00000000

00000000

10325476

00000000

00000000

18000000

00000000

7
F

T[1]

D6D117B4

61626380

00000000

00000000

00000000

EFCDAB89

00000000

00000000

00000000

00000000

98BADCFE

00000000

00000000

00000000

00000000

10325476

00000000

00000000

18000000

00000000

A = B + (A + F(B,C,D) + X[0] + T[1]) <<< 7


F + X[0] = 98BADCFE + 80636261 = 191E3F5F
= . + T[1] = 191E3F5F + D66AA478 = F088E3D7
= A + . = 67452301 + F088E3D7 = 57CE06D8
= . <<< 7 = 57CE06D8 <<< 7 = E7036C2B
A = B + . = EFCDAB89 + E7036C2B = D6D117B4

F(B,C,D) = (B & C) | (~B & D)


B & C = EFCDAB89 & 98BADCFE = 88888888
~B = ~EFCDAB89 = 10325476
~B & D = 10325476 & 10325476 = 10325476
F = 88888888 | 10325476 = 98BADCFE

: [ABCD 0 7 1]

D:
D = A + ((D + F(A,B,C) + X[1] + T[2]) <<< 12)
5.

D6D117B4

61626380

00000000

00000000

00000000

EFCDAB89

00000000

00000000

00000000

00000000

98BADCFE

00000000

00000000

00000000

00000000

10325476

00000000

00000000

18000000

00000000

12
F

T[2]

D6D117B4

61626380

00000000

00000000

00000000

EFCDAB89

00000000

00000000

00000000

00000000

98BADCFE

00000000

00000000

00000000

00000000

344A8432

00000000

00000000

18000000

00000000

D = A + (D + F(A,B,C) + X[1] + T[2]) <<< 12

F(A,B,C) = (A & B) | (~A & C)

F + X[0] = CEEBCBCA + 00000000 = CEEBCBCA

A & B = D6D117B4 & EFCDAB89 = C6C10380

= . + T[2] = CEEBCBCA + E8C7B756 = B7B38320

~A = ~D6D117B4 = 292EE84B

= D + . = 10325476 + B7B38320 = C7E5D796

~A & C = 292EE84B & 989BADCFE = 082AC84A

= . <<< 12 = C7E5D796 <<< 12 = 5D796C7E

F = C6C10380 | 082AC84A = CEEBCBCA

D = A + . = D6D117B4 + 5D796C7E = 344A8432

: [DABC 1 12 2]

,
. ,
: 1 F, 2
G, 3 H, 4
I.
[abcd k s I] . 1
:
[ABCD 0
[ABCD 4
[ABCD 8
[ABCD 12

7 1]
7 5]
7 9]
7 13]

[DABC 1
[DABC 5
[DABC 9
[DABC 13

12 2]
12 6]
12 10]
12 14]

[CDAB 2 17 3]
[CDAB 6 17 7]
[CDAB 10 17 11]
[CDAB 14 17 15]

[BCDA 3 22 4]
[BCDA 7 22 8]
[BCDA 11 22 12]
[BCDA 15 22 16]

.
OpenSSL :
/* Round 0 */
R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
R0(C,D,A,B,X[ 2],17,0x242070dbL);
R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
R0(D,A,B,C,X[ 5],12,0x4787c62aL);
R0(C,D,A,B,X[ 6],17,0xa8304613L);
R0(B,C,D,A,X[ 7],22,0xfd469501L);
R0(A,B,C,D,X[ 8], 7,0x698098d8L);
R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
R0(C,D,A,B,X[10],17,0xffff5bb1L);
R0(B,C,D,A,X[11],22,0x895cd7beL);
R0(A,B,C,D,X[12], 7,0x6b901122L);

R0(D,A,B,C,X[13],12,0xfd987193L);
R0(C,D,A,B,X[14],17,0xa679438eL);
R0(B,C,D,A,X[15],22,0x49b40821L);

, -
.
:
: D-STEPF1
.ABCD CR CR
: D-STEPF2
.ABCD CR CR
: D-STEPF3
.ABCD CR CR
: D-STEPF4
.ABCD CR CR

( -THEN
( -THEN
( -THEN
( -THEN

)
;
)
;
)
;
)
;

RB

7 RA

RB RC RD D-FF

0 D-TRANSFORM RA !

?PRINT IF

RA 12 RD

RA RB RC D-FF

1 D-TRANSFORM RD !

?PRINT IF

RD 17 RC

RD RA RB D-FF

2 D-TRANSFORM RC !

?PRINT IF

RC 22 RB

RC RD RA D-FF

3 D-TRANSFORM RB !

?PRINT IF

: D-STEPF5
.ABCD CR CR
: D-STEPF6
.ABCD CR CR
: D-STEPF7
.ABCD CR CR
: D-STEPF8
.ABCD CR CR

( -THEN
( -THEN
( -THEN
( -THEN

)
;
)
;
)
;
)
;

RB

7 RA

RB RC RD D-FF

4 D-TRANSFORM RA !

?PRINT IF

RA 12 RD

RA RB RC D-FF

5 D-TRANSFORM RD !

?PRINT IF

RD 17 RC

RD RA RB D-FF

6 D-TRANSFORM RC !

?PRINT IF

RC 22 RB

RC RD RA D-FF

7 D-TRANSFORM RB !

?PRINT IF

: D-STEPF9
.ABCD CR CR
: D-STEPF10
.ABCD CR CR
: D-STEPF11
.ABCD CR CR
: D-STEPF12
.ABCD CR CR

( -THEN
( -THEN
( -THEN
( -THEN

)
;
)
;
)
;
)
;

RB

RB RC RD D-FF

8 D-TRANSFORM RA !

?PRINT IF

RA 12 RD 10

RA RB RC D-FF

9 D-TRANSFORM RD !

?PRINT IF

RD 17 RC 11

RD RA RB D-FF 10 D-TRANSFORM RC !

?PRINT IF

RC 22 RB 12

RC RD RA D-FF 11 D-TRANSFORM RB !

?PRINT IF

: D-STEPF13
.ABCD CR CR
: D-STEPF14
.ABCD CR CR
: D-STEPF15
.ABCD CR CR
: D-STEPF16
.ABCD CR CR

( -THEN
( -THEN
( -THEN
( -THEN

)
;
)
;
)
;
)
;

RB

7 RA 13

RB RC RD D-FF 12 D-TRANSFORM RA !

?PRINT IF

RA 12 RD 14

RA RB RC D-FF 13 D-TRANSFORM RD !

?PRINT IF

RD 17 RC 15

RD RA RB D-FF 14 D-TRANSFORM RC !

?PRINT IF

RC 22 RB 16

RC RD RA D-FF 15 D-TRANSFORM RB !

?PRINT IF

7 RA

: D-ROUND1 ( -- )
D-STEPF1 D-STEPF2
D-STEPF5 D-STEPF6
D-STEPF9 D-STEPF10
D-STEPF13 D-STEPF14
;

D-STEPF3
D-STEPF7
D-STEPF11
D-STEPF15

D-STEPF4
D-STEPF8
D-STEPF12
D-STEPF16


:
:
:
:

STEPF1
STEPF2
STEPF3
STEPF4

: STEPF5
: STEPF6
: STEPF7

(
(
(
(

-----

) 3 RA
) 7 RD
) 11 RC
) 19 RB

0
0
0
0

RB
RA
RD
RC

RC
RB
RA
RD

RD
RC
RB
RA

FF
FF
FF
FF

( -- ) 3 RA 0 RB RC RD FF
( -- ) 7 RD 0 RA RB RC FF
( -- ) 11 RC 0 RD RA RB FF

0
1
2
3

TRANSFORM
TRANSFORM
TRANSFORM
TRANSFORM

RA
RD
RC
RB

!
!
!
!

;
;
;
;

4 TRANSFORM RA ! ;
5 TRANSFORM RD ! ;
6 TRANSFORM RC ! ;

: STEPF8

( -- ) 19 RB 0 RC RD RA FF

:
:
:
:

STEPF9
STEPF10
STEPF11
STEPF12

(
(
(
(

-----

) 3 RA
) 7 RD
) 11 RC
) 19 RB

0
0
0
0

RB
RA
RD
RC

RC
RB
RA
RD

RD
RC
RB
RA

FF 8 TRANSFORM
FF 9 TRANSFORM
FF 10 TRANSFORM
FF 11 TRANSFORM

RA
RD
RC
RB

!
!
!
!

;
;
;
;

:
:
:
:

STEPF13
STEPF14
STEPF15
STEPF16

(
(
(
(

-----

) 3 RA
) 7 RD
) 11 RC
) 19 RB

0
0
0
0

RB
RA
RD
RC

RC
RB
RA
RD

RD
RC
RB
RA

FF
FF
FF
FF

RA
RD
RC
RB

!
!
!
!

;
;
;
;

: ROUND1 ( -- )
STEPF1 STEPF2
STEPF5 STEPF6
STEPF9 STEPF10
STEPF13 STEPF14
;

STEPF3
STEPF7
STEPF11
STEPF15

7 TRANSFORM RB ! ;

12
13
14
15

TRANSFORM
TRANSFORM
TRANSFORM
TRANSFORM

STEPF4
STEPF8
STEPF12
STEPF16

(MD5-INIT)
(D-ROUND1).
.

A, B, C
D.
. ,
OpenSSL.

OpenSSL
OpenSSL ,
MD4. ,
16 ,
. :
-
#define
#define
#define
#define

INIT_DATA_A
INIT_DATA_B
INIT_DATA_C
INIT_DATA_D

(unsigned
(unsigned
(unsigned
(unsigned

void MD5_Init(MD5_CTX *c)


{
c->A=INIT_DATA_A;
c->B=INIT_DATA_B;
c->C=INIT_DATA_C;
c->D=INIT_DATA_D;
c->Nl=0;
c->Nh=0;
c->num=0;
}

long)0x67452301L
long)0xefcdab89L
long)0x98badcfeL
long)0x10325476L

void MD5_Update(MD5_CTX *c, const void *data_, unsigned long len)


{
const unsigned char *data=data_;
register HASH_LONG * p;
register unsigned long l;
int sw,sc,ew,ec;
if (len==0) return;
l=(c->Nl+(len<<3))&0xffffffffL;
/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
* Wei Dai <weidai@eskimo.com> for pointing it out. */
if (l < c->Nl) /* */
c->Nh++;
c->Nh+=(len>>29);
c->Nl=l;
if (c->num != 0)
{
p=c->data;
sw=c->num>>2;
sc=c->num&0x03;
if ((c->num+len) >= HASH_CBLOCK)
{
l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
for (; sw<HASH_LBLOCK; sw++)
{
HOST_c2l(data,l); p[sw]=l;
}
HASH_BLOCK_HOST_ORDER (c,p,1);
len-=(HASH_CBLOCK-c->num);
c->num=0;
/* drop through and do the rest */
}
else
{
c->num+=len;
if ((sc+len) < 4) /* */
{
l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
}
else
{
ew=(c->num>>2);
ec=(c->num&0x03);
l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
for (; sw < ew; sw++)
{
HOST_c2l(data,l); p[sw]=l;
}
if (ec)
{
HOST_c2l_p(data,l,ec); p[sw]=l;
}
}
return;
}
}
sw=len/HASH_CBLOCK;
if (sw > 0)
{
#if defined(HASH_BLOCK_DATA_ORDER)
{
HASH_BLOCK_DATA_ORDER(c,data,sw);
sw*=HASH_CBLOCK;
data+=sw;

len-=sw;
}
#endif

}
if (len!=0)
{
p = c->data;
c->num = len;
ew=len>>2;
/* */
ec=len&0x03;
for (; ew; ew--,p++)
{
HOST_c2l(data,l); *p=l;
}
HOST_c2l_p(data,l,ec);
*p=l;
}
}

-
void MD5_Final(unsigned char *md, MD5_CTX *c)
{
register HASH_LONG *p;
register unsigned long l;
register int i,j;
static const unsigned char end[4]={0x80,0x00,0x00,0x00};
const unsigned char *cp=end;
/* c->num
* . */
p=c->data;
i=c->num>>2;
j=c->num&0x03;
l = (j==0) ? 0 : p[i];
HOST_p_c2l(cp,l,j); p[i++]=l;
/* i ' ' */
if (i>(HASH_LBLOCK-2)) /* Nl Nh */
{
if (i<HASH_LBLOCK) p[i]=0;
HASH_BLOCK_HOST_ORDER (c,p,1);
i=0;
}
for (; i<(HASH_LBLOCK-2); i++)
p[i]=0;
#if

defined(DATA_ORDER_IS_BIG_ENDIAN)
p[HASH_LBLOCK-2]=c->Nh;
p[HASH_LBLOCK-1]=c->Nl;
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
p[HASH_LBLOCK-2]=c->Nl;
p[HASH_LBLOCK-1]=c->Nh;
#endif
HASH_BLOCK_HOST_ORDER (c,p,1);
#ifndef HASH_MAKE_STRING
#error "HASH_MAKE_STRING must be defined!"
#else
HASH_MAKE_STRING(c,md);
#endif
c->num=0;

/* , HASH_BLOCK
* ,
memset((void *)c,0,sizeof(HASH_CTX));
*/
}

16- ,
:
void md5_block_host_order(MD5_CTX *c, const void *data, int num)
{
const MD5_LONG *X=data;
register unsigned long A,B,C,D;
A=c->A;
B=c->B;
C=c->C;
D=c->D;
for (;num--;X+=HASH_LBLOCK)
{
/* 0 */
R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
R0(C,D,A,B,X[ 2],17,0x242070dbL);
R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
R0(D,A,B,C,X[ 5],12,0x4787c62aL);
R0(C,D,A,B,X[ 6],17,0xa8304613L);
R0(B,C,D,A,X[ 7],22,0xfd469501L);
R0(A,B,C,D,X[ 8], 7,0x698098d8L);
R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
R0(C,D,A,B,X[10],17,0xffff5bb1L);
R0(B,C,D,A,X[11],22,0x895cd7beL);
R0(A,B,C,D,X[12], 7,0x6b901122L);
R0(D,A,B,C,X[13],12,0xfd987193L);
R0(C,D,A,B,X[14],17,0xa679438eL);
R0(B,C,D,A,X[15],22,0x49b40821L);
/* 1 */
R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
R1(D,A,B,C,X[ 6], 9,0xc040b340L);
R1(C,D,A,B,X[11],14,0x265e5a51L);
R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
R1(D,A,B,C,X[10], 9,0x02441453L);
R1(C,D,A,B,X[15],14,0xd8a1e681L);
R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
R1(D,A,B,C,X[14], 9,0xc33707d6L);
R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
R1(B,C,D,A,X[ 8],20,0x455a14edL);
R1(A,B,C,D,X[13], 5,0xa9e3e905L);
R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
R1(C,D,A,B,X[ 7],14,0x676f02d9L);
R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
/* 2 */
R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
R2(D,A,B,C,X[ 8],11,0x8771f681L);
R2(C,D,A,B,X[11],16,0x6d9d6122L);
R2(B,C,D,A,X[14],23,0xfde5380cL);
R2(A,B,C,D,X[ 1], 4,0xa4beea44L);

R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
R2(B,C,D,A,X[10],23,0xbebfbc70L);
R2(A,B,C,D,X[13], 4,0x289b7ec6L);
R2(D,A,B,C,X[ 0],11,0xeaa127faL);
R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
R2(B,C,D,A,X[ 6],23,0x04881d05L);
R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
R2(D,A,B,C,X[12],11,0xe6db99e5L);
R2(C,D,A,B,X[15],16,0x1fa27cf8L);
R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
/* 3 */
R3(A,B,C,D,X[ 0], 6,0xf4292244L);
R3(D,A,B,C,X[ 7],10,0x432aff97L);
R3(C,D,A,B,X[14],15,0xab9423a7L);
R3(B,C,D,A,X[ 5],21,0xfc93a039L);
R3(A,B,C,D,X[12], 6,0x655b59c3L);
R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
R3(C,D,A,B,X[10],15,0xffeff47dL);
R3(B,C,D,A,X[ 1],21,0x85845dd1L);
R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
R3(C,D,A,B,X[ 6],15,0xa3014314L);
R3(B,C,D,A,X[13],21,0x4e0811a1L);
R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
R3(D,A,B,C,X[11],10,0xbd3af235L);
R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
R3(B,C,D,A,X[ 9],21,0xeb86d391L);
A
B
C
D

=
=
=
=

c->A
c->B
c->C
c->D

+=
+=
+=
+=

A;
B;
C;
D;

}
}

Microsoft Windows
Microsoft Windows
MD5 Crypto API
.
Crypto API "",
, .
, ,
Crypto API, .
,
MD5.

Crypto API :
CryptCreateHash
. -,
.
CryptGetHashParam , .
CryptHashData , .

CryptDestroyHash
- CryptCreatehash.

CryptHashData
.
, .

dwBufferLen, pBuffer. ,
.
CryptoGetHashParam
- .

#include <wincrypt.h>
// CryptoAPI
/*
, :
#define ALG_CLASS_HASH
(4 << 13)
#define ALG_TYPE_ANY
(0)
#define ALG_SID_MD5
3
#define CALG_MD5
(ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5)
#define HP_HASHVAL
0x0002 //
#define HP_HASHSIZE
0x0004 //
*/
BOOL bResult;
HCRYPTHASH hHash;
DWORD dwBufferLen;
DWORD dwValue;
PBYTE pBuffer;
// -.
bResult = CryptCreateHash(
hProv,
// CSP
CALG_MD5,
//
0,
0,
// !
&hHash);
//
// .
bResult = CryptHashData(
hHash,
// -
pBuffer,
//
dwBufferLen,
//
0);
//
// () .
dwBufferSize = sizeof(DWORD);
bResult = CryptGetHashParam(
hHash,
// -
HP_HASHSIZE,
//
&dwValue,
//
&dwBufferLen,
//
0);
// !
// .
pBuffer = new char [dwBufferSize];
// Get hash value.
bResult = CryptGetHashParam(
hHash,
HP_HASHVAL,
pBuffer,
&dwBufferSize,
0);

//
//
//
//
//

-



!

// -.
CryptDestroyHash(hHash);

! , ,
MD5 . ,
CryptoAPI
, MD4, MD5, SHA-1
,
.



MD4, ,
MD4_* MD5_*:
MD5_CTX context;
unsigned char digest[16];
unsigned char string = "abc";
unsigned int len = strlen (string);
MD5_Init(&context);
MD5_Update(&context, string, len);
MD5_Final(digest, &context);

:
MD5("abc") = 900150983CD24FB0D6963F7D28E17F72


MD5 ,
MD4:
FILE *file;
MD5_CTX context;
int len;
unsigned char buffer[1024], digest[16];
file = fopen(filename, "rb");
MD5_Init(&context);
while (len = fread (buffer, 1, 1024, file))
{
MD5_Update(&context, buffer, len);
}
MD5_Final(digest, &context);
fclose(file);

, , ,
: "4" "5".


MD4. ,
MD5 , MD4. ,
10,000 MD4 MD5 10,000
, , , . :
64 , 128 .
(? 64!)
Intel Pentium III 750 ,
Microsoft Windows XP.
MD4
64
RFC
OpenSSL

2.574
0.891

128
37940 /
109603 /

2.234
0.781

43717 /
125040 /

MD5
64
RFC
OpenSSL

2.614
1.152

128
37359 /
84771 /

2.344
1.092

41662 /
89429 /

, :
MD5 MD4 RFC 1.55%..4.92%
, , MD5 , MD4
1.53%..4.69%
MD5 MD4 RFC 29.29%..39.82%
MD5 , MD4 22.66%..28.48%.
, (OpenSSL),
. ,
MD5 30% , MD4!


.
-, -. ,
:
,
.
, -,
.
.


256 , - 2 ,
MD5.
, 2256 . , 2128
MD5.
M ( Messages) D ( Digests) ( 5).

M {2256}

D {2128}

256 128

5. 256
128 .
M , D,
M D, 2128- M
D .
D. , - D
M ( 6).

M1
D1

M2

D2

M4
M5
D3
M6

M3

6. M D .

, , M
D1 D, ,
M: M1, M2 M3,
,
.

.
,
, .
, : " 2256
! - ! !"
.....
MD4
125040 , Intel Pentium III
750 .
:
- 2256 1.15791077
- 256 , 16 ,
64
- 1.15791077 4 = 4.6131077 ( 4
, )
- 4.6131077 1024 = 4.52301074
-
, 4.52301074 125040 = 3.61731069

- 3.61731069 = 3.61731069
(60 [ ] 60 [ ] 24 [ ] 365 [ ]) =
3.61731069 31,536,000 = 1.14701062
? ?
,
( , ):
- MD5 128 = 16
- 2256
- 2256 * 16 = 2260
- 2260 1024 = 2250
- 2250 1024 = 2240
- 2240 1024 = 2230
!
, ,
.

( )
.


. ,
MD5(abc) = MD5(61626316) = MD5(1010000110100010101000112) =
= 900150983CD24FB0D6963F7D28E17F72
MD5(acc) = MD5(61636316) = MD5(1010000110100011101000112) =
= 1673448EE7064C989D02579C534F6B66
100100000000000101010000100110000011...
000101100111001101000100100011101110...
.
MD5 .

MD5 ?
1996 MD5.
:
MD5 ,
(, 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476),
,
, ,
. , , .
:
MD5(IV, M1) = MD5(IV, M2),
IV = Initial Values = , M1 M2 .
, (Hans Dobbertin), ,
MD5
IVA = 0x12AC2375
IVB = 0x3B341042
IVC = 0x5F62B97C
IVD = 0x4BA763ED
:
X0 = 0xAA1DDABE
X1 = 0xD97ABFF5
X2 = 0xBBF0E1C1
X3 = 0x32774244
X4 = 0x1006363E
X5 = 0x7218209D
X6 = 0xE01C136D
X7 = 0x9DA64D0E
X8 = 0x98A1FB19
X9 = 0x1FAE44B0
X10 = 0x236BB992
X11 = 0x6B7A779B
X12 = 0x1326ED65
X13 = 0xD93E0972
X14 = 0xD458C868
X15 = 0x6B72746A

X i ,
i < 16, i 14;

X 'i =
X14 + 29 ,
i = 14.

MD5(IV, X) = MD5(IV, X') = BF90E670752AF92B9CE4E3E1B12CF8DE.


,
RFC 1321 , MD5
.
, MD5 !
, .
, ,
. MD4
MD5 HTTP://WWW.Relcom.COM/Argc-Argv.

2 7 2003
(LoShu_LoShu@Yahoo.CO.UK, LoShu_LoShu@HotMail.COM).

. RFC 1321

Network Working Group


Request for Comments: 1321

R. Rivest
MIT Laboratory for Computer
Science
and RSA Data Security, Inc.
April 1992


MD5


. .
.

(Don
Coppersmith), (Burt Kaliski), (Ralph
Merkle), (David Chaum) (Noam Nisan)
, .

................................................................................................................ 23
.................................................................................................................................. 23
...................................................................................................................................... 23
1. ..................................................................................................................... 24
2. ............................................................................................................... 24
3. MD5 ............................................................................................................. 25
3.1 1. ................................................................................................ 25
3.2 2. ....................................................................................................... 25
3.3 3. MD ........................................................................................... 26
3.4 4. 16 .................................................................. 26
3.5 5. ......................................................................................................... 28
4. ......................................................................................................................................... 28
5. MD4 MD5.......................................................................................................... 28
....................................................................................................................................... 28
A ............................................................................................. 29
A.1 global.h.................................................................................................................................... 29

A.2 md5.h ...................................................................................................................................... 30


A.3 md5c.c..................................................................................................................................... 31
A.4 mddriver.c................................................................................................................................ 36
A.5 ........................................................................................................................... 40
............................................................................................................ 41
.................................................................................................................................... 41

1.
MD5.

128- ""
" " . ,
,
,
. MD5
,
""
()
, , , RSA.
MD5 ,
32- . , MD5
;
.
MD5 MD4
[1,2]. MD5 , MD4,
"" . MD4
, ,
" " . MD5
,
.
, . MD4

.
OSI, MD5

5}

md5 OBJECT IDENTIFIER ::=


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

AlgorithmIdentifier [3] X.509, MD5


NULL.

2.
"" 32- , ""
8- .
,

( ) .
,
32- ,

(
) .
x_i "x sub i".
, ,
x_{i+1}. , ^ (
), x^i x i.
"+" (
2^32). X <<< s 32-
() X s . not(X)
X, X v Y
X Y. X xor Y
X Y, XY X Y.

3. MD5
, b-
.
b ; b ,
, .
, :
m_0 m_1 ... m_{b-1}

.

3.1 1.
, ( )
448 512.
64 ,
512. ,
448 512.
:
"1" ,
"0" , 448
512. , 512
.

3.2 2.
64- b (
) ,
. , b
2^64, 64 b. (
32-
.)
(
b) , 512
. , ,

16 (32-) . M[0 ... N-1]


, N 16.

3.3 3. MD

(A, B, C, D). A, B, C, D
32- .
( ):

A:
B:
C:
D:

01
89
fe
76

23
ab
dc
54

45
cd
ba
32

67
ef
98
10

3.4 4. 16

32-
32- .
F(X,Y,Z)
G(X,Y,Z)
H(X,Y,Z)
I(X,Y,Z)

=
=
=
=

XY v not(X) Z
XZ v Y not(Z)
X xor Y xor Z
Y xor (X v not(Z))

F : X, Y, Z.
F "+"
"v", XY and not(X)Z "1"
. (???) , X, Y
Z , F(X,Y,Z)
.
G, H I F ,
""
X, Y Z, ,
X, Y Z , G(X,Y,Z), H(X,Y,Z)
I(X,Y,Z) . , H
"" .
64 T[1 ... 64],
. T[i] i- ,
4294967296 abs(sin(i)), I
. .
:
/* 16 . */
For i = 0 to N/16-1 do
/* i X. */
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end /* j */
/* A AA, B BB, C CC, D DD. */
AA = A
BB = B

CC = C
DD = D

4]
8]
12]
16]

20]
24]
28]
32]

36]
40]
44]
48]

52]
56]
60]
64]

/* 1. */
/* [abcd k s i]
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
/* 16 . */
[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA

3 22

[ABCD

5]

[DABC

5 12

7 22

[ABCD

9]

[DABC

9 12 10]

[CDAB 10 17 11]

[BCDA 11 22

[DABC 13 12 14]

[CDAB 14 17 15]

[BCDA 15 22

[ABCD 12

7 13]

6]

[CDAB

6 17

7]

[BCDA

/* 2. */
/* [abcd k s i]
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
/* 16 . */
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA

0 20

[ABCD

5 21]

[DABC 10

9 22]

[CDAB 15 14 23]

[BCDA

4 20

[ABCD

5 25]

[DABC 14

9 26]

[CDAB

3 14 27]

[BCDA

8 20

[ABCD 13

5 29]

[DABC

9 30]

[CDAB

7 14 31]

[BCDA 12 20

/* 3. */
/* [abcd k s t]
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
/* 16 . */
[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23
[ABCD

4 37]

[DABC

4 11 38]

[CDAB

7 16 39]

[BCDA 10 23

[ABCD 13

4 41]

[DABC

0 11 42]

[CDAB

3 16 43]

[BCDA

6 23

[ABCD

4 45]

[DABC 12 11 46]

[CDAB 15 16 47]

[BCDA

2 23

/* 4. */
/* [abcd k s t]
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
/* 16 . */
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA

5 21

[ABCD 12

6 53]

[DABC

1 21

[ABCD

6 57]

[ABCD

6 61]

3 10 54]

[CDAB 10 15 55]

[BCDA

[DABC 15 10 58]

[CDAB

6 15 59]

[BCDA 13 21

[DABC 11 10 62]

[CDAB

2 15 63]

[BCDA

9 21

/* . (
,

.) */
A = A + AA
B = B + BB

C = C + CC
D = D + DD
end /* i */

3.5 5.

A, B, C, D.
A D.
MD5.
.

4.
MD5
, ""
. ,

2^64 ,
2^128 .
MD5
. ,

.

5. MD4 MD5
MD4 MD5:
1.

2.

3.

g 2 (XY v XZ v YZ) (XZ v


Y not(Z)), g .

4.


. " ". (This
promotes a faster "avalanche effect".)

5.

2
3, .

6.


, " ".
.

[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."

A
,
RSAREF: A Cryptographic Toolkit for Privacy-Enhanced Mail:
global.h
md5.h MD5
md5c.c MD5
RSAREF
<rsaref@rsa.com>.
:
mddriver.c MD2, MD4 MD5
MD5,
MD2 MD4,
MD 2 4.
.
,
, . ,
" " ("little-endian"),
32-
, Decode MD4Transform
.

A.1 global.h
/* GLOBAL.H - RSAREF
*/
/* PROTOTYPES 1

.
PROTOTYPES 0
.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER */

typedef unsigned char *POINTER;


/* UINT2 - */
typedef unsigned short int UINT2;
/* UINT4 - */
typedef unsigned long int UINT4;
/* PROTO_LIST ,
PROTOTYPES.
PROTOTYPES , PROTO_LIST ,

.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif

A.2 md5.h
/* MD5.H 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.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* MD5. */
typedef struct {
UINT4 state[4];
/* (ABCD)
*/
UINT4 count[2];
/* 2^64 (lsb first)
*/
unsigned char buffer[64];
/*
*/
} 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.
*/
/* 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"
/* MD5Transform.
*/
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

S11
S12
S13
S14
S21
S22
S23
S24
S31
S32
S33
S34
S41
S42
S43
S44

7
12
17
22
5
9
14
20
4
11
16
23
6
10
15
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,
};
/* F, G, H
*/
#define F(x,
#define G(x,
#define H(x,
#define I(x,

{
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

I MD5.
y,
y,
y,
y,

z)
z)
z)
z)

(((x) & (y)) | ((~x) & (z)))


(((x) & (z)) | ((y) & (~z)))
((x) ^ (y) ^ (z))
((y) ^ ((x) | (~z)))

/* ROTATE_LEFT x n .
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, II 1, 2, 3, 4. *\
/* ,

*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(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. MD5, .
*/
void MD5Init (context)
MD5_CTX *context;
/*
*/
{
context->count[0] = context->count[1] = 0;
/* "" .
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;

}
/* MD5 .

MD5, ,
.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context;
/*
*/
unsigned char *input;
/*
*/
unsigned int inputLen;
/*
*/
{
unsigned int i, index, partLen;
/* 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* .
*/
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;
/* */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5.

MD5, .
*/
void MD5Final (digest, context)
unsigned char digest[16];
/* */
MD5_CTX *context;
/* */
{
unsigned char bits[8];
unsigned int index, padLen;
/* */

Encode (bits, context->count, 8);


/* 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* ( ) */
MD5Update (context, bits, 8);
/* */
Encode (digest, context->state, 16);
/* .
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5. state
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);
/*
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF

1 */
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,

/* 2
GG (a, b,
GG (d, a,
GG (c, d,
GG (b, c,
GG (a, b,
GG (d, a,
GG (c, d,
GG (b, c,
GG (a, b,
GG (d, a,
GG (c, d,

*/
c,
b,
a,
d,
c,
b,
a,
d,
c,
b,
a,

d,
c,
b,
a,
d,
c,
b,
a,
d,
c,
b,

x[ 0],
x[ 1],
x[ 2],
x[ 3],
x[ 4],
x[ 5],
x[ 6],
x[ 7],
x[ 8],
x[ 9],
x[10],
x[11],
x[12],
x[13],
x[14],
x[15],

S11,
S12,
S13,
S14,
S11,
S12,
S13,
S14,
S11,
S12,
S13,
S14,
S11,
S12,
S13,
S14,

0xd76aa478);
0xe8c7b756);
0x242070db);
0xc1bdceee);
0xf57c0faf);
0x4787c62a);
0xa8304613);
0xfd469501);
0x698098d8);
0x8b44f7af);
0xffff5bb1);
0x895cd7be);
0x6b901122);
0xfd987193);
0xa679438e);
0x49b40821);

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

1 */
2 */
3 */
4 */
5 */
6 */
7 */
8 */
9 */
10 */
11 */
12 */
13 */
14 */
15 */
16 */

x[ 1],
x[ 6],
x[11],
x[ 0],
x[ 5],
x[10],
x[15],
x[ 4],
x[ 9],
x[14],
x[ 3],

S21,
S22,
S23,
S24,
S21,
S22,
S23,
S24,
S21,
S22,
S23,

0xf61e2562);
0xc040b340);
0x265e5a51);
0xe9b6c7aa);
0xd62f105d);
0x2441453);
0xd8a1e681);
0xe7d3fbc8);
0x21e1cde6);
0xc33707d6);
0xf4d50d87);

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

17
18
19
20
21
22
23
24
25
26
27

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

GG
GG
GG
GG
GG

(b,
(a,
(d,
(c,
(b,

c,
b,
a,
d,
c,

a,
d,
c,
b,
a,

x[ 8],
x[13],
x[ 2],
x[ 7],
x[12],

S24,
S21,
S22,
S23,
S24,

0x455a14ed);
0xa9e3e905);
0xfcefa3f8);
0x676f02d9);
0x8d2a4c8a);

/*
/*
/*
/*
/*

28
29
30
31
32

*/
*/
*/
*/
*/

/*
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH
HH

3 */
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,

x[ 5],
x[ 8],
x[11],
x[14],
x[ 1],
x[ 4],
x[ 7],
x[10],
x[13],
x[ 0],
x[ 3],
x[ 6],
x[ 9],
x[12],
x[15],
x[ 2],

S31,
S32,
S33,
S34,
S31,
S32,
S33,
S34,
S31,
S32,
S33,
S34,
S31,
S32,
S33,
S34,

0xfffa3942);
0x8771f681);
0x6d9d6122);
0xfde5380c);
0xa4beea44);
0x4bdecfa9);
0xf6bb4b60);
0xbebfbc70);
0x289b7ec6);
0xeaa127fa);
0xd4ef3085);
0x4881d05);
0xd9d4d039);
0xe6db99e5);
0x1fa27cf8);
0xc4ac5665);

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

/*
II
II
II
II
II
II
II
II
II
II
II
II
II
II
II
II

4 */
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,
(a, b, c, d,
(d, a, b, c,
(c, d, a, b,
(b, c, d, a,

x[ 0],
x[ 7],
x[14],
x[ 5],
x[12],
x[ 3],
x[10],
x[ 1],
x[ 8],
x[15],
x[ 6],
x[13],
x[ 4],
x[11],
x[ 2],
x[ 9],

S41,
S42,
S43,
S44,
S41,
S42,
S43,
S44,
S41,
S42,
S43,
S44,
S41,
S42,
S43,
S44,

0xf4292244);
0x432aff97);
0xab9423a7);
0xfc93a039);
0x655b59c3);
0x8f0ccc92);
0xffeff47d);
0x85845dd1);
0x6fa87e4f);
0xfe2ce6e0);
0xa3014314);
0x4e0811a1);
0xf7537e82);
0xbd3af235);
0x2ad7d2bb);
0xeb86d391);

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

state[0]
state[1]
state[2]
state[3]

d,
c,
b,
a,
d,

+=
+=
+=
+=

a;
b;
c;
d;

/* .
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* input (UINT4) output (unsigned char). ,
len
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);
}
}
/* input (unsigned char) output (UINT4). ,
len
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);
}
/* : "for loop" memcpy
.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* : "for loop" memset
.
*/
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 MD2, MD4 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.
*/
/* MD MD5 ,

.
*/
#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
#include "md4.h"
#endif
#if MD == 5
#include "md5.h"
#endif
/* , .
*/
#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000
static
static
static
static
static
static

void
void
void
void
void
void

MDString PROTO_LIST ((char *));


MDTimeTrial PROTO_LIST ((void));
MDTestSuite PROTO_LIST ((void));
MDFile PROTO_LIST ((char *));
MDFilter PROTO_LIST ((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
/* .
( ):
-sstring
-t
-
-x
-
filename
(none)
-

*/
int main (argc, argv)
int argc;
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);

/* .
*/
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");

/* TEST_BLOCK_COUNT

TEST_BLOCK_LEN.
*/
static void MDTimeTrial ()
{
MD_CTX context;

time_t endTime, startTime;


unsigned char block[TEST_BLOCK_LEN], digest[16];
unsigned int i;
printf
("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
/* */
for (i = 0; i < TEST_BLOCK_LEN; i++)
block[i] = (unsigned char)(i & 0xff);
/* */
time (&startTime);
/* */
MDInit (&context);
for (i = 0; i < TEST_BLOCK_COUNT; i++)
MDUpdate (&context, block, TEST_BLOCK_LEN);
MDFinal (digest, &context);
/* */
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));
}
/* .
*/
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");
}
/* .
*/
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");
}
}
/* .
*/
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");

/* .
*/
static void MDPrint (digest)
unsigned char digest[16];
{
unsigned int i;
for (i = 0; i < 16; i++)
printf ("%02x", digest[i]);
}

A.5
MD5 ( "-x")
:
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




MD5
.


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