Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SHA2-256 in C und in C++

2 views
Skip to first unread message

Bonita Montero

unread,
Jul 4, 2022, 4:59:51 AM7/4/22
to
Ich hab mal kurz SHA2-256 aus einer C-Implementation in eine C++
-Implementation verwandelt:

Hier der C-Code ohne Kommentare:

#include <stdlib.h>
#include <memory.h>
#include "sha256.h"

#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))

#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))

static const WORD 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
};

void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) |
(data[j + 3]);
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];

for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}

ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}

void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}

void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;

for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}

void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;

i = ctx->datalen;

if (ctx->datalen < 56) {
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else {
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}

ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);

for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}


In C++20:

#include <cstdlib>
#include <memory.h>
#include "sha256.h"
#include "unroll.h"

#if defined(_MSC_VER)
#pragma warning(disable: 4554)
#endif

using namespace std;

static void sha256_transform( SHA256_CTX &ctx, uint8_t const *data )
{
static uint32_t const 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
};
static auto rotright = []( uint32_t a, unsigned char b ) -> uint32_t {
return a >> b | a << 32 - b; };
auto ch = []( uint32_t x, uint32_t y, uint32_t z ) -> uint32_t { return
x & y ^ ~x & z; };
auto maj = []( uint32_t x, uint32_t y, uint32_t z ) -> uint32_t {
return x & y ^ x & z ^ y & z; };
auto ep0 = []( uint32_t x ) -> uint32_t { return rotright( x, 2 ) ^
rotright( x, 13 ) ^ rotright( x, 22 ); };
auto ep1 = []( uint32_t x ) -> uint32_t { return rotright( x, 6 ) ^
rotright( x, 11 ) ^ rotright( x, 25 ); };
auto sig0 = []( uint32_t x ) { return rotright( x, 7 ) ^ rotright( x,
18 ) ^ x >> 3; };
auto sig1 = []( uint32_t x ) -> uint32_t { return rotright( x, 17 ) ^
rotright( x, 19 ) ^ x >> 10; };
uint32_t v[8], t[2], m[64];
size_t i, j;
for( i = 0, j = 0; i != 16; ++i, j += 4 )
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) |
(data[j + 3]);
for( ; i != 64; ++i )
m[i] = sig1( m[i - 2] ) + m[i - 7] + sig0( m[i - 15] ) + m[i - 16];
unroll<8>( [&]<size_t I>() { v[I] = ctx.state[I]; } );
for( i = 0; i != 64; ++i )
t[0] = v[7] + ep1(v[4]) + ch(v[4], v[5], v[6]) + k[i] + m[i],
t[1] = ep0(v[0]) + maj(v[0], v[1], v[2]),
v[7] = v[6],
v[6] = v[5],
v[5] = v[4],
v[4] = v[3] + t[0],
v[3] = v[2],
v[2] = v[1],
v[1] = v[0],
v[0] = t[0] + t[1];
unroll<8>( [&]<size_t I>() { ctx.state[I] += v[I]; } );
}

void sha256_init( SHA256_CTX &ctx )
{
ctx.datalen = 0;
ctx.bitlen = 0;
static uint32_t const init[] = { 0x6A09E667, 0xBB67AE85, 0x3C6EF372,
0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 };
unroll<8>( [&]<size_t I>() { ctx.state[I] = init[I]; } );
}

void sha256_update( SHA256_CTX &ctx, uint8_t const *data, size_t len )
{
for( size_t i = 0; i != len; ++i )
{
ctx.data[ctx.datalen] = data[i];
ctx.datalen++;
if( ctx.datalen == 64 )
sha256_transform( ctx, ctx.data ),
ctx.bitlen += 512,
ctx.datalen = 0;
}
}

void sha256_final( SHA256_CTX &ctx, uint8_t (&hash)[SHA256_BLOCK_SIZE] )
{
size_t i = ctx.datalen;
if( ctx.datalen < 56 )
{
ctx.data[i++] = 0x80;
while( i != 56 )
ctx.data[i++] = 0x00;
}
else
{
ctx.data[i++] = 0x80;
while( i != 64 )
ctx.data[i++] = 0x00;
sha256_transform( ctx, ctx.data );
memset( ctx.data, 0, 56 );
}
ctx.bitlen += ctx.datalen * 8;
unroll<8>( [&]<size_t I>() { ctx.data[63 - I] = (uint8_t)(ctx.bitlen >>
I * 8); } );
sha256_transform( ctx, ctx.data );
for( i = 0; i != 4; ++i )
unroll<8>( [&]<size_t I>() { hash[i + I * 4] = (uint8_t)(ctx.state[I]
>> 24 - i * 8); } );
}


Deutlich kürzer und deutlich lesbarer.
0 new messages