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) このメモの位置付け このメモは、インターネット・コミュニティに情報を提供するものである。 インターネット標準を規定するものではない。このメモの配布は無制限である。 著作権表示 Copyright (C) The Internet Society (2001). All Rights Reserved. 要旨 本ドキュメントの目的は、SHA-1 (Secure Hash Algorithm 1) を、インターネット・ コミュニティが簡単に利用できるようにすることである。アメリカ合衆国は、ここで 記述するSHA-1ハッシュアルゴリズムをFederal Information Processing Standard として採用している。本ドキュメントのほとんどの文章は、FIPS 180-1から転記 したものである。C言語による実装のみが「オリジナル」である。 謝辞 本ドキュメントのほとんどの文章は、[FIPS 180-1] からのものである。C言語による 実装のみが「オリジナル」である。実装方法は、すでに発行されているMD4とMD5 のRFC [RFC 1320, 1321]と同様の形式で記述している。 SHA-1は、MITのRonald L. Rivest教授がMD4メッセージダイジェストアルゴリズム [MD4] を設計したときに使用した原理と同様の原理に基づいており、またその アルゴリズムをモデルとしている [RFC 1320]。 本ドキュメントに含まれている有用なコメントを以下の方々より頂いた。ここに 感謝する。 Tony Hansen Garrett Wollman 目次 1. 概要 .......................................................... 2 2. ビット文字列と整数の定義 ...................................... 3 3. それぞれのワードに対する演算 .................................. 3 4. メッセージへのパディング ...................................... 4 5. メッセージへのパディング ...................................... 6 6. 使用関数と使用定数 ............................................ 6 6.1 方法 1 ....................................................... 6 6.2 方法 2 ....................................................... 7 7. C言語コード ................................................... 8 7.1 .h ファイル .................................................. 8 7.2 .c ファイル .................................................. 10 7.3 テストドライバ ............................................... 18 8. セキュリティに関する考察 ...................................... 20 参考文献 ......................................................... 21 著者のアドレス ................................................... 21 著作権表示 ....................................................... 22 1. 概要 注:下記の文章は、そのほとんどを[FIPS 180-1]から転記したものであり、SHA-1の セキュリティ検証は合衆国政府、[FIPS 180-1]の著者とその他の方々によって 行われている。 本ドキュメントでは、メッセージもしくはデータファイルの圧縮表記を計算する ためのSecure Hash Algorithm、SHA-1を規定する。2^64ビット以下の長さを持つ メッセージの入力に対して、SHA-1ではメッセージダイジェストと呼ばれる160 ビットの出力値を生成する。メッセージダイジェストは、例えばメッセージ の署名作成または検証を行うための署名アルゴリズムへの入力となる。メッセージ 自体ではなくメッセージダイジェストに署名を行うことで、通常は署名処理の 効率が向上する。これは通常メッセージダイジェストはメッセージよりもサイズ が小さいからである。デジタル署名を作成するのに使用したアルゴリズムと同じ アルゴリズムを使用してデジタル署名の検証を行わなければならない。メッセージ の転送中にメッセージへの変更が発生すると、非常に高い確率で異なるメッセージ ダイジェストを計算することになるため、署名検証に失敗することになる。 SHA-1は安全であるとされている。それは与えられたメッセージダイジェストから メッセージを発見したり、同じメッセージダイジェストを持つ異なる2つのメッ セージを発見したりすることが計算上不可能だからである。メッセージの転送中 にメッセージへの変更が発生すると、非常に高い確率で異なるメッセージ ダイジェストを計算することになるため、署名検証に失敗することになる。 第2章以下では、用語や、ブロック化を行いSHA-1処理を行う機能を定義する。 2. ビット文字列と整数の定義 ビット文字列と整数に関する以下の用語を使用する。 a. 16進数とは、{0, 1, ... , 9, A, ... , F}で構成されている集合の中の 1つの要素である。16進数は4ビット文字列を表記したものである。 例: 7 = 0111, A = 1010 b. ワードとは32ビットの文字列のことで、8個の16進数の列で表記される。 1つのワードを8個の16進数に変換するには、4ビット文字列ごとに、 (a)で定義される16進数に変換する。 例: 1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23 c. 0から2^32 - 1までの間の整数は、1つのワードで表記することが出来る。 整数における最下位4ビットは、ワードの16進数表記における最も右側 の16進数となる。 例: 整数 291 = 2^8+2^5+2^1+2^0 = 256+32+2+1 は、16進数で00000123と表記される。 z を 0 <= z < 2^64 の整数とすると、z = (2^32)x + y 、ただし 0 <= x < 2^32 であり 0 <= y < 2^32 である。x と y はそれぞれワード X と Y として表記できるため、z はワードの組(X,Y)として表記できる。 d. ブロックとは、512ビットの文字列である。 1つのブロック(例:B)は、 16ワード列として表記できる。 3. それぞれのワードに対する演算 以下の論理演算が、ワードに対して適用される。 a. ビットごとの論理ワード演算 X AND Y = X と Y の、ビットごとの論理積 X OR Y = X と Y の、ビットごとの論理和 X XOR Y = X と Y の、ビットごとの排他的論理和 NOT X = X のビットごとの論理否定 例: 01101100101110011101001001111011 XOR 01100101110000010110100110110111 -------------------------------- = 00001001011110001011101111001100 b. 演算 X + Y は以下のように定義される。ワード X と Y は、整数 x と y を表す。ここで 0 <= x < 2^32 であり、また 0 <= y < 2^32 である。 正の整数 n と m に対し、n mod m を、m で n を割ったときの剰余とする。 以下を計算する。 z = (x + y) mod 2^32 このとき、0 <= z < 2^32 となる。そして z を1ワード Z に変換したものを、 Z = X + Y と定義する。 c. X は1ワード、n は 0 <= n < 32 となる整数であるとき、循環左シフト演算 S^n(X) は以下のように定義される。 S^n(X) = (X << n) OR (X >> 32-n) 上式における、X << n は以下のようにして得られる。X の左 n ビット を捨て、n ビットのゼロを右に付加する(結果はやはり32ビットである)。 上式における X >> n は、X の右 n ビットを捨て、n ビットのゼロを 左に付加することで得られる。したがって S^n(X) は、X を n 個分左に 循環シフトしたものと等価となる。 4. メッセージへのパディング SHA-1は、入力として提供されるメッセージまたはデータファイルのメッセージ ダイジェストを計算するのに使用される。メッセージまたはデータファイルは、 ビット文字列と見なされる。メッセージ長は、メッセージのビット数(空メッ セージは長さ0)である。メッセージのビット数が8の倍数であれば、簡便さのため メッセージを16進数で表す。メッセージに対してはパディングを行うが、その 目的はパディングを行った後のメッセージ長が512の倍数になるようにすること である。SHA-1では、メッセージダイジェストを計算する際に、512ビットのブロック ごとに処理を行う。以下では、このパディングがどのように行われるかについて 記述する。簡単に述べると、1つの"1"を付加し、その後にm個の"0"を付加して、 最後に64ビットの整数を付加することで、メッセージ長を512 * n とする。この 64ビット整数というのは、オリジナルメッセージの長さである。パディングの 行われたメッセージは、その後n個の512ビットブロックとして解釈され、SHA-1 により処理される。 あるメッセージの長さ l が、l < 2^64 であるとする。これをSHA-1に入力する前に、 メッセージはその右側に対して以下のようなパディングを行う。 a. 1個の"1"を付加する。 例:オリジナルメッセージが"01010000"であるとき、パディングされた メッセージは"010100001"である。 b. "0"を付加する。付加する"0"の個数はオリジナルメッセージの長さに依存 する。最後の512ビットブロックにおける最後の64ビットは、オリジナル メッセージの長さ l を格納するために予約されている。 例:オリジナルメッセージが以下のようなビット文字列であったとき、 01100001 01100010 01100011 01100100 01100101 ステップ(a)の処理を行うと、以下のようになる。 01100001 01100010 01100011 01100100 01100101 1 l = 40 であるため、上記のビット数は41ビットであり、407個の"0"が付加 されて448ビットとされる。したがって、16進数で以下のようになる。 61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 c. オリジナルメッセージのビット数 l を2ワードで表記する。l < 2^32 であれば、 最初のワードはすべて0になる。これらの2ワードをメッセージに付加する。 例:オリジナルメッセージが(b)と同じである場合、l = 40 となる( l は パディングを行う前に計算することに注意)。40を2ワード表記すると16進数で 00000000 00000028となる。それゆえパディング処理により最終的に得られる メッセージは、16進数で以下のようになる。 61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000028 パディングされたメッセージには、16 * n 個(ただし任意の n > 0 )の ワードが含まれている。パディングされたメッセージは、最初の文字(もし くはビット)から順に、n 個のブロック M(1), M(2), となる。 5. 使用関数と使用定数 SHA-1では、論理関数のシーケンス f(0), f(1),..., f(79)を使用する。それぞれの f(t), 0 <= t <= 79 では、3つの32ビットワードB, C, Dを処理し1つの32ビット ワードを出力する。ワードB, C, Dに対し、f(t;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 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 XOR C XOR D (60 <= t <= 79) SHA-1では、定数ワードのシーケンス K(0), K(1), ... , K(79) を使用する。 それぞれは、16進表記で以下のように定義される。 K(t) = 5A827999 ( 0 <= t <= 19) K(t) = 6ED9EBA1 (20 <= t <= 39) K(t) = 8F1BBCDC (40 <= t <= 59) K(t) = CA62C1D6 (60 <= t <= 79) 6. メッセージダイジェストの計算 以下の第6.1節と6.2節で示されている2つの方法は、どちらも同じダイジェスト値を 出力する。方法2は方法1に比べ、32ビットワード64個分の記憶域を使用しなくて済むが、 ステップcにおけるそれぞれの W[t] のアドレス計算が複雑であるため実行時間が長く なるようである。同じ結果を出力する他の計算方法も存在する。 6.1 方法 1 メッセージダイジェストは、第4章で示されているメッセージパディングを使用して 計算する。計算に際して2つのバッファを使用する。それぞれのバッファは32ビット ワード5つ分で構成されている。さらに32ビットワード80個分のワードシーケンスを 1つ使用する。1つの5ワードバッファにおけるそれぞれのワードを A,B,C,D,E とする。 もう1つの5ワードバッファにおけるそれぞれのワードを H0, H1, H2, H3, H4とする。 80ワードシーケンスにおけるそれぞれのワードは W(0), W(1),..., W(79) とする。 そして1ワードのバッファTEMPを使用する。 メッセージダイジェストの計算では、第4章で定義された16ワードブロックM(1), M(2),...,M(n)を、この順序で処理する。それぞれのM(i)の処理に対して80ステップ の処理が行われる。 ワードブロックを処理する前に、それぞれのHを以下のように初期化する(16進で 表記している)。 H0 = 67452301 H1 = EFCDAB89 H2 = 98BADCFE H3 = 10325476 H4 = C3D2E1F0. そして M(1), M(2), ... , M(n) の計算を行う。 M(i)の処理を以下のように行う。 a. M(i)を、16個のワード W(0), W(1), ... , W(15) に分割する。ここで W(0) は 最上位ワードである。 b. 16から79までのtに対して、以下の計算を行う。 W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)) c. A, B, C, D, E をそれぞれ、A = H0, B = H1, C = H2, D = H3, E = H4 とする。 d. 0から79までの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. HO, H1, H2, H3, H4 をそれぞれ、H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E とする。 M(n)の処理を行うと、メッセージダイジェストは、以下の5ワードで表される160ビットの 文字列として得られる。 H0 H1 H2 H3 H4 6.2 方法 2 上記の方法では、シーケンスW(0), ... , W(79)は32ビットワード80個をもつ配列 として実装されることを仮定している。これは実行時間を最小化するという点から 見ると効果的であるといえる。それはステップbにおけるW(t-3), ... ,W(t-16)の アドレスが簡単に求まるからである。しかしメモリ使用量を極力抑えたい場合には、 他の計算方法として、W(t)の列を循環キューと見なす方法がある。この場合、16個の 32ビットワードW[0], ... W[15]の配列を使用するような実装を行うことができる。 ここではMASKを、16進表記で MASK = 0000000F と定義する。M(i)の計算は以下の ようになる。 a. M(i)を、16個のワード W[0], ... , W[15] に分割する。ここで W[0] は 最上位ワードである。 b. A, B, C, D, E をそれぞれ、A = H0, B = H1, C = H2, D = H3, E = H4 とする。 c. 0から79までのtに対して、以下の計算を行う。 s = t AND MASK; 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); E = D; D = C; C = S^30(B); B = A; A = TEMP; d. HO, H1, H2, H3, H4 をそれぞれ、H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E とする。 7. C言語コード 以下は、C言語でのSHA-1実装例である。第7.1節にはヘッダファイル、7.2節は C言語コード、そして7.3節はテストドライバである。 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. * */ #ifndef _SHA1_H_ #define _SHA1_H_ #include /* * 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 /* * 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 */ /* 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; /* * Function Prototypes */ int SHA1Reset( SHA1Context *); int SHA1Input( SHA1Context *, const uint8_t *, unsigned int); int SHA1Result( SHA1Context *, uint8_t Message_Digest[SHA1HashSize]); #endif 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 (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" /* * 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 *); /* * 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->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; 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; if (!context || !Message_Digest) { return shaNull; } 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; } for(i = 0; i < SHA1HashSize; ++i) { Message_Digest[i] = context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ); } 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->Computed) { context->Corrupted = shaStateError; return shaStateError; } 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; } } if (context->Message_Block_Index == 64) { SHA1ProcessMessageBlock(context); } message_array++; } 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: * 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]; } 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]; 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; } 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 = 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->Message_Block_Index = 0; } /* * 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. * */ 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); 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; } } /* * 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); } 7.3 テストドライバ 以下のコードは、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. * */ #include #include #include #include "sha1.h" /* * 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" }; 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]); 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) { 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]); } /* 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. セキュリティに関する考察 本ドキュメントは、インターネットコミュニティに対し、the United States of America Federal Information Processing Standard Secure Hash Function SHA-1 [FIPS 180-1] のオープンソースを提供することを目的としている。本ハッシュ 関数のセキュリティについて、著者らによる独自の主張を行うことを目的とは していない。 参考文献 [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. [MD4] "The MD4 Message Digest Algorithm," Advances in Cryptology - CRYPTO '90 Proceedings, Springer-Verlag, 1991, pp. 303-311. [RFC 1320] Rivest, R., "The MD4 Message-Digest Algorithm", RFC 1320, April 1992. [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April 1992. [RFC 1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness Requirements for Security", RFC 1750, December 1994. 著者のアドレス Donald E. Eastlake, 3rd Motorola 155 Beaver Street Milford, MA 01757 USA 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 Phone: +1 919 392 6948 EMail: paulej@packetizer.com 著作権表示 Copyright (C) The Internet Society (2001). All Rights Reserved. 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. あとがき RFCの運営基金は現在、Internet Societyによって提供されている。 日本語訳 西原 啓輔 2002年5月 訳者は、訳出した文書を利用することにより発生したいかなる損害に対しても 責任を負いません。 本文書には、技術的あるいは翻訳上の誤りがある可能性があります。技術的に 正しい知識を獲得しなければならない場合は、InterNIC/IETFから発行されて いる原文を参照してください。