草稿存于2021-03-16。下面,为了显示出很专业的样子,贴出百科解释:
说明
SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发[3],由美国国家标准与技术研究院(NIST)在2001年发布。属于SHA算法之一,是SHA-1的后继者。其下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
由于加密芯片 atsha204 主要使用了 SHA-256 算法,故本文描述的就是 SHA-256 算法。
计算 SHA-256 时,当数据长度 len + 8
大于等于64字节时,分组进行:
分组数 n = ( len + 8 ) / 64 + 1;
每组数据为64字节,最后一组不满 55
字节则补全,剩余 9 字节为固定值与数据长度,一般地方使用 0 填充,在所需计算数据的位置后直接填充 0x80,64字节中的最后四字节为 len * 8
例如,计算一组数据的 SHA-256
要计算的数组
{0x43,0x43}
则构成的64字节则为(hex):
43 43 80 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
计算的 SHA-256 结果为:
a5 63 62 a1 0c 81 6a bf 20 6d 72 cb 91 4e 2d 5c
a4 54 eb 9c 7e 74 4f 88 b1 a1 42 2c 37 9e 99 42
程序
- 以下例程为计算 {0x43,0x43} 的 SHA-256 值:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
unsigned int sha256_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
};
#define SHFR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define CH(x, y, z) ((x & y) ^ (~x & z))
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
static void sha256_update(uint8_t *Input,unsigned int *Output)
{
unsigned int w[64];
unsigned int wv[8];
unsigned int t1, t2;
uint8_t j;
for (j = 0; j < 16; j++) {
w[j]= ((unsigned int)Input[4*j+3])+
(((unsigned int)Input[4*j+2])<<8)+
(((unsigned int)Input[4*j+1])<<16)+
(((unsigned int)Input[4*j]) << 24);
}
for (j = 16; j < 64; j++) {
w[j]= SHA256_F4(w[j-2]) + w[j-7]+ SHA256_F3(w[j - 15]) + w[j-16];
}
for (j = 0; j < 8; j++) {
wv[j] = Output[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
Output[j] += wv[j];
}
}
static void sha256(uint8_t *Input, uint32_t len, uint8_t *Output)
{
unsigned int sha256_h[8];
uint8_t sha256_block[256]; //其大小最多可测试 247 字节
uint16_t i=0;
uint32_t n = ( len + 8 ) / 64 + 1; //分组数
sha256_h[0] = 0x6a09e667;
sha256_h[1] = 0xbb67ae85;
sha256_h[2] = 0x3c6ef372;
sha256_h[3] = 0xa54ff53a;
sha256_h[4] = 0x510e527f;
sha256_h[5] = 0x9b05688c;
sha256_h[6] = 0x1f83d9ab;
sha256_h[7] = 0x5be0cd19;
memmove(sha256_block, Input, len);
memset(sha256_block+len, 0x0, n*64-len);
sha256_block[len] = 0x80;
for(i=1; i<=4; i++){
sha256_block[(n*64)-i] = (uint8_t)(8*len>>(i-1)*8);
}
for(i=0; i<n; i++){
sha256_update(&sha256_block[64*i], sha256_h);
}
for (i = 0 ; i < 8; i++){
Output[4*i] =((uint8_t)(sha256_h[i] >> 24));
Output[4*i+1]=((uint8_t)(sha256_h[i] >> 16));
Output[4*i+2]=((uint8_t)(sha256_h[i] >> 8));
Output[4*i+3]=((uint8_t)(sha256_h[i]));
}
}
uint8_t testhex[] = {0x43,0x43};
uint8_t outhex[32];
int main(int argc, char **argv)
{
sha256(testhex, sizeof(testhex), outhex);
for(int i=0; i < 32; ++i){
printf("%02x ", outhex[i]);
}
printf("\n");
return 0;
}
- 若是在linux系统中安装了 openssl ,则会比较简单,直接调用 API
#include <openssl/sha.h>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
string sha256(const uint8_t * data, int len)
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, data, len);
SHA256_Final(hash, &sha256);
stringstream ss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++){
ss << hex << setw(2) << setfill('0') << (int)hash[i];
}
return ss.str();
}
uint8_t testhex[]={ 0x43,0x43 };
int main(){
cout << sha256(testhex, sizeof(testhex)) << endl;
return 0;
}
编译时需要加上 -lssl -lcrypto
,否则会报错
g++ -o sha256_test sha256_test.cpp -lssl -lcrypto
相关参考:
https://github.com/nsood/sha204/blob/master/sha256.c
https://github.com/panshq/atsha204a/blob/master/sha204-core.c
https://blog.youkuaiyun.com/lwanttowin/article/details/53726450
https://stackoverflow.com/questions/2262386/generate-sha256-with-openssl-and-c/10632725