Network Working Group                                   D. Eastlake, 3rd
Request for Comments: 3174                                      Motorola
Category: Informational                                         P. Jones
                                                           Cisco Systems
                                                          September 2001
        
Network Working Group                                   D. Eastlake, 3rd
Request for Comments: 3174                                      Motorola
Category: Informational                                         P. Jones
                                                           Cisco Systems
                                                          September 2001
        

US Secure Hash Algorithm 1 (SHA1)

美国安全哈希算法1(SHA1)

Status of this Memo

本备忘录的状况

This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.

本备忘录为互联网社区提供信息。它没有规定任何类型的互联网标准。本备忘录的分发不受限制。

Copyright Notice

版权公告

Copyright (C) The Internet Society (2001). All Rights Reserved.

版权所有(C)互联网协会(2001年)。版权所有。

Abstract

摘要

The purpose of this document is to make the SHA-1 (Secure Hash Algorithm 1) hash algorithm conveniently available to the Internet community. The United States of America has adopted the SHA-1 hash algorithm described herein as a Federal Information Processing Standard. Most of the text herein was taken by the authors from FIPS 180-1. Only the C code implementation is "original".

本文档的目的是使SHA-1(安全哈希算法1)哈希算法方便地提供给互联网社区。美利坚合众国已采用本文所述的SHA-1哈希算法作为联邦信息处理标准。本文中的大部分文本由作者摘自FIPS 180-1。只有C代码实现是“原始的”。

Acknowledgements

致谢

Most of the text herein was taken from [FIPS 180-1]. Only the C code implementation is "original" but its style is similar to the previously published MD4 and MD5 RFCs [RFCs 1320, 1321].

本文大部分内容摘自[FIPS 180-1]。只有C代码实现是“原始的”,但它的风格类似于之前发布的MD4和MD5 RFC[RFCS13201321]。

The SHA-1 is based on principles similar to those used by Professor Ronald L. Rivest of MIT when designing the MD4 message digest algorithm [MD4] and is modeled after that algorithm [RFC 1320].

SHA-1基于与麻省理工学院Ronald L.Rivest教授在设计MD4消息摘要算法[MD4]时使用的原理相似的原理,并以该算法[RFC 1320]为模型。

Useful comments from the following, which have been incorporated herein, are gratefully acknowledged:

感谢以下各方提出的有用意见,这些意见已纳入本文:

Tony Hansen Garrett Wollman

托尼·汉森·加勒特·沃尔曼

Table of Contents

目录

   1. Overview of Contents...........................................  2
   2. Definitions of Bit Strings and Integers........................  3
   3. Operations on Words............................................  3
   4. Message Padding................................................  4
   5. Functions and Constants Used...................................  6
   6. Computing the Message Digest...................................  6
   6.1 Method 1......................................................  6
   6.2 Method 2......................................................  7
   7. C Code.........................................................  8
   7.1 .h file.......................................................  8
   7.2 .c file....................................................... 10
   7.3 Test Driver................................................... 18
   8. Security Considerations........................................ 20
   References........................................................ 21
   Authors' Addresses................................................ 21
   Full Copyright Statement.......................................... 22
        
   1. Overview of Contents...........................................  2
   2. Definitions of Bit Strings and Integers........................  3
   3. Operations on Words............................................  3
   4. Message Padding................................................  4
   5. Functions and Constants Used...................................  6
   6. Computing the Message Digest...................................  6
   6.1 Method 1......................................................  6
   6.2 Method 2......................................................  7
   7. C Code.........................................................  8
   7.1 .h file.......................................................  8
   7.2 .c file....................................................... 10
   7.3 Test Driver................................................... 18
   8. Security Considerations........................................ 20
   References........................................................ 21
   Authors' Addresses................................................ 21
   Full Copyright Statement.......................................... 22
        
1. Overview of Contents
1. 内容概述

NOTE: The text below is mostly taken from [FIPS 180-1] and assertions therein of the security of SHA-1 are made by the US Government, the author of [FIPS 180-1], and not by the authors of this document.

注:以下文字主要摘自[FIPS 180-1],其中关于SHA-1安全性的声明由[FIPS 180-1]的作者美国政府提出,而非本文件的作者。

This document specifies a Secure Hash Algorithm, SHA-1, for computing a condensed representation of a message or a data file. When a message of any length < 2^64 bits is input, the SHA-1 produces a 160-bit output called a message digest. The message digest can then, for example, be input to a signature algorithm which generates or verifies the signature for the message. Signing the message digest rather than the message often improves the efficiency of the process because the message digest is usually much smaller in size than the message. The same hash algorithm must be used by the verifier of a digital signature as was used by the creator of the digital signature. Any change to the message in transit will, with very high probability, result in a different message digest, and the signature will fail to verify.

本文档指定了一种安全哈希算法SHA-1,用于计算消息或数据文件的压缩表示。当输入任何长度小于2^64位的消息时,SHA-1产生一个160位的输出,称为消息摘要。然后,例如,可以将消息摘要输入到签名算法,该算法生成或验证消息的签名。签名消息摘要而不是消息通常会提高流程的效率,因为消息摘要的大小通常比消息小得多。数字签名的验证者必须使用与数字签名的创建者相同的哈希算法。对传输中的消息的任何更改都极有可能导致不同的消息摘要,并且签名将无法验证。

The SHA-1 is called secure because it is computationally infeasible to find a message which corresponds to a given message digest, or to find two different messages which produce the same message digest. Any change to a message in transit will, with very high probability, result in a different message digest, and the signature will fail to verify.

SHA-1被称为安全的,因为在计算上不可能找到与给定消息摘要相对应的消息,也不可能找到生成相同消息摘要的两条不同消息。对传输中的消息的任何更改都极有可能导致不同的消息摘要,并且签名将无法验证。

Section 2 below defines the terminology and functions used as building blocks to form SHA-1.

下文第2节定义了构成SHA-1的构建块所使用的术语和功能。

2. Definitions of Bit Strings and Integers
2. 位字符串和整数的定义

The following terminology related to bit strings and integers will be used:

将使用以下与位字符串和整数相关的术语:

a. A hex digit is an element of the set {0, 1, ... , 9, A, ... , F}. A hex digit is the representation of a 4-bit string. Examples: 7 = 0111, A = 1010.

a. 十六进制数字是集合{0,1,…,9,A,…,F}的一个元素。十六进制数字是4位字符串的表示形式。示例:7=0111,A=1010。

b. A word equals a 32-bit string which may be represented as a sequence of 8 hex digits. To convert a word to 8 hex digits each 4-bit string is converted to its hex equivalent as described in (a) above. Example:

b. 一个字等于一个32位字符串,可以表示为8个十六进制数字的序列。要将一个字转换为8个十六进制数字,每个4位字符串将转换为其十六进制等效值,如上文(a)所述。例子:

1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23.

1010 0001 0000 0011 1111 1110 0010 0011=A103FE23。

c. An integer between 0 and 2^32 - 1 inclusive may be represented as a word. The least significant four bits of the integer are represented by the right-most hex digit of the word representation. Example: the integer 291 = 2^8+2^5+2^1+2^0 = 256+32+2+1 is represented by the hex word, 00000123.

c. 介于0和2^32-1(含)之间的整数可以表示为一个字。整数的最低有效位由单词表示法的最右边的十六进制数字表示。示例:整数291=2^8+2^5+2^1+2^0=256+32+2+1由十六进制字00000123表示。

      If z is an integer, 0 <= z < 2^64, then z = (2^32)x + y where 0 <=
      x < 2^32 and 0 <= y < 2^32.  Since x and y can be represented as
      words X and Y, respectively, z can be represented as the pair of
      words (X,Y).
        
      If z is an integer, 0 <= z < 2^64, then z = (2^32)x + y where 0 <=
      x < 2^32 and 0 <= y < 2^32.  Since x and y can be represented as
      words X and Y, respectively, z can be represented as the pair of
      words (X,Y).
        

d. block = 512-bit string. A block (e.g., B) may be represented as a sequence of 16 words.

d. 块=512位字符串。块(例如,B)可以表示为16个字的序列。

3. Operations on Words
3. 文字操作

The following logical operators will be applied to words:

以下逻辑运算符将应用于字:

a. Bitwise logical word operations

a. 按位逻辑字运算

X AND Y = bitwise logical "and" of X and Y.

X和Y=X和Y的按位逻辑“AND”。

X OR Y = bitwise logical "inclusive-or" of X and Y.

X或Y=X和Y的按位逻辑“包含或”。

X XOR Y = bitwise logical "exclusive-or" of X and Y.

X XOR Y=X和Y的按位逻辑“异或”。

NOT X = bitwise logical "complement" of X.

NOT X=X的按位逻辑“补码”。

Example:

例子:

               01101100101110011101001001111011
         XOR   01100101110000010110100110110111
               --------------------------------
           =   00001001011110001011101111001100
        
               01101100101110011101001001111011
         XOR   01100101110000010110100110110111
               --------------------------------
           =   00001001011110001011101111001100
        
   b. The operation X + Y is defined as follows:  words X and Y
      represent integers x and y, where 0 <= x < 2^32 and 0 <= y < 2^32.
      For positive integers n and m, let n mod m be the remainder upon
      dividing n by m.  Compute
        
   b. The operation X + Y is defined as follows:  words X and Y
      represent integers x and y, where 0 <= x < 2^32 and 0 <= y < 2^32.
      For positive integers n and m, let n mod m be the remainder upon
      dividing n by m.  Compute
        
         z  =  (x + y) mod 2^32.
        
         z  =  (x + y) mod 2^32.
        

Then 0 <= z < 2^32. Convert z to a word, Z, and define Z = X + Y.

然后0<=z<2^32。将z转换为单词z,并定义z=X+Y。

   c. The circular left shift operation S^n(X), where X is a word and n
      is an integer with 0 <= n < 32, is defined by
        
   c. The circular left shift operation S^n(X), where X is a word and n
      is an integer with 0 <= n < 32, is defined by
        
         S^n(X)  =  (X << n) OR (X >> 32-n).
        
         S^n(X)  =  (X << n) OR (X >> 32-n).
        

In the above, X << n is obtained as follows: discard the left-most n bits of X and then pad the result with n zeroes on the right (the result will still be 32 bits). X >> n is obtained by discarding the right-most n bits of X and then padding the result with n zeroes on the left. Thus S^n(X) is equivalent to a circular shift of X by n positions to the left.

在上面的例子中,X<<n如下所示:丢弃X的最左边的n位,然后在右边用n个零填充结果(结果仍然是32位)。X>>n是通过丢弃X的最右边的n位,然后在左边用n个零填充结果来获得的。因此,S^n(X)相当于X向左移动n个位置。

4. Message Padding
4. 消息填充

SHA-1 is used to compute a message digest for a message or data file that is provided as input. The message or data file should be considered to be a bit string. The length of the message is the number of bits in the message (the empty message has length 0). If the number of bits in a message is a multiple of 8, for compactness we can represent the message in hex. The purpose of message padding is to make the total length of a padded message a multiple of 512. SHA-1 sequentially processes blocks of 512 bits when computing the message digest. The following specifies how this padding shall be performed. As a summary, a "1" followed by m "0"s followed by a 64- bit integer are appended to the end of the message to produce a padded message of length 512 * n. The 64-bit integer is the length of the original message. The padded message is then processed by the SHA-1 as n 512-bit blocks.

SHA-1用于计算作为输入提供的消息或数据文件的消息摘要。消息或数据文件应视为位字符串。消息的长度是消息中的位数(空消息的长度为0)。如果消息中的位数是8的倍数,为了简洁起见,我们可以用十六进制表示消息。消息填充的目的是使填充消息的总长度为512的倍数。在计算消息摘要时,SHA-1顺序处理512位的块。以下规定了应如何进行填充。作为总结,将“1”后跟m“0”后跟64位整数附加到消息末尾,以生成长度为512*n的填充消息。64位整数是原始消息的长度。然后,SHA-1将填充消息作为n 512位块进行处理。

Suppose a message has length l < 2^64. Before it is input to the SHA-1, the message is padded on the right as follows:

假设一条消息的长度l<2^64。在输入到SHA-1之前,消息在右侧填充,如下所示:

a. "1" is appended. Example: if the original message is "01010000", this is padded to "010100001".

a. 附加“1”。示例:如果原始消息为“01010000”,则填充为“010100001”。

b. "0"s are appended. The number of "0"s will depend on the original length of the message. The last 64 bits of the last 512-bit block are reserved

b. 追加了“0”。“0”的数量将取决于消息的原始长度。最后512位块的最后64位保留

for the length l of the original message.

对于原始消息的长度l。

Example: Suppose the original message is the bit string

示例:假设原始消息是位字符串

01100001 01100010 01100011 01100100 01100101.

01100001 01100010 01100011 01100100 01100101.

After step (a) this gives

在步骤(a)之后,给出

01100001 01100010 01100011 01100100 01100101 1.

01100001 01100010 01100011 01100100 01100101 1.

Since l = 40, the number of bits in the above is 41 and 407 "0"s are appended, making the total now 448. This gives (in hex)

因为l=40,上面的位数是41,加上407个“0”,总数现在是448。这给出了(十六进制)

61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000.

61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000.

c. Obtain the 2-word representation of l, the number of bits in the original message. If l < 2^32 then the first word is all zeroes. Append these two words to the padded message.

c. 获取l的2字表示形式,即原始消息中的位数。如果l<2^32,则第一个字为全零。将这两个单词附加到填充的消息中。

Example: Suppose the original message is as in (b). Then l = 40 (note that l is computed before any padding). The two-word representation of 40 is hex 00000000 00000028. Hence the final padded message is hex

示例:假设原始消息如(b)所示。然后l=40(注意,l是在任何填充之前计算的)。40的两个单词表示为十六进制00000000000028。因此,最后的填充消息是hex

61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000028.

61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000028.

The padded message will contain 16 * n words for some n > 0. The padded message is regarded as a sequence of n blocks M(1) , M(2), first characters (or bits) of the message.

填充消息将包含16*n个单词,表示某些n>0。填充消息被视为消息的n个块M(1)、M(2)、第一个字符(或位)的序列。

5. Functions and Constants Used
5. 使用的函数和常量

A sequence of logical functions f(0), f(1),..., f(79) is used in SHA-1. Each f(t), 0 <= t <= 79, operates on three 32-bit words B, C, D and produces a 32-bit word as output. f(t;B,C,D) is defined as follows: for words B, C, D,

SHA-1中使用了一系列逻辑函数f(0),f(1),…,f(79)。每个f(t),0<=t<=79,对三个32位字B、C、D进行运算,并产生一个32位字作为输出。f(t;B,C,D)的定义如下:对于单词B,C,D,

      f(t;B,C,D) = (B AND C) OR ((NOT B) AND D)         ( 0 <= t <= 19)
        
      f(t;B,C,D) = (B AND C) OR ((NOT B) AND D)         ( 0 <= t <= 19)
        
      f(t;B,C,D) = B XOR C XOR D                        (20 <= t <= 39)
        
      f(t;B,C,D) = B XOR C XOR D                        (20 <= t <= 39)
        
      f(t;B,C,D) = (B AND C) OR (B AND D) OR (C AND D)  (40 <= t <= 59)
        
      f(t;B,C,D) = (B AND C) OR (B AND D) OR (C AND D)  (40 <= t <= 59)
        

f(t;B,C,D) = B XOR C XOR D (60 <= t <= 79).

f(t;B,C,D)=B XOR C XOR D(60<=t<=79)。

A sequence of constant words K(0), K(1), ... , K(79) is used in the SHA-1. In hex these are given by

一系列常量字K(0),K(1),SHA-1中使用了K(79)。在十六进制中,它们由

      K(t) = 5A827999         ( 0 <= t <= 19)
        
      K(t) = 5A827999         ( 0 <= t <= 19)
        
      K(t) = 6ED9EBA1         (20 <= t <= 39)
        
      K(t) = 6ED9EBA1         (20 <= t <= 39)
        
      K(t) = 8F1BBCDC         (40 <= t <= 59)
        
      K(t) = 8F1BBCDC         (40 <= t <= 59)
        

K(t) = CA62C1D6 (60 <= t <= 79).

K(t)=CA62C1D6(60<=t<=79)。

6. Computing the Message Digest
6. 计算消息摘要

The methods given in 6.1 and 6.2 below yield the same message digest. Although using method 2 saves sixty-four 32-bit words of storage, it is likely to lengthen execution time due to the increased complexity of the address computations for the { W[t] } in step (c). There are other computation methods which give identical results.

下面6.1和6.2中给出的方法产生相同的消息摘要。尽管使用方法2节省了64个32位的存储字,但由于步骤(c)中{W[t]}的地址计算的复杂性增加,可能会延长执行时间。还有其他的计算方法给出了相同的结果。

6.1 Method 1
6.1 方法1

The message digest is computed using the message padded as described in section 4. The computation is described using two buffers, each consisting of five 32-bit words, and a sequence of eighty 32-bit words. The words of the first 5-word buffer are labeled A,B,C,D,E. The words of the second 5-word buffer are labeled H0, H1, H2, H3, H4. The words of the 80-word sequence are labeled W(0), W(1),..., W(79). A single word buffer TEMP is also employed.

消息摘要使用第4节中描述的填充消息进行计算。使用两个缓冲区描述计算,每个缓冲区由五个32位字和一个由八十个32位字组成的序列组成。第一个5字缓冲区的字标记为A、B、C、D、E。第二个5字缓冲区的字标记为H0、H1、H2、H3、H4。80个单词序列中的单词标记为W(0)、W(1)、…、W(79)。还使用了单字缓冲区TEMP。

To generate the message digest, the 16-word blocks M(1), M(2),..., M(n) defined in section 4 are processed in order. The processing of each M(i) involves 80 steps.

为了生成消息摘要,按顺序处理第4节中定义的16字块M(1)、M(2)、…、M(n)。每个M(i)的处理涉及80个步骤。

Before processing any blocks, the H's are initialized as follows: in hex,

在处理任何块之前,H的初始化如下:十六进制,

      H0 = 67452301
        
      H0 = 67452301
        
      H1 = EFCDAB89
        
      H1 = EFCDAB89
        
      H2 = 98BADCFE
        
      H2 = 98BADCFE
        
      H3 = 10325476
        
      H3 = 10325476
        

H4 = C3D2E1F0.

H4=C3D2E1F0。

Now M(1), M(2), ... , M(n) are processed. To process M(i), we proceed as follows:

现在M(1),M(2),M(n)被处理。为了处理M(i),我们按照以下步骤进行:

a. Divide M(i) into 16 words W(0), W(1), ... , W(15), where W(0) is the left-most word.

a. 将M(i)分为16个单词W(0),W(1),W(15),其中W(0)是最左边的单词。

b. For t = 16 to 79 let

b. 对于t=16至79,让

W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)).

W(t)=S^1(W(t-3)XOR W(t-8)XOR W(t-14)XOR W(t-16))。

c. Let A = H0, B = H1, C = H2, D = H3, E = H4.

c. 设A=H0,B=H1,C=H2,D=H3,E=H4。

d. For t = 0 to 79 do

d. 对于t=0至79 do

         TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t);
        
         TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t);
        
         E = D;  D = C;  C = S^30(B);  B = A; A = TEMP;
        
         E = D;  D = C;  C = S^30(B);  B = A; A = TEMP;
        

e. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.

e. 设H0=H0+A,H1=H1+B,H2=H2+C,H3=H3+D,H4=H4+E。

After processing M(n), the message digest is the 160-bit string represented by the 5 words

在处理M(n)之后,消息摘要是由5个字表示的160位字符串

H0 H1 H2 H3 H4.

h0h1h2h3h4。

6.2 Method 2
6.2 方法2
   The method above assumes that the sequence W(0), ... , W(79) is
   implemented as an array of eighty 32-bit words.  This is efficient
   from the standpoint of minimization of execution time, since the
   addresses of W(t-3), ...  ,W(t-16) in step (b) are easily computed.
   If space is at a premium, an alternative is to regard { W(t) } as a
        
   The method above assumes that the sequence W(0), ... , W(79) is
   implemented as an array of eighty 32-bit words.  This is efficient
   from the standpoint of minimization of execution time, since the
   addresses of W(t-3), ...  ,W(t-16) in step (b) are easily computed.
   If space is at a premium, an alternative is to regard { W(t) } as a
        

circular queue, which may be implemented using an array of sixteen 32-bit words W[0], ... W[15]. In this case, in hex let

循环队列,可使用十六个32位字W[0]的数组实现。。。W[15]。在这种情况下,在hex-let中

MASK = 0000000F. Then processing of M(i) is as follows:

掩码=0000000 F。那么M(i)的处理如下:

a. Divide M(i) into 16 words W[0], ... , W[15], where W[0] is the left-most word.

a. 将M(i)分成16个字W[0],W[15],其中W[0]是最左边的单词。

b. Let A = H0, B = H1, C = H2, D = H3, E = H4.

b. 设A=H0,B=H1,C=H2,D=H3,E=H4。

c. For t = 0 to 79 do

c. 对于t=0至79 do

s = t AND MASK;

s=t和掩模;

         if (t >= 16) W[s] = S^1(W[(s + 13) AND MASK] XOR W[(s + 8) AND
         MASK] XOR W[(s + 2) AND MASK] XOR W[s]);
        
         if (t >= 16) W[s] = S^1(W[(s + 13) AND MASK] XOR W[(s + 8) AND
         MASK] XOR W[(s + 2) AND MASK] XOR W[s]);
        
         TEMP = S^5(A) + f(t;B,C,D) + E + W[s] + K(t);
        
         TEMP = S^5(A) + f(t;B,C,D) + E + W[s] + K(t);
        
         E = D; D = C; C = S^30(B); B = A; A = TEMP;
        
         E = D; D = C; C = S^30(B); B = A; A = TEMP;
        

d. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.

d. 设H0=H0+A,H1=H1+B,H2=H2+C,H3=H3+D,H4=H4+E。

7. C Code
7. C代码

Below is a demonstration implementation of SHA-1 in C. Section 7.1 contains the header file, 7.2 the C code, and 7.3 a test driver.

下面是C中SHA-1的演示实现。第7.1节包含头文件、7.2 C代码和7.3 a测试驱动程序。

7.1 .h file
7.1 .h文件
/*
 *  sha1.h
 *
 *  Description:
 *      This is the header file for code which implements the Secure
 *      Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
 *      April 17, 1995.
 *
 *      Many of the variable names in this code, especially the
 *      single character names, were used because those were the names
 *      used in the publication.
 *
 *      Please read the file sha1.c for more information.
 *
 */
        
/*
 *  sha1.h
 *
 *  Description:
 *      This is the header file for code which implements the Secure
 *      Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
 *      April 17, 1995.
 *
 *      Many of the variable names in this code, especially the
 *      single character names, were used because those were the names
 *      used in the publication.
 *
 *      Please read the file sha1.c for more information.
 *
 */
        

#ifndef _SHA1_H_ #define _SHA1_H_

#如果没有定义_

#include <stdint.h>
/*
 * If you do not have the ISO standard stdint.h header file, then you
 * must typdef the following:
 *    name              meaning
 *  uint32_t         unsigned 32 bit integer
 *  uint8_t          unsigned 8 bit integer (i.e., unsigned char)
 *  int_least16_t    integer of >= 16 bits
 *
 */
        
#include <stdint.h>
/*
 * If you do not have the ISO standard stdint.h header file, then you
 * must typdef the following:
 *    name              meaning
 *  uint32_t         unsigned 32 bit integer
 *  uint8_t          unsigned 8 bit integer (i.e., unsigned char)
 *  int_least16_t    integer of >= 16 bits
 *
 */
        
#ifndef _SHA_enum_
#define _SHA_enum_
enum
{
    shaSuccess = 0,
    shaNull,            /* Null pointer parameter */
    shaInputTooLong,    /* input data too long */
    shaStateError       /* called Input after Result */
};
#endif
#define SHA1HashSize 20
        
#ifndef _SHA_enum_
#define _SHA_enum_
enum
{
    shaSuccess = 0,
    shaNull,            /* Null pointer parameter */
    shaInputTooLong,    /* input data too long */
    shaStateError       /* called Input after Result */
};
#endif
#define SHA1HashSize 20
        
/*
 *  This structure will hold context information for the SHA-1
 *  hashing operation
 */
typedef struct SHA1Context
{
    uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest  */
        
/*
 *  This structure will hold context information for the SHA-1
 *  hashing operation
 */
typedef struct SHA1Context
{
    uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest  */
        
    uint32_t Length_Low;            /* Message length in bits      */
    uint32_t Length_High;           /* Message length in bits      */
        
    uint32_t Length_Low;            /* Message length in bits      */
    uint32_t Length_High;           /* Message length in bits      */
        
                               /* Index into message block array   */
    int_least16_t Message_Block_Index;
    uint8_t Message_Block[64];      /* 512-bit message blocks      */
        
                               /* Index into message block array   */
    int_least16_t Message_Block_Index;
    uint8_t Message_Block[64];      /* 512-bit message blocks      */
        
    int Computed;               /* Is the digest computed?         */
    int Corrupted;             /* Is the message digest corrupted? */
} SHA1Context;
        
    int Computed;               /* Is the digest computed?         */
    int Corrupted;             /* Is the message digest corrupted? */
} SHA1Context;
        
/*
 *  Function Prototypes
 */
        
/*
 *  Function Prototypes
 */
        
int SHA1Reset(  SHA1Context *);
int SHA1Input(  SHA1Context *,
                const uint8_t *,
                unsigned int);
int SHA1Result( SHA1Context *,
                uint8_t Message_Digest[SHA1HashSize]);
        
int SHA1Reset(  SHA1Context *);
int SHA1Input(  SHA1Context *,
                const uint8_t *,
                unsigned int);
int SHA1Result( SHA1Context *,
                uint8_t Message_Digest[SHA1HashSize]);
        

#endif

#恩迪夫

7.2 .c file
7.2 .c文件
/*
 *  sha1.c
 *
 *  Description:
 *      This file implements the Secure Hashing Algorithm 1 as
 *      defined in FIPS PUB 180-1 published April 17, 1995.
 *
 *      The SHA-1, produces a 160-bit message digest for a given
 *      data stream.  It should take about 2**n steps to find a
 *      message with the same digest as a given message and
 *      2**(n/2) to find any two messages with the same digest,
 *      when n is the digest size in bits.  Therefore, this
 *      algorithm can serve as a means of providing a
 *      "fingerprint" for a message.
 *
 *  Portability Issues:
 *      SHA-1 is defined in terms of 32-bit "words".  This code
 *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
 *      bit unsigned integer types.  If your C compiler does not
 *      support 32 bit unsigned integers, this code is not
 *      appropriate.
 *
 *  Caveats:
 *      SHA-1 is designed to work with messages less than 2^64 bits
 *      long.  Although SHA-1 allows a message digest to be generated
 *      for messages of any number of bits less than 2^64, this
 *      implementation only works with messages with a length that is
 *      a multiple of the size of an 8-bit character.
 *
 */
        
