📄 sha1.c
字号:
/* * sha1.c * * an implementation of the Secure Hash Algorithm v.1 (SHA-1), * specified in FIPS 180-1 * * David A. McGrew * Cisco Systems, Inc. *//* * * Copyright (c) 2001, 2002, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the Cisco Systems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */#include "sha1.h"#define PRINT_DEBUG 0 /* set to 1 to print debugging info */#if PRINT_DEBUG#include <stdio.h> #endif#define S1(X) ((X << 1) | (X >> 31))#define S5(X) ((X << 5) | (X >> 27))#define S30(X) ((X << 30) | (X >> 2))#define f0(B,C,D) ((B & C) | (~B & D)) #define f1(B,C,D) (B ^ C ^ D)#define f2(B,C,D) ((B & C) | (B & D) | (C & D))#define f3(B,C,D) (B ^ C ^ D)/* * nota bene: the variable K0 appears in the curses library, so we * give longer names to these variables to avoid spurious warnings */uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */voidsha1(const uint32_t *M, int octets_in_msg, uint32_t hash_value[5]) { uint32_t H0 = 0x67452301; uint32_t H1 = 0xefcdab89; uint32_t H2 = 0x98badcfe; uint32_t H3 = 0x10325476; uint32_t H4 = 0xc3d2e1f0; uint32_t W[80]; uint32_t A, B, C, D, E, TEMP; int t; int i, j; int num_bits_in_msg = octets_in_msg * 8; /* break message into 16-word (64-byte) blocks, process each block */ j = 0; while (octets_in_msg > 64) { octets_in_msg -= 64; /* copy/xor message into array */ /* the first sixteen copies could be avoided, but I'm in a hurry */ W[0] = M[j+0]; W[1] = M[j+1]; W[2] = M[j+2]; W[3] = M[j+3]; W[4] = M[j+4]; W[5] = M[j+5]; W[6] = M[j+6]; W[7] = M[j+7]; W[8] = M[j+8]; W[9] = M[j+9]; W[10] = M[j+10]; W[11] = M[j+11]; W[12] = M[j+12]; W[13] = M[j+13]; W[14] = M[j+14]; W[15] = M[j+15]; TEMP = M[j+13] ^ M[j+8] ^ M[j+2] ^ M[j+0]; W[16] = S1(TEMP); TEMP = M[j+14] ^ M[j+9] ^ M[j+3] ^ M[j+1]; W[17] = S1(TEMP); TEMP = M[j+15] ^ M[j+10] ^ M[j+4] ^ M[j+2]; W[18] = S1(TEMP); TEMP = W[16] ^ M[j+11] ^ M[j+5] ^ M[j+3]; W[19] = S1(TEMP); TEMP = W[17] ^ M[j+12] ^ M[j+6] ^ M[j+4]; W[20] = S1(TEMP); TEMP = W[18] ^ M[j+13] ^ M[j+7] ^ M[j+5]; W[21] = S1(TEMP); TEMP = W[19] ^ M[j+14] ^ M[j+8] ^ M[j+6]; W[22] = S1(TEMP); TEMP = W[20] ^ M[j+15] ^ M[j+9] ^ M[j+7]; W[23] = S1(TEMP); TEMP = W[21] ^ W[16] ^ M[j+10] ^ M[j+8]; W[24] = S1(TEMP); TEMP = W[22] ^ W[17] ^ M[j+11] ^ M[j+9]; W[25] = S1(TEMP); TEMP = W[23] ^ W[18] ^ M[j+12] ^ M[j+10]; W[26] = S1(TEMP); TEMP = W[24] ^ W[19] ^ M[j+13] ^ M[j+11]; W[27] = S1(TEMP); TEMP = W[25] ^ W[20] ^ M[j+14] ^ M[j+12]; W[28] = S1(TEMP); TEMP = W[26] ^ W[21] ^ M[j+15] ^ M[j+13]; W[29] = S1(TEMP); TEMP = W[27] ^ W[22] ^ W[16] ^ M[j+14]; W[30] = S1(TEMP); TEMP = W[28] ^ W[23] ^ W[17] ^ M[j+15]; W[31] = S1(TEMP); /* process the remainder of the array */ for (t=32; t < 80; t++) { TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; W[t] = S1(TEMP); } A = H0; B = H1; C = H2; D = H3; E = H4; for (t=0; t < 20; t++) { TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 40; t++) { TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 60; t++) { TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 80; t++) { TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3; E = D; D = C; C = S30(B); B = A; A = TEMP; } H0 += A; H1 += B; H2 += C; H3 += D; H4 += E; j += 16; /* advance message pointer */ } /* * process the remaining octets_in_msg, padding and terminating as * necessary */ { int tail = octets_in_msg % 4; /* copy/xor message into array */ for (i=0; i < (octets_in_msg+3)/4; i++) W[i] = M[j+i];#if PRINT_DEBUG printf("tail: %d\n", tail); printf("M[j+i-1]: %x\n", M[j+i-1]);#endif /* set the high bit of the octet immediately following the message */ switch (tail) { case (3): W[i-1] = (M[j+i-1] & 0xffffff00) | 0x80; W[i] = 0x0; break; case (2): W[i-1] = (M[j+i-1] & 0xffff0000) | 0x8000; W[i] = 0x0; break; case (1): W[i-1] = (M[j+i-1] & 0xff000000) | 0x800000; W[i] = 0x0; break; case (0): W[i] = 0x80000000; break; } /* zeroize remaining words */ for (i++ ; i < 15; i++) W[i] = 0x0; /* * if there is room at the end of the word array, then set the * last word to the bit-length of the message; otherwise, set that * word to zero and then we need to do one more run of the * compression algo. */ if (octets_in_msg < 56) W[15] = num_bits_in_msg; else W[15] = 0x0;#if PRINT_DEBUG for (i=0; i < 16; i++) printf("@@@ W[%d]: %x\n", i, W[i]);#endif /* process the word array */ for (t=16; t < 80; t++) { TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; W[t] = S1(TEMP); } A = H0; B = H1; C = H2; D = H3; E = H4; for (t=0; t < 20; t++) { TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0; E = D; D = C; C = S30(B); B = A; A = TEMP;#if PRINT_DEBUG printf("%d: { %x%x%x%x%x } \n", t, A, B, C, D, E); #endif } for ( ; t < 40; t++) { TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 60; t++) { TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 80; t++) { TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3; E = D; D = C; C = S30(B); B = A; A = TEMP; } H0 += A; H1 += B; H2 += C; H3 += D; H4 += E; } if (octets_in_msg >= 56) { /* we need to do one final run of the compression algo */ /* * set initial part of word array to zeros, and set the * final part to the number of bits in the message */ for (i=0; i < 15; i++) W[i] = 0x0; W[15] = num_bits_in_msg;#if PRINT_DEBUG printf("pass two "); for (i=0; i < 16; i++) printf("@@@ W[%d]: %x\n", i, W[i]);#endif /* process the word array */ for (t=16; t < 80; t++) { TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; W[t] = S1(TEMP); } A = H0; B = H1; C = H2; D = H3; E = H4; for (t=0; t < 20; t++) { TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0; E = D; D = C; C = S30(B); B = A; A = TEMP;#if PRINT_DEBUG printf("%d: { %x%x%x%x%x } \n", t, A, B, C, D, E); #endif } for ( ; t < 40; t++) { TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 60; t++) { TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2; E = D; D = C; C = S30(B); B = A; A = TEMP; } for ( ; t < 80; t++) { TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3; E = D; D = C; C = S30(B); B = A; A = TEMP; } H0 += A; H1 += B; H2 += C; H3 += D; H4 += E; } hash_value[0] = H0; hash_value[1] = H1; hash_value[2] = H2; hash_value[3] = H3; hash_value[4] = H4; return;}/* * sha1_compress(M,l,H) computes the compression function, where * M is the next part of the message, l is the length of * M in octets, and H is the intermediate state {H0, H1, ...} */voidsha1_compress(const uint32_t *M, int octets_in_msg, uint32_t hash_value[5]) { uint32_t H0; uint32_t H1; uint32_t H2; uint32_t H3; uint32_t H4; uint32_t W[80]; uint32_t A, B, C, D, E, TEMP; int t; int i, j; int num_bits_in_msg = octets_in_msg * 8; /* copy hash_value into H0, H1, H2, H3, H4 */ H0 = hash_value[0]; H1 = hash_value[1]; H2 = hash_value[2]; H3 = hash_value[3]; H4 = hash_value[4]; /* break message into 16-word (64-byte) blocks, process each block */ j = 0; while (octets_in_msg > 64) { octets_in_msg -= 64; /* copy/xor message into array */ /* the first sixteen copies could be avoided, but I'm in a hurry */ W[0] = M[j+0]; W[1] = M[j+1]; W[2] = M[j+2]; W[3] = M[j+3]; W[4] = M[j+4]; W[5] = M[j+5]; W[6] = M[j+6]; W[7] = M[j+7]; W[8] = M[j+8]; W[9] = M[j+9]; W[10] = M[j+10]; W[11] = M[j+11]; W[12] = M[j+12]; W[13] = M[j+13]; W[14] = M[j+14]; W[15] = M[j+15]; TEMP = M[j+13] ^ M[j+8] ^ M[j+2] ^ M[j+0]; W[16] = S1(TEMP); TEMP = M[j+14] ^ M[j+9] ^ M[j+3] ^ M[j+1]; W[17] = S1(TEMP); TEMP = M[j+15] ^ M[j+10] ^ M[j+4] ^ M[j+2]; W[18] = S1(TEMP); TEMP = W[16] ^ M[j+11] ^ M[j+5] ^ M[j+3]; W[19] = S1(TEMP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -