/*******************************************************************************************
***** sha256 *****
*******************************************************************************************/
/* 带符号整数类型 */
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
/* 无符号整数类型 */
typedef unsigned char uint8_t; // 8-bit -> byte
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t; // 32-bit -> word
/********************************************************************
* Context Structure
*
* SHA256 运算所使用的数据结构
*********************************************************************/
typedef struct {
uint8_t data[64]; // 数据缓冲区: 消息的当前分块(512-bit)
uint32_t datalen; // 数据缓冲区当前长度
uint32_t state[8]; // 存储哈希运算的中间状态
unsigned long long bitlen; // 消息总长度: 单位 bit
} SHA256_CTX;
/********************************************************************
P-CODE:
Note: All variables are unsigned 32 bits and wrap modulo 232 when calculating
Initialize variables
(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
Initialize table of round constants
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
k[0..63] :=
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
Pre-processing:
append the bit '1' to the message
append k bits '0', where k is the minimum number >= 0 such that the resulting message
length (in bits) is congruent to 448(mod 512)
append length of message (before pre-processing), in bits, as 64-bit big-endian integer
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
break chunk into sixteen 32-bit big-endian words w[0..15]
Extend the sixteen 32-bit words into sixty-four 32-bit words:
for i from 16 to 63
s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor(w[i-15] rightshift 3)
s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor(w[i-2] rightshift 10)
w[i] := w[i-16] + s0 + w[i-7] + s1
Initialize hash value for this chunk:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7
Main loop:
for i from 0 to 63
s0 := (a rightrotate 2) xor (a rightrotate 13) xor(a rightrotate 22)
maj := (a and b) xor (a and c) xor(b and c)
t2 := s0 + maj
s1 := (e rightrotate 6) xor (e rightrotate 11) xor(e rightrotate 25)
ch := (e and f) xor ((not e) and g)
t1 := h + s1 + ch + k[i] + w[i]
h := g
g := f
f := e
e := d + t1
d := c
c := b
b := a
a := t1 + t2
Add this chunk's hash to result so far:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h
Produce the final hash value (big-endian):
digest = hash = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
********************************************************************/
/* 逻辑运算 */
/* SHA256 非线性操作 */
/* 常量 */
static const 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
};
/********************************************************************
* SHA-256 循环加密操作
*
* 参数说明:
* ctx: 数据结构 SHA256_CTX
* data: 待加密数据, 一明文分组长度 (512-bit, 64-byte, 16-word)
********************************************************************/
void sha256_transform(SHA256_CTX* ctx, const uint8_t data[]) {
uint32_t 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;
}
/********************************************************************
* SHA256 上下文初始化
*
* 参数说明:
* ctx: 数据结构 SHA256_CTX
********************************************************************/
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;
}
/********************************************************************
* 导入待计算数据, 更新上下文
*
* 参数说明:
* ctx: 数据结构 SHA256_CTX
* data: 待加密数据
* len: 待加密数据长度
********************************************************************/
void sha256_update(SHA256_CTX* ctx, const uint8_t data[], uint8_t len)
{
uint32_t i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
/* 数据缓冲区 ctx->data 满时, 进行散列映射 */
if (ctx->datalen == 64) {
// 64 byte = 512 bit, 以为当前数据块已满
// 对当前块进行 SHA256 散列映射
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
/********************************************************************
* 生成 SHA-256 加密后的哈希值
*
* 参数说明:
* ctx: 数据结构 SHA256_CTX
* hash: 出参, 算法生成的哈希值
********************************************************************/
void sha256_finish(SHA256_CTX* ctx, uint8_t hash[])
{
uint32_t i;
i = ctx->datalen;
// 填充数据缓冲区
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80; // 填充: 10000000 = 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);
}
// 将长度信息添加在消息块末64位
ctx->bitlen += ctx->datalen << 3;
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 << 3))) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - (i << 3))) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - (i << 3))) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - (i << 3))) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - (i << 3))) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - (i << 3))) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - (i << 3))) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - (i << 3))) & 0x000000ff;
}
}
/********************************************************************
* SHA-256 加密算法
*
* 参数说明:
* digest: 输出加密结果, 出参
* msg: 要加密的数据
* msg_len: 数据长度
********************************************************************/
void sha256(unsigned char digest[SHA256_DIGEST_SIZE],
uint8_t* msg, uint8_t msg_len) {
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, (unsigned char*)msg, msg_len);
sha256_finish(&ctx, digest);
}
static void print_memory(uint32_t start_addr, uint8_t* data, uint16_t len) {
uint32_t data32;
uint32_t line = (len & (LINE_BYTE - 1)) ? (len / LINE_BYTE + 1) : (len / LINE_BYTE);
for (uint16_t i = 0; i < line; i++) {
printf("0x%04X ", i * LINE_BYTE + start_addr);
for (uint16_t j = 0; j < LINE_BYTE; j += 4) {
data32 = *(uint32_t*)(data + i * LINE_BYTE + j);
for (uint8_t k = 0; k < 4; k++) {
if (i * LINE_BYTE + j + k >= len) {
printf("\n");
goto ret;
}
printf(" %02X", (uint8_t)(data32 >> (k * 8)));
}
}
printf("\n");
}
ret:
printf("\n");
}
uint8_t random_code[16] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00
};
const uint8_t cable_c_secret[16] = {
// 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
// 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00
};
int main () {
uint8_t digest_match = 1;
uint32_t d0[] = {0x03020100,0x07060504,0x0b0a0908,0x0f0e0d0c};
uint32_t r0[] = {0x238E95F7,0x109ED35F,0x77F8E874,0xC115A531};
uint8_t db1[] = {0x80,0xFA,0xC1,0xE3,0x70,0xF6,0x0D,0x0B,
0x90,0xD3,0x50,0xCB,0x30,0x9B,0x91,0x38};
uint32_t d1[] = {0x80fac1e3,0x70f60d0b,0x90d350cb,0x309b9138};
uint32_t r1[] = {0x1d8fe744,0x245a2152,0xa3d71181,0x1ec0736e};
uint32_t d2[] = {0x8c6834c5,0x2499a8b9,0x108461dd,0x34deac9d};
uint32_t r2[] = {0x500143ad,0x057631a4,0xa66b2d28,0xef23f2f3};
uint32_t d3[] = {0x8C17697D,0x0137A8FF,0x63416BCD,0x758DAA6E};
uint32_t r3[] = {0x1DFA1854,0x0F4CE172,0x30A77218,0x23EF2A05};
uint32_t d4[] = {0x00000000,0x00000000,0x00000000,0x00000000};
uint32_t r4[] = {0x4f5e8869,0xef7dfeca,0x9c947847,0x6a5625d5};
uint32_t d5[] = {0x4447575e,0x22cd6554,0xe0b353aa,0x7ef92160};
uint32_t r5[] = {0x4b133d30,0x25fbb7a3,0xb7d10e25,0x578e476d};
uint8_t s[32] = {0};
uint8_t sha256_out[32] = {0};
srand(0);
for (uint8_t i = 0; i < 16; i++) {
printf("%02X ", (uint8_t)rand());
}
memcpy(s, cable_c_secret, sizeof(cable_c_secret));
// memcpy((uint8_t*)&d1, (uint8_t*)db1, sizeof(db1));
// for (uint8_t i = 0; i < sizeof(db1)/sizeof(uint32_t); i++) {
// printf("%08x\n", __builtin_bswap32(d1[i]));
// }
// for (uint8_t i = 0; i < sizeof(db1)/sizeof(uint32_t); i++) {
// *(uint32_t*)(db1+i*4) = __builtin_bswap32(*(uint32_t*)(db1+i*4));
// }
for (uint8_t i = 0; i < sizeof(d5)/sizeof(uint32_t); i++) {
// *(uint32_t*)(d5+i*4) = __builtin_bswap32(*(uint32_t*)(d5+i*4));
d5[i] = __builtin_bswap32(d5[i]);
}
memcpy(&s[16], (uint8_t*)d5, sizeof(d5));
print_memory(0, s, sizeof(s));
sha256(sha256_out, s, sizeof(s));
for (uint8_t i = 0; i < 4; i++) {
if (*(uint32_t*)(sha256_out + i * 4) != __builtin_bswap32(r5[i])) {
digest_match = 0;
}
}
print_memory(0, sha256_out, sizeof(sha256_out));
if (digest_match) {
printf("Match!!!");
} else {
printf("Not Match!!!");
}
return 0;
}