/*
 *  sha1.c
 *
 *  Description:
 *      This file implements the Secure Hashing Algorithm 1 as
 *      defined in FIPS PUB 180-1 published April 17, 1995.
 *
 *      The SHA-1, produces a 160-bit message digest for a given
 *      data stream.  It should take about 2**n steps to find a
 *      message with the same digest as a given message and
 *      2**(n/2) to find any two messages with the same digest,
 *      when n is the digest size in bits.  Therefore, this
 *      algorithm can serve as a means of providing a
 *      "fingerprint" for a message.
 *
 *  Portability Issues:
 *      SHA-1 is defined in terms of 32-bit "words".  This code
 *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
 *      bit unsigned integer types.  If your C compiler does not
 *      support 32 bit unsigned integers, this code is not
 *      appropriate.
 *
 *  Caveats:
 *      SHA-1 is designed to work with messages less than 2^64 bits
 *      long.  Although SHA-1 allows a message digest to be generated
 *      for messages of any number of bits less than 2^64, this
 *      implementation only works with messages with a length that is
 *      a multiple of the size of an 8-bit character.
 *
 */
        

#include "sha1.h"

#包括“sha1.h”

/*
 *  Define the SHA1 circular left shift macro
 */
#define SHA1CircularShift(bits,word) \
                (((word) << (bits)) | ((word) >> (32-(bits))))
        
/*
 *  Define the SHA1 circular left shift macro
 */
#define SHA1CircularShift(bits,word) \
                (((word) << (bits)) | ((word) >> (32-(bits))))
        
/* Local Function Prototyptes */
void SHA1PadMessage(SHA1Context *);
void SHA1ProcessMessageBlock(SHA1Context *);
        
/* Local Function Prototyptes */
void SHA1PadMessage(SHA1Context *);
void SHA1ProcessMessageBlock(SHA1Context *);
        
/*
 *  SHA1Reset
 *
 *  Description:
 *      This function will initialize the SHA1Context in preparation
 *      for computing a new SHA1 message digest.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to reset.
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1Reset(SHA1Context *context)
{
    if (!context)
    {
        return shaNull;
    }
        
/*
 *  SHA1Reset
 *
 *  Description:
 *      This function will initialize the SHA1Context in preparation
 *      for computing a new SHA1 message digest.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to reset.
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1Reset(SHA1Context *context)
{
    if (!context)
    {
        return shaNull;
    }
        
    context->Length_Low             = 0;
    context->Length_High            = 0;
    context->Message_Block_Index    = 0;
        
    context->Length_Low             = 0;
    context->Length_High            = 0;
    context->Message_Block_Index    = 0;
        
    context->Intermediate_Hash[0]   = 0x67452301;
    context->Intermediate_Hash[1]   = 0xEFCDAB89;
    context->Intermediate_Hash[2]   = 0x98BADCFE;
    context->Intermediate_Hash[3]   = 0x10325476;
    context->Intermediate_Hash[4]   = 0xC3D2E1F0;
        
    context->Intermediate_Hash[0]   = 0x67452301;
    context->Intermediate_Hash[1]   = 0xEFCDAB89;
    context->Intermediate_Hash[2]   = 0x98BADCFE;
    context->Intermediate_Hash[3]   = 0x10325476;
    context->Intermediate_Hash[4]   = 0xC3D2E1F0;
        
    context->Computed   = 0;
    context->Corrupted  = 0;
        
    context->Computed   = 0;
    context->Corrupted  = 0;
        
    return shaSuccess;
}
        
    return shaSuccess;
}
        
/*
 *  SHA1Result
 *
 *  Description:
 *      This function will return the 160-bit message digest into the
 *      Message_Digest array  provided by the caller.
 *      NOTE: The first octet of hash is stored in the 0th element,
 *            the last octet of hash in the 19th element.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to use to calculate the SHA-1 hash.
 *      Message_Digest: [out]
 *          Where the digest is returned.
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1Result( SHA1Context *context,
                uint8_t Message_Digest[SHA1HashSize])
{
    int i;
        
/*
 *  SHA1Result
 *
 *  Description:
 *      This function will return the 160-bit message digest into the
 *      Message_Digest array  provided by the caller.
 *      NOTE: The first octet of hash is stored in the 0th element,
 *            the last octet of hash in the 19th element.
 *
 *  Parameters:
 *      context: [in/out]
 *          The context to use to calculate the SHA-1 hash.
 *      Message_Digest: [out]
 *          Where the digest is returned.
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1Result( SHA1Context *context,
                uint8_t Message_Digest[SHA1HashSize])
{
    int i;
        
    if (!context || !Message_Digest)
    {
        return shaNull;
    }
        
    if (!context || !Message_Digest)
    {
        return shaNull;
    }
        
    if (context->Corrupted)
    {
        return context->Corrupted;
    }
        
    if (context->Corrupted)
    {
        return context->Corrupted;
    }
        
    if (!context->Computed)
    {
        SHA1PadMessage(context);
        for(i=0; i<64; ++i)
        {
            /* message may be sensitive, clear it out */
            context->Message_Block[i] = 0;
        }
        context->Length_Low = 0;    /* and clear length */
        context->Length_High = 0;
        context->Computed = 1;
        
    if (!context->Computed)
    {
        SHA1PadMessage(context);
        for(i=0; i<64; ++i)
        {
            /* message may be sensitive, clear it out */
            context->Message_Block[i] = 0;
        }
        context->Length_Low = 0;    /* and clear length */
        context->Length_High = 0;
        context->Computed = 1;
        

}

}

    for(i = 0; i < SHA1HashSize; ++i)
    {
        Message_Digest[i] = context->Intermediate_Hash[i>>2]
                            >> 8 * ( 3 - ( i & 0x03 ) );
    }
        
    for(i = 0; i < SHA1HashSize; ++i)
    {
        Message_Digest[i] = context->Intermediate_Hash[i>>2]
                            >> 8 * ( 3 - ( i & 0x03 ) );
    }
        
    return shaSuccess;
}
        
    return shaSuccess;
}
        
/*
 *  SHA1Input
 *
 *  Description:
 *      This function accepts an array of octets as the next portion
 *      of the message.
 *
 *  Parameters:
 *      context: [in/out]
 *          The SHA context to update
 *      message_array: [in]
 *          An array of characters representing the next portion of
 *          the message.
 *      length: [in]
 *          The length of the message in message_array
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1Input(    SHA1Context    *context,
                  const uint8_t  *message_array,
                  unsigned       length)
{
    if (!length)
    {
        return shaSuccess;
    }
        
/*
 *  SHA1Input
 *
 *  Description:
 *      This function accepts an array of octets as the next portion
 *      of the message.
 *
 *  Parameters:
 *      context: [in/out]
 *          The SHA context to update
 *      message_array: [in]
 *          An array of characters representing the next portion of
 *          the message.
 *      length: [in]
 *          The length of the message in message_array
 *
 *  Returns:
 *      sha Error Code.
 *
 */
int SHA1Input(    SHA1Context    *context,
                  const uint8_t  *message_array,
                  unsigned       length)
{
    if (!length)
    {
        return shaSuccess;
    }
        
    if (!context || !message_array)
    {
        return shaNull;
    }
        
    if (!context || !message_array)
    {
        return shaNull;
    }
        
    if (context->Computed)
    {
        context->Corrupted = shaStateError;
        
    if (context->Computed)
    {
        context->Corrupted = shaStateError;
        
        return shaStateError;
    }
        
        return shaStateError;
    }
        
    if (context->Corrupted)
    {
         return context->Corrupted;
    }
    while(length-- && !context->Corrupted)
    {
    context->Message_Block[context->Message_Block_Index++] =
                    (*message_array & 0xFF);
        
    if (context->Corrupted)
    {
         return context->Corrupted;
    }
    while(length-- && !context->Corrupted)
    {
    context->Message_Block[context->Message_Block_Index++] =
                    (*message_array & 0xFF);
        
    context->Length_Low += 8;
    if (context->Length_Low == 0)
    {
        context->Length_High++;
        if (context->Length_High == 0)
        {
            /* Message is too long */
            context->Corrupted = 1;
        }
    }
        
    context->Length_Low += 8;
    if (context->Length_Low == 0)
    {
        context->Length_High++;
        if (context->Length_High == 0)
        {
            /* Message is too long */
            context->Corrupted = 1;
        }
    }
        
    if (context->Message_Block_Index == 64)
    {
        SHA1ProcessMessageBlock(context);
    }
        
    if (context->Message_Block_Index == 64)
    {
        SHA1ProcessMessageBlock(context);
    }
        
    message_array++;
    }
        
    message_array++;
    }
        
    return shaSuccess;
}
        
    return shaSuccess;
}
        
/*
 *  SHA1ProcessMessageBlock
 *
 *  Description:
 *      This function will process the next 512 bits of the message
 *      stored in the Message_Block array.
 *
 *  Parameters:
 *      None.
 *
 *  Returns:
 *      Nothing.
 *
 *  Comments:
        
/*
 *  SHA1ProcessMessageBlock
 *
 *  Description:
 *      This function will process the next 512 bits of the message
 *      stored in the Message_Block array.
 *
 *  Parameters:
 *      None.
 *
 *  Returns:
 *      Nothing.
 *
 *  Comments:
        
 *      Many of the variable names in this code, especially the
 *      single character names, were used because those were the
 *      names used in the publication.
 *
 *
 */
void SHA1ProcessMessageBlock(SHA1Context *context)
{
    const uint32_t K[] =    {       /* Constants defined in SHA-1   */
                            0x5A827999,
                            0x6ED9EBA1,
                            0x8F1BBCDC,
                            0xCA62C1D6
                            };
    int           t;                 /* Loop counter                */
    uint32_t      temp;              /* Temporary word value        */
    uint32_t      W[80];             /* Word sequence               */
    uint32_t      A, B, C, D, E;     /* Word buffers                */
        
 *      Many of the variable names in this code, especially the
 *      single character names, were used because those were the
 *      names used in the publication.
 *
 *
 */
void SHA1ProcessMessageBlock(SHA1Context *context)
{
    const uint32_t K[] =    {       /* Constants defined in SHA-1   */
                            0x5A827999,
                            0x6ED9EBA1,
                            0x8F1BBCDC,
                            0xCA62C1D6
                            };
    int           t;                 /* Loop counter                */
    uint32_t      temp;              /* Temporary word value        */
    uint32_t      W[80];             /* Word sequence               */
    uint32_t      A, B, C, D, E;     /* Word buffers                */
        
    /*
     *  Initialize the first 16 words in the array W
     */
    for(t = 0; t < 16; t++)
    {
        W[t] = context->Message_Block[t * 4] << 24;
        W[t] |= context->Message_Block[t * 4 + 1] << 16;
        W[t] |= context->Message_Block[t * 4 + 2] << 8;
        W[t] |= context->Message_Block[t * 4 + 3];
    }
        
    /*
     *  Initialize the first 16 words in the array W
     */
    for(t = 0; t < 16; t++)
    {
        W[t] = context->Message_Block[t * 4] << 24;
        W[t] |= context->Message_Block[t * 4 + 1] << 16;
        W[t] |= context->Message_Block[t * 4 + 2] << 8;
        W[t] |= context->Message_Block[t * 4 + 3];
    }
        
    for(t = 16; t < 80; t++)
    {
       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
    }
        
    for(t = 16; t < 80; t++)
    {
       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
    }
        
    A = context->Intermediate_Hash[0];
    B = context->Intermediate_Hash[1];
    C = context->Intermediate_Hash[2];
    D = context->Intermediate_Hash[3];
    E = context->Intermediate_Hash[4];
        
    A = context->Intermediate_Hash[0];
    B = context->Intermediate_Hash[1];
    C = context->Intermediate_Hash[2];
    D = context->Intermediate_Hash[3];
    E = context->Intermediate_Hash[4];
        
    for(t = 0; t < 20; t++)
    {
        temp =  SHA1CircularShift(5,A) +
                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        
    for(t = 0; t < 20; t++)
    {
        temp =  SHA1CircularShift(5,A) +
                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        
        B = A;
        A = temp;
    }
        
        B = A;
        A = temp;
    }
        
    for(t = 20; t < 40; t++)
    {
        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        B = A;
        A = temp;
    }
        
    for(t = 20; t < 40; t++)
    {
        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        B = A;
        A = temp;
    }
        
    for(t = 40; t < 60; t++)
    {
        temp = SHA1CircularShift(5,A) +
               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        B = A;
        A = temp;
    }
        
    for(t = 40; t < 60; t++)
    {
        temp = SHA1CircularShift(5,A) +
               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        B = A;
        A = temp;
    }
        
    for(t = 60; t < 80; t++)
    {
        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        B = A;
        A = temp;
    }
        
    for(t = 60; t < 80; t++)
    {
        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
        E = D;
        D = C;
        C = SHA1CircularShift(30,B);
        B = A;
        A = temp;
    }
        
    context->Intermediate_Hash[0] += A;
    context->Intermediate_Hash[1] += B;
    context->Intermediate_Hash[2] += C;
    context->Intermediate_Hash[3] += D;
    context->Intermediate_Hash[4] += E;
        
    context->Intermediate_Hash[0] += A;
    context->Intermediate_Hash[1] += B;
    context->Intermediate_Hash[2] += C;
    context->Intermediate_Hash[3] += D;
    context->Intermediate_Hash[4] += E;
        
    context->Message_Block_Index = 0;
}
        
    context->Message_Block_Index = 0;
}
        
/*
 *  SHA1PadMessage
 *
        
/*
 *  SHA1PadMessage
 *
        

* Description: * According to the standard, the message must be padded to an even * 512 bits. The first padding bit must be a '1'. The last 64 * bits represent the length of the original message. All bits in * between should be 0. This function will pad the message * according to those rules by filling the Message_Block array * accordingly. It will also call the ProcessMessageBlock function * provided appropriately. When it returns, it can be assumed that * the message digest has been computed. * * Parameters: * context: [in/out] * The context to pad * ProcessMessageBlock: [in] * The appropriate SHA*ProcessMessageBlock function * Returns: * Nothing. * */

* 描述:*根据标准,消息必须填充到偶数*512位。第一个填充位必须是“1”。最后64*位表示原始消息的长度。*之间的所有位应为0。此函数将根据这些规则填充消息块数组*,从而填充消息*。它还将调用适当提供的ProcessMessageBlock函数*。当它返回时,可以假定*消息摘要已计算。**参数:*上下文:[in/out]*要填充的上下文*ProcessMessageBlock:[in]*相应的SHA*ProcessMessageBlock函数*返回:*无。**/

void SHA1PadMessage(SHA1Context *context)
{
    /*
     *  Check to see if the current message block is too small to hold
     *  the initial padding bits and length.  If so, we will pad the
     *  block, process it, and then continue padding into a second
     *  block.
     */
    if (context->Message_Block_Index > 55)
    {
        context->Message_Block[context->Message_Block_Index++] = 0x80;
        while(context->Message_Block_Index < 64)
        {
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
        
void SHA1PadMessage(SHA1Context *context)
{
    /*
     *  Check to see if the current message block is too small to hold
     *  the initial padding bits and length.  If so, we will pad the
     *  block, process it, and then continue padding into a second
     *  block.
     */
    if (context->Message_Block_Index > 55)
    {
        context->Message_Block[context->Message_Block_Index++] = 0x80;
        while(context->Message_Block_Index < 64)
        {
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
        

SHA1ProcessMessageBlock(context);

SHA1ProcessMessageBlock(上下文);

        while(context->Message_Block_Index < 56)
        {
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
    }
    else
    {
        context->Message_Block[context->Message_Block_Index++] = 0x80;
        while(context->Message_Block_Index < 56)
        {
        
        while(context->Message_Block_Index < 56)
        {
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
    }
    else
    {
        context->Message_Block[context->Message_Block_Index++] = 0x80;
        while(context->Message_Block_Index < 56)
        {
        
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
    }
        
            context->Message_Block[context->Message_Block_Index++] = 0;
        }
    }
        
    /*
     *  Store the message length as the last 8 octets
     */
    context->Message_Block[56] = context->Length_High >> 24;
    context->Message_Block[57] = context->Length_High >> 16;
    context->Message_Block[58] = context->Length_High >> 8;
    context->Message_Block[59] = context->Length_High;
    context->Message_Block[60] = context->Length_Low >> 24;
    context->Message_Block[61] = context->Length_Low >> 16;
    context->Message_Block[62] = context->Length_Low >> 8;
    context->Message_Block[63] = context->Length_Low;
        
    /*
     *  Store the message length as the last 8 octets
     */
    context->Message_Block[56] = context->Length_High >> 24;
    context->Message_Block[57] = context->Length_High >> 16;
    context->Message_Block[58] = context->Length_High >> 8;
    context->Message_Block[59] = context->Length_High;
    context->Message_Block[60] = context->Length_Low >> 24;
    context->Message_Block[61] = context->Length_Low >> 16;
    context->Message_Block[62] = context->Length_Low >> 8;
    context->Message_Block[63] = context->Length_Low;
        
    SHA1ProcessMessageBlock(context);
}
        
    SHA1ProcessMessageBlock(context);
}
        
7.3 Test Driver
7.3 试驾

The following code is a main program test driver to exercise the code in sha1.c.

下面的代码是一个主程序测试驱动程序,用于练习sha1.c中的代码。

/*
 *  sha1test.c
 *
 *  Description:
 *      This file will exercise the SHA-1 code performing the three
 *      tests documented in FIPS PUB 180-1 plus one which calls
 *      SHA1Input with an exact multiple of 512 bits, plus a few
 *      error test checks.
 *
 *  Portability Issues:
 *      None.
 *
 */
        
/*
 *  sha1test.c
 *
 *  Description:
 *      This file will exercise the SHA-1 code performing the three
 *      tests documented in FIPS PUB 180-1 plus one which calls
 *      SHA1Input with an exact multiple of 512 bits, plus a few
 *      error test checks.
 *
 *  Portability Issues:
 *      None.
 *
 */
        
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sha1.h"
        
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sha1.h"
        
/*
 *  Define patterns for testing
 */
#define TEST1   "abc"
#define TEST2a  "abcdbcdecdefdefgefghfghighijhi"
        
/*
 *  Define patterns for testing
 */
#define TEST1   "abc"
#define TEST2a  "abcdbcdecdefdefgefghfghighijhi"
        
#define TEST2b  "jkijkljklmklmnlmnomnopnopq"
#define TEST2   TEST2a TEST2b
#define TEST3   "a"
#define TEST4a  "01234567012345670123456701234567"
#define TEST4b  "01234567012345670123456701234567"
    /* an exact multiple of 512 bits */
#define TEST4   TEST4a TEST4b
char *testarray[4] =
{
    TEST1,
    TEST2,
    TEST3,
    TEST4
};
long int repeatcount[4] = { 1, 1, 1000000, 10 };
char *resultarray[4] =
{
    "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
    "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
    "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
    "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
};
        
#define TEST2b  "jkijkljklmklmnlmnomnopnopq"
#define TEST2   TEST2a TEST2b
#define TEST3   "a"
#define TEST4a  "01234567012345670123456701234567"
#define TEST4b  "01234567012345670123456701234567"
    /* an exact multiple of 512 bits */
#define TEST4   TEST4a TEST4b
char *testarray[4] =
{
    TEST1,
    TEST2,
    TEST3,
    TEST4
};
long int repeatcount[4] = { 1, 1, 1000000, 10 };
char *resultarray[4] =
{
    "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
    "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
    "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
    "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
};
        
int main()
{
    SHA1Context sha;
    int i, j, err;
    uint8_t Message_Digest[20];
        
int main()
{
    SHA1Context sha;
    int i, j, err;
    uint8_t Message_Digest[20];
        
    /*
     *  Perform SHA-1 tests
     */
    for(j = 0; j < 4; ++j)
    {
        printf( "\nTest %d: %d, '%s'\n",
                j+1,
                repeatcount[j],
                testarray[j]);
        
    /*
     *  Perform SHA-1 tests
     */
    for(j = 0; j < 4; ++j)
    {
        printf( "\nTest %d: %d, '%s'\n",
                j+1,
                repeatcount[j],
                testarray[j]);
        
        err = SHA1Reset(&sha);
        if (err)
        {
            fprintf(stderr, "SHA1Reset Error %d.\n", err );
            break;    /* out of for j loop */
        }
        
        err = SHA1Reset(&sha);
        if (err)
        {
            fprintf(stderr, "SHA1Reset Error %d.\n", err );
            break;    /* out of for j loop */
        }
        
        for(i = 0; i < repeatcount[j]; ++i)
        {
        
        for(i = 0; i < repeatcount[j]; ++i)
        {
        
            err = SHA1Input(&sha,
                  (const unsigned char *) testarray[j],
                  strlen(testarray[j]));
            if (err)
            {
                fprintf(stderr, "SHA1Input Error %d.\n", err );
                break;    /* out of for i loop */
            }
        }
        
            err = SHA1Input(&sha,
                  (const unsigned char *) testarray[j],
                  strlen(testarray[j]));
            if (err)
            {
                fprintf(stderr, "SHA1Input Error %d.\n", err );
                break;    /* out of for i loop */
            }
        }
        
        err = SHA1Result(&sha, Message_Digest);
        if (err)
        {
            fprintf(stderr,
            "SHA1Result Error %d, could not compute message digest.\n",
            err );
        }
        else
        {
            printf("\t");
            for(i = 0; i < 20 ; ++i)
            {
                printf("%02X ", Message_Digest[i]);
            }
            printf("\n");
        }
        printf("Should match:\n");
        printf("\t%s\n", resultarray[j]);
    }
        
        err = SHA1Result(&sha, Message_Digest);
        if (err)
        {
            fprintf(stderr,
            "SHA1Result Error %d, could not compute message digest.\n",
            err );
        }
        else
        {
            printf("\t");
            for(i = 0; i < 20 ; ++i)
            {
                printf("%02X ", Message_Digest[i]);
            }
            printf("\n");
        }
        printf("Should match:\n");
        printf("\t%s\n", resultarray[j]);
    }
        
    /* Test some error returns */
    err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1);
    printf ("\nError %d. Should be %d.\n", err, shaStateError );
    err = SHA1Reset(0);
    printf ("\nError %d. Should be %d.\n", err, shaNull );
    return 0;
}
        
    /* Test some error returns */
    err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1);
    printf ("\nError %d. Should be %d.\n", err, shaStateError );
    err = SHA1Reset(0);
    printf ("\nError %d. Should be %d.\n", err, shaNull );
    return 0;
}
        
8. Security Considerations
8. 安全考虑

This document is intended to provide convenient open source access by the Internet community to the United States of America Federal Information Processing Standard Secure Hash Function SHA-1 [FIPS 180-1]. No independent assertion of the security of this hash function by the authors for any particular use is intended.

本文件旨在为互联网社区提供方便的开放源码访问美利坚合众国联邦信息处理标准安全哈希函数SHA-1[FIPS 180-1]。作者无意为任何特定用途独立断言此哈希函数的安全性。

References

工具书类

[FIPS 180-1] "Secure Hash Standard", United States of American, National Institute of Science and Technology, Federal Information Processing Standard (FIPS) 180-1, April 1993.

[FIPS 180-1]“安全哈希标准”,美利坚合众国,国家科学技术研究所,联邦信息处理标准(FIPS)180-11993年4月。

[MD4] "The MD4 Message Digest Algorithm," Advances in Cryptology - CRYPTO '90 Proceedings, Springer-Verlag, 1991, pp. 303-311.

[MD4]“MD4消息摘要算法”,密码学进展-加密'90会议记录,Springer Verlag,1991年,第303-311页。

[RFC 1320] Rivest, R., "The MD4 Message-Digest Algorithm", RFC 1320, April 1992.

[RFC 1320]Rivest,R.,“MD4消息摘要算法”,RFC 1320,1992年4月。

[RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April 1992.

[RFC 1321]Rivest,R.,“MD5消息摘要算法”,RFC 1321,1992年4月。

[RFC 1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness Requirements for Security", RFC 1750, December 1994.

[RFC 1750]Eastlake,D.,Crocker,S.和J.Schiller,“安全的随机性要求”,RFC 1750,1994年12月。

Authors' Addresses

作者地址

Donald E. Eastlake, 3rd Motorola 155 Beaver Street Milford, MA 01757 USA

美国马萨诸塞州米尔福德海狸街155号摩托罗拉3号唐纳德E.伊斯特莱克01757

   Phone:   +1 508-634-2066 (h)
            +1 508-261-5434 (w)
   Fax:     +1 508-261-4777
   EMail:   Donald.Eastlake@motorola.com
        
   Phone:   +1 508-634-2066 (h)
            +1 508-261-5434 (w)
   Fax:     +1 508-261-4777
   EMail:   Donald.Eastlake@motorola.com
        

Paul E. Jones Cisco Systems, Inc. 7025 Kit Creek Road Research Triangle Park, NC 27709 USA

Paul E.Jones Cisco Systems,Inc.美国北卡罗来纳州Kit Creek Road研究三角公园7025号,邮编:27709

   Phone:   +1 919 392 6948
   EMail:   paulej@packetizer.com
        
   Phone:   +1 919 392 6948
   EMail:   paulej@packetizer.com
        

Full Copyright Statement

完整版权声明

Copyright (C) The Internet Society (2001). All Rights Reserved.

版权所有(C)互联网协会(2001年)。版权所有。

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

本文件及其译本可复制并提供给他人,对其进行评论或解释或协助其实施的衍生作品可全部或部分编制、复制、出版和分发,不受任何限制,前提是上述版权声明和本段包含在所有此类副本和衍生作品中。但是,不得以任何方式修改本文件本身,例如删除版权通知或对互联网协会或其他互联网组织的引用,除非出于制定互联网标准的需要,在这种情况下,必须遵循互联网标准过程中定义的版权程序,或根据需要将其翻译成英语以外的其他语言。

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

上述授予的有限许可是永久性的,互联网协会或其继承人或受让人不会撤销。

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

本文件和其中包含的信息是按“原样”提供的,互联网协会和互联网工程任务组否认所有明示或暗示的保证,包括但不限于任何保证,即使用本文中的信息不会侵犯任何权利,或对适销性或特定用途适用性的任何默示保证。

Acknowledgement

确认

Funding for the RFC Editor function is currently provided by the Internet Society.

RFC编辑功能的资金目前由互联网协会提供。