?? 中文rfc1321.txt
字號:
組織:中國互動出版網(http://www.china-pub.com/)
RFC文檔中文翻譯計劃(http://www.china-pub.com/compters/emook/aboutemook.htm)
E-mail:ouyang@china-pub.com
譯者:()
譯文發布時間:2001-11-7
版權:本中文翻譯文檔版權歸中國互動出版網所有。可以用于非商業用途自由轉載,但必須
保留本文檔的翻譯及版權信息。
Network Working Group R. Rivest
Request for Comments: 1321 MIT Laboratory for Computer Science
and RSA Data Security, Inc.
April 1992
MD5 報文摘要算法
(RFC1321——The MD5 Message-Digest Algorithm)
本文地位
本文并非指定一個Internet標準,而是向互聯網提供信息,本文可以任意傳播,不受限制。
致謝
Don Coppersmith, Burt Kaliski, Ralph Merkle,David Chaum, 和Noam Nisan向本文提供極大的幫
助,在此本人表示忠心的感謝。
目錄
1 執行簡介 1
2 術語和符號 1
3 MD5算法描述 2
4 摘要 4
5 MD4和MD5的區別 4
6 參考文獻 4
7 附錄A-參考應用程序 4
8 安全事項 18
9 作者地址 18
1 執行簡介
本文描述了MD5報文摘要算法,此算法將對輸入的任意長度的信息進行計算,產生一個128位
長度的“指紋”或“報文摘要”,假定兩個不同的文件產生相同的報文摘要或由給定的報文摘要產生
原始信息在計算上是行不通的。MD5算法適合用在數據簽名應用中,在此應用中,一個大的文件必
須在類似RSA算法的公用密鑰系統中用私人密鑰加密前被“壓縮”在一種安全模式下。
MD5算法能在32位機器上能以很快的速度運行。另外,MD5算法不需要任何大型的置換列表。
此算法編碼很簡潔。MD5 算法是MD4報文摘要算法的擴展。MD5算法稍慢于MD4算法,但是在設
計上比MD4算法更加“保守”。設計MD5是因為MD4算法被采用的速度太快,以至于還無法證明
它的正確性,因為MD4算法速度非常快,它處在遭受成功秘密攻擊的“邊緣”。MD5后退了一步,
它舍棄了一些速度以求更好的安全性。它集中了不同的評論家提出的建議,并采取了一些附加的優化
措施。它被放在公共的地方以求公眾的評論意見,它可能當作一個標準被采納。
作為基于OSI的應用,MD5的對象標識符是:
md5 OBJECT IDENTIFIER ::=
iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
在X.509類型AlgorithmIdentifier [3]中,MD5算法參數應該包括NULL類型。
2 術語和符號
本文中一個“字”是32位,一個“字節”是8位。一系列位串可看成是一系列字節的普通形式,
其中的連續的8位看成一個字節,高位在前,同理一系列字節串可看成是一系列32位的字,其中每
個連續的4個字節當作一個字,地位在前。
我們定義x_i代表“x減去I".如果下劃線左邊的是一個表達式,則用括號括住,如:
x_{i+1}。同樣我們用^代表求冪,這樣x^i則代表x的i次冪。
符號“+”代表字的加,X <<< s代表32位的值X循環左移s位,not(X)代表X的按位
補運算,X v Y 表示X和Y的按位或運算,XxorY代表X和Y的按位異或運算,XY代表
X和Y的按位與運算。
3 MD5算法描述
我們假設有一個b位長度的輸入信號,希望產生它的報文摘要,此處b是一個非負整數,b也可
能是0,不一定必須是8的整數倍,它可能是任意大的長度。我們設想信號的比特流如下所示:
m_0 m_1 ... m_{b-1}
下面的5步計算信息的報文摘要。
(1) 補位
MD5算法是對輸入的數據進行補位,使得如果數據位長度LEN對512求余的結果是448。即數
據擴展至K*512+448位。即K*64+56個字節,K為整數。補位操作始終要執行,即使數據長度LEN
對512求余的結果已是448。
具體補位操作:補一個1,然后補0至滿足上述要求。總共最少要補一位,最多補512位。
(2) 補數據長度
用一個64位的數字表示數據的原始長度b,把b用兩個32位數表示。那么只取B的低64位。
當遇到b大于2^64這種極少遇到的情況時,這時,數據就被填補成長度為512位的倍數。也就是說,
此時的數據長度是16個字(32位)的整數倍數。用M[0 ... N-1]表示此時的數據,其中的N是16
的倍數。
(3) 初始化MD緩沖器
用一個四個字的緩沖器(A,B,C,D)來計算報文摘要,A,B,C,D分別是32位的寄存器,初
始化使用的是十六進制表示的數字
A=0X01234567
B=0X89abcdef
C=0Xfedcba98
D=0X76543210
(4) 處理位操作函數
首先定義4個輔助函數,每個函數的輸入是三個32位的字,輸出是一個32位的字。
X,Y,Z為32位整數。
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))
這一步中 使用一個64元素的常數組T[1 ... 64],它由sine函數構成,T[i]表示數組中的第i個元
素,它的值等于經過4294967296次abs(sin(i))后的值的整數部分(其中i是弧度 )。T[i]為32位
整數用16進制表示,數組元素在附錄中給出。
具體過程如下:
/* 處理數據原文 */
For i = 0 to N/16-1 do
/*每一次,把數據原文存放在16個元素的數組X中. */
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end /結束對J的循環
/* Save A as AA, B as BB, C as CC, and D as DD. */
AA = A
BB = B
CC = C
DD = D
/* 第1輪*/
/* 以 [abcd k s i]表示如下操作
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]
/* 第2輪* */
/* 以 [abcd k s i]表示如下操作
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]
/* 第3輪*/
/* 以 [abcd k s i]表示如下操作
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]
/* 第4輪*/
/* 以 [abcd k s i]表示如下操作
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]
/* 然后進行如下操作 */
A = A + AA
B = B + BB
C = C + CC
D = D + DD
end /* 結束對I的循環*/
(5) 輸出結果
報文摘要的產生后的形式為:A,B,C,D。也就是低位字節A開始,高位字節D結束。
現在完成了對MD5的描述,在附錄中給出了C形式的程序。
4 摘要
MD5算法實現很容易,它提供了任意長度的信息的“指紋”(或稱為報文摘要)。據推測要實現
兩個不同的報文產生相同的摘要需要2^64次的操作,要恢復給定摘要的報文則需要2^128次操作。
為尋找缺陷,MD5算法已經過非常細致的檢查。最后的結論是還需要相關的更好的算法和更進一步
的安全分析。
5 MD4和MD5的區別
以下是MD5和MD4的不同點:
1. 加上了第四輪循環。
2. 每一步增加了一個唯一的常數值。
第二輪中的函數g從(XY v XZ v YZ)變成了(XZ v Y not(Z)),以減少g函數的均衡性。
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 '90Proceedings, pages 303-311, Springer-Verlag,
1991.
[3] CCITT Recommendation X.509 (1988), "The Directory - Authentication
Framework."
7 附錄A-參考應用程序
本附錄包括以下文件:(摘自RSAREF: A Cryptographic Toolkit for Privacy-Enhanced Mail:)
global.h - 全局頭文件
md5.h -- MD5頭文件
md5c.c -- MD5源代碼
(要得到更多的RSAREF信息,請發e-mai到: <rsaref@rsa.com>.)
附錄中還包括:
mddriver.c-MD2, MD4 and MD5的測試驅動程序。
驅動程序默認情況下編譯MD5,但如果在C的編譯命令行將MD5參數設成2或4,則也可以編譯
MD2和MD4
此應用程序是方便使用的,可用在不同的平臺上,在特殊的平臺上優化它也并不困難,這留給讀
者作為練習。例如,在“little-endian”平臺上,此平臺32位字的最低地址字節最無意義的字節,
并且沒有隊列限制,在MD5變換中的解碼的命令調用可以被相應的類型替代。
A1 global.h
/* GLOBAL.H - RSAREF 類型和常數*/
/* 當且僅當編譯器支持函數原型的聲明時,PROTOTYPES必須被設置一次
如果還沒有定義C編譯器的標記,下面的代碼使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頭文件*/
/*本軟件允許被復制或運用,但必須在所有提及和參考的地方標注“RSA Data Security, Inc. MD5
Message-Digest Algorithm”,也允許產生或運用派生軟件,但必須在所有提及和參考的地方標明
“derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm”
RSA數據安全公司(RSA Data Security, Inc.)從來沒有出于任何特定目的陳述過關于此
軟件的可買性和實用性,它提供了“as is”,沒有表達或暗示過任何理由。
此聲明必須在任何此文件和軟件的任何拷貝中保留。*/
/* MD5 context. */
typedef struct
{
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* 位數量, 模 2^64 (低位在前) */
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數據安全公司,MD5報文摘要算法*/
/*本軟件允許被復制或運用,但必須在所有提及和參考的地方標注“RSA Data Security, Inc. MD5
Message-Digest Algorithm”也允許產生或運用派生軟件,但必須在所有提及和參考的地方標明
“derived from the RSA Data RSA數據安全公司(RSA Data Security, Inc.)從來沒有出于任何
特定目的陳述過關于此軟件的可買性和實用性,它提供了“as is”,沒有表達或暗示過任何理由。
此聲明必須在任何此文件和軟件的任何拷貝中保留。*/
#include "global.h"
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#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 和 I 是基本MD5函數 */
#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 將x循環左移n位 */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* 循環從加法中分離出是為了防止重復計算*/
#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操作寫一個新的context. */
void MD5Init (context)
MD5_CTX *context; /* 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操作,處理另一個消息分組并更新context. */
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* 輸入分組*/
unsigned int inputLen; /* 輸入的分組的長度 */
{
unsigned int i, index, partLen;
/* 計算字節數模64的值 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
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; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* 保存位數值 */
Encode (bits, context->count, 8);
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* 附加長度 (在補位之前) */
MD5Update (context, bits, 8);
/* 將 state 存入 digest 中*/
Encode (digest, context->state, 16);
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5基本轉換. 轉換狀態基于分組*/
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);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -