SHA1.c (4902B)
1 /* 2 * SHA-1 Implementation 3 * Note: SHA-1 is cryptographically broken, use for compatibility only 4 */ 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <stdint.h> 10 11 // SHA-1 context 12 typedef struct { 13 uint32_t state[5]; 14 uint64_t count; 15 uint8_t buffer[64]; 16 } sha1_context; 17 18 // Rotate left 19 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 20 21 // SHA-1 functions 22 #define F1(b, c, d) (((b) & (c)) | (~(b) & (d))) 23 #define F2(b, c, d) ((b) ^ (c) ^ (d)) 24 #define F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) 25 #define F4(b, c, d) ((b) ^ (c) ^ (d)) 26 27 // SHA-1 transform 28 static void sha1_transform(uint32_t state[5], const uint8_t block[64]) { 29 uint32_t W[80]; 30 uint32_t a, b, c, d, e, temp; 31 int i; 32 33 // Prepare message schedule 34 for (i = 0; i < 16; i++) { 35 W[i] = ((uint32_t)block[i * 4] << 24) | 36 ((uint32_t)block[i * 4 + 1] << 16) | 37 ((uint32_t)block[i * 4 + 2] << 8) | 38 ((uint32_t)block[i * 4 + 3]); 39 } 40 41 for (i = 16; i < 80; i++) { 42 W[i] = ROTL(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); 43 } 44 45 // Initialize working variables 46 a = state[0]; 47 b = state[1]; 48 c = state[2]; 49 d = state[3]; 50 e = state[4]; 51 52 // Main loop - Round 1 53 for (i = 0; i < 20; i++) { 54 temp = ROTL(a, 5) + F1(b, c, d) + e + W[i] + 0x5A827999; 55 e = d; d = c; c = ROTL(b, 30); b = a; a = temp; 56 } 57 58 // Round 2 59 for (i = 20; i < 40; i++) { 60 temp = ROTL(a, 5) + F2(b, c, d) + e + W[i] + 0x6ED9EBA1; 61 e = d; d = c; c = ROTL(b, 30); b = a; a = temp; 62 } 63 64 // Round 3 65 for (i = 40; i < 60; i++) { 66 temp = ROTL(a, 5) + F3(b, c, d) + e + W[i] + 0x8F1BBCDC; 67 e = d; d = c; c = ROTL(b, 30); b = a; a = temp; 68 } 69 70 // Round 4 71 for (i = 60; i < 80; i++) { 72 temp = ROTL(a, 5) + F4(b, c, d) + e + W[i] + 0xCA62C1D6; 73 e = d; d = c; c = ROTL(b, 30); b = a; a = temp; 74 } 75 76 // Update state 77 state[0] += a; 78 state[1] += b; 79 state[2] += c; 80 state[3] += d; 81 state[4] += e; 82 } 83 84 // Initialize SHA-1 context 85 void sha1_init(sha1_context *ctx) { 86 ctx->state[0] = 0x67452301; 87 ctx->state[1] = 0xEFCDAB89; 88 ctx->state[2] = 0x98BADCFE; 89 ctx->state[3] = 0x10325476; 90 ctx->state[4] = 0xC3D2E1F0; 91 ctx->count = 0; 92 } 93 94 // Update SHA-1 with data 95 void sha1_update(sha1_context *ctx, const uint8_t *data, size_t len) { 96 size_t i, index, part_len; 97 98 index = (size_t)(ctx->count & 0x3F); 99 ctx->count += len; 100 part_len = 64 - index; 101 102 if (len >= part_len) { 103 memcpy(&ctx->buffer[index], data, part_len); 104 sha1_transform(ctx->state, ctx->buffer); 105 106 for (i = part_len; i + 63 < len; i += 64) { 107 sha1_transform(ctx->state, &data[i]); 108 } 109 index = 0; 110 } else { 111 i = 0; 112 } 113 114 memcpy(&ctx->buffer[index], &data[i], len - i); 115 } 116 117 // Finalize SHA-1 and produce digest 118 void sha1_final(sha1_context *ctx, uint8_t digest[20]) { 119 uint8_t bits[8]; 120 size_t index, pad_len; 121 uint64_t bit_count = ctx->count * 8; 122 123 // Encode bit count 124 for (int i = 0; i < 8; i++) { 125 bits[7 - i] = (uint8_t)(bit_count >> (i * 8)); 126 } 127 128 // Pad 129 index = (size_t)(ctx->count & 0x3F); 130 pad_len = (index < 56) ? (56 - index) : (120 - index); 131 132 uint8_t padding[64]; 133 padding[0] = 0x80; 134 memset(padding + 1, 0, pad_len - 1); 135 136 sha1_update(ctx, padding, pad_len); 137 sha1_update(ctx, bits, 8); 138 139 // Store digest 140 for (int i = 0; i < 5; i++) { 141 digest[i * 4] = (uint8_t)(ctx->state[i] >> 24); 142 digest[i * 4 + 1] = (uint8_t)(ctx->state[i] >> 16); 143 digest[i * 4 + 2] = (uint8_t)(ctx->state[i] >> 8); 144 digest[i * 4 + 3] = (uint8_t)(ctx->state[i]); 145 } 146 } 147 148 // One-shot SHA-1 149 void sha1(const uint8_t *data, size_t len, uint8_t digest[20]) { 150 sha1_context ctx; 151 sha1_init(&ctx); 152 sha1_update(&ctx, data, len); 153 sha1_final(&ctx, digest); 154 } 155 156 // Test program 157 #ifndef LIB_MODE 158 int main(void) { 159 printf("SHA-1 Implementation\n"); 160 printf("====================\n"); 161 printf("WARNING: SHA-1 is cryptographically broken. Use for compatibility only!\n\n"); 162 163 // Test vectors 164 const char *test1 = "abc"; 165 const char *test2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; 166 167 uint8_t digest[20]; 168 169 // Test 1 170 printf("Test 1: \"%s\"\n", test1); 171 sha1((uint8_t*)test1, strlen(test1), digest); 172 printf("SHA-1: "); 173 for (int i = 0; i < 20; i++) printf("%02x", digest[i]); 174 printf("\n"); 175 printf("Expected: a9993e364706816aba3e25717850c26c9cd0d89d\n\n"); 176 177 // Test 2 178 printf("Test 2: \"%s\"\n", test2); 179 sha1((uint8_t*)test2, strlen(test2), digest); 180 printf("SHA-1: "); 181 for (int i = 0; i < 20; i++) printf("%02x", digest[i]); 182 printf("\n"); 183 printf("Expected: 84983e441c3bd26ebaae4aa1f95129e5e54670f1\n\n"); 184 185 return 0; 186 } 187 #endif