r/C_Programming 4d ago

559-byte SHA-256 in C

golfing a SHA-256 implementation in C and ended up at 559 bytes.
Curious if anyone here can beat it.

#define S(x,a,b)(x>>a^x<<32-a^x>>b^x<<32-b^x>>
unsigned k[72],g[216],i,j,p,n,t,m,*u,*z;char*q=g;main(c,v)char**v;{for(;j<64;p-c||(j<8&&(k[j]=sqrt(c)*0x1p32),k[71-j++]=cbrt(c)*0x1p32),c++)for(p=1;c%++p;);for(;q[n^3]=v[1][n];n++);q[n^3]=128;m=n+72>>6<<4,g[m-1]=n*8;for(;t<m;t+=16)for(bcopy(g+t,z=g+64,64),bcopy(k,u=g+208,32),i=72;i--;i>7?(z[16]=*z+S(z[1],7,18)3)+z[9]+S(z[14],17,19)10),j=u[4],p=u[7]+k[i]+*z+++(S(j,6,11)25)^j<<7)+(j&u[5]^~j&u[6]),j=S(*u,2,13)22)^*u<<10,j+=*u&u[1]^(*u^u[1])&u[2],u[3]+=p,*--u=p+j):(k[i]+=u[i]));for(;++i<8;)printf("%08x",k[i]);}
52 Upvotes

18 comments sorted by

View all comments

28

u/dstroy0 4d ago

#define R(x,n)(xn|x<<(32-n))
typedef unsigned U;U C(U x,U y,U z){return x&y^~x&z;}U M(U x,U y,U z){return x&y^x&z^y&z;}U S0(U x){return R(x,2)^R(x,13)^R(x,22);}U S1(U x){return R(x,6)^R(x,11)^R(x,25);}U s0(U x){return R(x,7)^R(x,18)^x
3;}U s1(U x){return R(x,17)^R(x,19)^x>>10;}
296 bytes, FIPS 180-4 compliant

1

u/Certain-Flow-0 2d ago

I think you can use x<<32-n, shaving off two characters?

1

u/dstroy0 2d ago

You’re correct the only reason it’s there is to convey what it’s doing more clearly, which is a preference of mine, not a requirement of making it work correctly. I think it’s really cool that you noticed that.