Skip to content

Instantly share code, notes, and snippets.

@kulp
Created August 17, 2015 17:33
Show Gist options
  • Save kulp/c7feb6109e770cebb74a to your computer and use it in GitHub Desktop.
Save kulp/c7feb6109e770cebb74a to your computer and use it in GitHub Desktop.
SHA-1 command-line implementation in C
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
static inline uint32_t rol(uint32_t x, unsigned char y)
{
return (x << y) | ((x >> (32 - y)) & ~(-1 << y));
}
static void chunk(uint32_t h[5], unsigned char *ptr)
{
uint32_t w[80];
for (int i = 0; i < 16; i++)
w[i] = (ptr[i * 4 + 0] << 24)
| (ptr[i * 4 + 1] << 16)
| (ptr[i * 4 + 2] << 8)
| (ptr[i * 4 + 3] << 0);
for (int i = 16; i < 80; i++)
w[i] = rol(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
uint32_t a = h[0],
b = h[1],
c = h[2],
d = h[3],
e = h[4];
static const uint32_t k[] =
{ 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
for (int i = 0; i < 80; i++) {
uint32_t f = (i < 20) ? (b & c) | (~b & d) :
(i < 40) ? b ^ c ^ d :
(i < 60) ? (b & c) | (b & d) | (c & d) :
b ^ c ^ d;
uint32_t temp = rol(a, 5) + f + e + k[i / 20] + w[i];
e = d;
d = c;
c = rol(b, 30);
b = a;
a = temp;
}
h[0] += a;
h[1] += b;
h[2] += c;
h[3] += d;
h[4] += e;
}
void process_stream(FILE *in, const char *fname)
{
uint32_t h[] =
{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
const int chunkbytes = 512 / CHAR_BIT;
unsigned char buf[chunkbytes * 2];
size_t end = 0, pos = 0;
while (!feof(in) && !ferror(in)) {
end += fread(buf, 1, chunkbytes, in);
if (end - pos >= chunkbytes) {
chunk(h, buf);
pos += chunkbytes;
}
}
if (ferror(in)) {
perror("sha1");
return;
}
// handle last chunk which is necessarily < 512 bits long
uint64_t ml = end * CHAR_BIT;
buf[end++ - pos] = 1 << (CHAR_BIT - 1);
while ((end - pos) % 64 != 56)
buf[end++ - pos] = 0x00;
size_t idx = end - pos;
for (int i = 0; i < 64 / CHAR_BIT; i++)
buf[idx + i] = (ml >> ((7 - i) * CHAR_BIT)) & 0xff;
for (size_t off = 0; off < idx; off += 64)
chunk(h, &buf[off]);
printf("%08x%08x%08x%08x%08x %s\n", h[0], h[1], h[2], h[3], h[4], fname);
}
int main(int argc, char *argv[])
{
if (argc <= 1) {
process_stream(stdin, "-");
} else for (int i = 1; i < argc; i++) {
FILE *in = fopen(argv[i], "rb");
process_stream(in, argv[i]);
fclose(in);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment