Skip to content

Instantly share code, notes, and snippets.

@odzhan
Last active July 8, 2025 21:35
Show Gist options
  • Save odzhan/8e97006807192c35ad9b138777f537f1 to your computer and use it in GitHub Desktop.
Save odzhan/8e97006807192c35ad9b138777f537f1 to your computer and use it in GitHub Desktop.
sha256
#ifndef SHA256_H
#define SHA256_H
#define R(v,n)(((v)>>(n))|((v)<<(32-(n))))
#define F(n)for(i=0;i<n;i++)
#ifdef _MSC_VER
#include <intrin.h>
#define rev32(x) _byteswap_ulong(x)
#define rev64(x) _byteswap_uint64(x)
#else // GCC/Clang
#define rev32(x) __builtin_bswap32(x)
#define rev64(x) __builtin_bswap64(x)
#endif
typedef struct _sha256_ctx {
union {
uint32_t b[32];
uint32_t w[8];
} s;
union {
uint8_t b[64];
uint32_t w[16];
uint64_t q[8];
}x;
uint32_t len;
} sha256_ctx;
#ifdef __cplusplus
extern "C" {
#endif
void sha256_init(sha256_ctx *c);
void sha256_update(sha256_ctx *c, const void *in, uint32_t len);
void sha256_final(void *out, sha256_ctx *c);
#ifdef __cplusplus
}
#endif
#endif
#include "sha256.h"
#define CH(x,y,z)(((x)&(y))^(~(x)&(z)))
#define MAJ(x,y,z)(((x)&(y))^((x)&(z))^((y)&(z)))
#define EP0(x)(R(x,2)^R(x,13)^R(x,22))
#define EP1(x)(R(x,6)^R(x,11)^R(x,25))
#define SIG0(x)(R(x,7)^R(x,18)^((x)>>3))
#define SIG1(x)(R(x,17)^R(x,19)^((x)>>10))
void sha256_compress(sha256_ctx *c) {
uint32_t t1,t2,i,w[64],x[8];
uint32_t k[64]=
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
// load input in big endian byte order
F(16)w[i] = rev32(c->x.w[i]);
// expand input
for(i=16;i<64;i++)
w[i] = SIG1(w[i-2])+w[i-7]+SIG0(w[i-15])+w[i-16];
// load state
F(8)x[i] = c->s.w[i];
// permute
F(64) {
t1 = x[7] + EP1(x[4]) + CH(x[4],x[5],x[6]) + w[i] + k[i];
t2 = EP0(x[0]) + MAJ(x[0],x[1],x[2]);
x[7] = x[6],x[6] = x[5],x[5] = x[4],x[4] = x[3] + t1;
x[3] = x[2],x[2] = x[1],x[1] = x[0], x[0] = t1 + t2;
}
// update state
F(8)c->s.w[i] += x[i];
}
void sha256_init(sha256_ctx *c) {
c->s.w[0]=0x6a09e667;
c->s.w[1]=0xbb67ae85;
c->s.w[2]=0x3c6ef372;
c->s.w[3]=0xa54ff53a;
c->s.w[4]=0x510e527f;
c->s.w[5]=0x9b05688c;
c->s.w[6]=0x1f83d9ab;
c->s.w[7]=0x5be0cd19;
c->len =0;
}
void sha256_update(sha256_ctx *c,const void *in,uint32_t len) {
uint8_t *p=(uint8_t*)in;
uint32_t i, idx;
// index = len % 64
idx = c->len & 63;
// update total length
c->len += len;
for (i=0;i<len;i++) {
// add byte to buffer
c->x.b[idx]=p[i]; idx++;
// buffer filled?
if(idx==64) {
// compress it
sha256_compress(c);
idx=0;
}
}
}
void sha256_final(void *out,sha256_ctx *c) {
uint32_t i,len,*p=(uint32_t*)out;
// get index
i = len = c->len & 63;
// zero remainder of buffer
while(i < 64) c->x.b[i++]=0;
// add 1 bit
c->x.b[len]=0x80;
// exceeds or equals area for total bits?
if(len >= 56) {
// compress it
sha256_compress(c);
// zero buffer
F(16)c->x.w[i]=0;
}
// add total length in bits
c->x.q[7]=rev64(c->len*8);
// compress it
sha256_compress(c);
// return hash
F(8)p[i] = rev32(c->s.w[i]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment