luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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