3.2 签名算法
原文来自:https://www.cnblogs.com/Kingfans/p/16546386.html
简介
SHA (Security Hash Algorithm) 是美国的 NIST 和 NSA 设计的一种标准的 Hash 算法,SHA 用于数字签名的标准算法的 DSS 中,也是安全性很高的一种 Hash 算法。
SHA系列家族
原文来自:https://www.cnblogs.com/Kingfans/p/16546386.html
SHA (Security Hash Algorithm) 是美国的 NIST 和 NSA 设计的一种标准的 Hash 算法,SHA 用于数字签名的标准算法的 DSS 中,也是安全性很高的一种 Hash 算法。
原文来自:https://www.cnblogs.com/Kingfans/p/16561821.html
SHA (Security Hash Algorithm) 是美国的 NIST 和 NSA 设计的一种标准的 Hash 算法,SHA 用于数字签名的标准算法的 DSS 中,也是安全性很高的一种 Hash 算法。
SHA-1 是第一代 SHA 算法标准,后来的 SHA-224、SHA-256、SHA-384 和 SHA-512 被统称为 SHA-2。
有关 SHA1 算法详情请参见 RFC 3174 http://www.ietf.org/rfc/rfc3174.txt。
RFC 3174 是SHA1算法的官方文档,(建议了解SHA1算法前,先了解下MD4 md4算法实现原理深剖 )其实现原理共分为5步:
数据先补上1个1比特,再补上k个0比特,使得补位后的数据比特数(n+1+k)满足(n+1+k) mod 512 = 448,k取最小正整数。
数据比特位的数据长度追加到最后8字节中。【注意字节顺序与MD4不同 大小端之分】
这一步最简单了,定义ABCD四个4字节数组,分别赋初值即可。【注意相对于MD4 添加了H4】
uint32_t H0 = 0x67452301; // 0x01, 0x23, 0x45, 0x67
uint32_t H1 = 0xEFCDAB89; // 0x89, 0xAB, 0xCD, 0xEF
uint32_t H2 = 0x98BADCFE; // 0xFE, 0xDC, 0xBA, 0x98
uint32_t H3 = 0x10325476; // 0x76, 0x54, 0x32, 0x10
uint32_t H4 = 0xC3D2E1F0; // 0xF0, 0xE1, 0xD2, 0xC3
这个是SHA1算法最核心的部分了,对第2步组装数据进行分块依次处理。
/* Process each 16-word block. */
For i = 0 to N/16-1 do
/* Copy block i into X. */
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end /* of loop on j */
a. Divide M(i) into 16 words W(0), W(1), ... , W(15), where W(0) is the left-most word.
b. For t = 16 to 79 let
W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)).
c. Let A = H0, B = H1, C = H2, D = H3, E = H4.
d. For t = 0 to 79 do
TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t);
E = D; D = C; C = S^30(B); B = A; A = TEMP;
e. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.
end /* of loop on i */
这一步也非常简单,只需要将计算后的H0、H1、H2、H3、H4进行拼接输出即可。
四、代码实现 以下为C/C++代码实现:
#include <string.h>
#include <stdio.h>
#define HASH_BLOCK_SIZE 64 /* 512 bits = 64 bytes */
#define HASH_LEN_SIZE 8 /* 64 bits = 8 bytes */
#define HASH_LEN_OFFSET 56 /* 64 bytes - 8 bytes */
#define HASH_DIGEST_SIZE 16 /* 128 bits = 16 bytes */
#define HASH_ROUND_NUM 80
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
/* Swap bytes in 32 bit value. 0x01234567 -> 0x67452301 */
#define __bswap_32(x) \
((((x) & 0xff000000) >> 24) \
| (((x) & 0x00ff0000) >> 8) \
| (((x) & 0x0000ff00) << 8) \
| (((x) & 0x000000ff) << 24))
/* SHA1 Constants */
static uint32_t K[4] =
{
0x5A827999, /* [0, 19] */
0x6ED9EBA1, /* [20, 39] */
0x8F1BBCDC, /* [40, 59] */
0xCA62C1D6 /* [60, 79] */
};
/* f(X, Y, Z) */
/* [0, 19] */
static uint32_t Ch(uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) ^ ((~X) & Z);
}
/* [20, 39] */ /* [60, 79] */
static uint32_t Parity(uint32_t X, uint32_t Y, uint32_t Z)
{
return X ^ Y ^ Z;
}
/* [40, 59] */
static uint32_t Maj(uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) ^ (X & Z) ^ (Y & Z);
}
/* 循环向左移动offset个比特位 */
static uint32_t MoveLeft(uint32_t X, uint8_t offset)
{
uint32_t res = (X << offset) | (X >> (32 - offset));
return res;
}
#define ASSERT_RETURN_INT(x, d) if(!(x)) { return d; }
int sha1(unsigned char *out, const unsigned char* in, const int inlen)
{
ASSERT_RETURN_INT(out && in && (inlen >= 0), 1);
int i = 0, j = 0, t = 0;
// step 1: 字节填充(Append Padding Bytes)
// 数据先补上1个1比特,再补上k个0比特,使得补位后的数据比特数(n+1+k)满足(n+1+k) mod 512 = 448,k取最小正整数
int iX = inlen / HASH_BLOCK_SIZE;
int iY = inlen % HASH_BLOCK_SIZE;
iX = (iY < HASH_LEN_OFFSET) ? iX : (iX + 1);
int iLen = (iX + 1) * HASH_BLOCK_SIZE;
unsigned char* X = malloc(iLen);
memcpy(X, in, inlen);
// 先补上1个1比特+7个0比特
X[inlen] = 0x80;
// 再补上(k-7)个0比特
for (i = inlen + 1; i < (iX * HASH_BLOCK_SIZE + HASH_LEN_OFFSET); i++)
{
X[i] = 0;
}
// step 2: 追加长度信息(Append Length)
uint8_t *pLen = (uint64_t*)(X + (iX * HASH_BLOCK_SIZE + HASH_LEN_OFFSET));
uint64_t iTempLen = inlen << 3;
uint8_t *pTempLen = &iTempLen;
pLen[0] = pTempLen[7]; pLen[1] = pTempLen[6]; pLen[2] = pTempLen[5]; pLen[3] = pTempLen[4];
pLen[4] = pTempLen[3]; pLen[5] = pTempLen[2]; pLen[6] = pTempLen[1]; pLen[7] = pTempLen[0];
// Step 3. 初始化MD Buffer(Initialize MD Buffer)
uint32_t H0 = 0x67452301; // 0x01, 0x23, 0x45, 0x67
uint32_t H1 = 0xEFCDAB89; // 0x89, 0xAB, 0xCD, 0xEF
uint32_t H2 = 0x98BADCFE; // 0xFE, 0xDC, 0xBA, 0x98
uint32_t H3 = 0x10325476; // 0x76, 0x54, 0x32, 0x10
uint32_t H4 = 0xC3D2E1F0; // 0xF0, 0xE1, 0xD2, 0xC3
uint32_t M[HASH_BLOCK_SIZE / 4] = { 0 };
uint32_t W[HASH_ROUND_NUM] = { 0 };
// step 4: 处理消息块(Process Message in 64-Byte Blocks)
for (i = 0; i < iLen / HASH_BLOCK_SIZE; i++)
{
/* Copy block i into X. */
for (j = 0; j < HASH_BLOCK_SIZE; j = j + 4)
{
uint64_t k = i * HASH_BLOCK_SIZE + j;
M[j / 4] = (X[k] << 24) | (X[k + 1] << 16) | (X[k + 2] << 8) | X[k + 3];
}
/* a. Divide M(i) into 16 words W(0), W(1), ..., W(15), where W(0) is the left - most word. */
for (t = 0; t <= 15; t++)
{
W[t] = M[t];
}
/* b. For t = 16 to 79 let
W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)). */
for (t = 16; t <= 79; t++)
{
W[t] = MoveLeft(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
}
/* c. Let A = H0, B = H1, C = H2, D = H3, E = H4. */
uint32_t A = H0;
uint32_t B = H1;
uint32_t C = H2;
uint32_t D = H3;
uint32_t E = H4;
/* d. For t = 0 to 79 do
TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t);
E = D; D = C; C = S^30(B); B = A; A = TEMP; */
for (t = 0; t <= 19; t++)
{
uint32_t temp = MoveLeft(A, 5) + Ch(B, C, D) + E + W[t] + K[0];
E = D;
D = C;
C = MoveLeft(B, 30);
B = A;
A = temp;
}
for (t = 20; t <= 39; t++)
{
uint32_t temp = MoveLeft(A, 5) + Parity(B, C, D) + E + W[t] + K[1];
E = D;
D = C;
C = MoveLeft(B, 30);
B = A;
A = temp;
}
for (t = 40; t <= 59; t++)
{
uint32_t temp = MoveLeft(A, 5) + Maj(B, C, D) + E + W[t] + K[2];
E = D;
D = C;
C = MoveLeft(B, 30);
B = A;
A = temp;
}
for (t = 60; t <= 79; t++)
{
uint32_t temp = MoveLeft(A, 5) + Parity(B, C, D) + E + W[t] + K[3];
E = D;
D = C;
C = MoveLeft(B, 30);
B = A;
A = temp;
}
/* e. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E. */
H0 = H0 + A;
H1 = H1 + B;
H2 = H2 + C;
H3 = H3 + D;
H4 = H4 + E;
}
// step 5: 输出ABCD
uint32_t* pOut = (uint8_t*)out;
pOut[0] = __bswap_32(H0);
pOut[1] = __bswap_32(H1);
pOut[2] = __bswap_32(H2);
pOut[3] = __bswap_32(H3);
pOut[4] = __bswap_32(H4);
free(X);
return 0;
}
int main()
{
unsigned char digest[20] = { 0 };
sha1(digest, "Hello World!", strlen("Hello World!"));
return 0;
}
原文来自:https://www.cnblogs.com/Kingfans/p/16572411.html
SHA (Security Hash Algorithm) 是美国的 NIST 和 NSA 设计的一种标准的 Hash 算法,SHA 用于数字签名的标准算法的 DSS 中,也是安全性很高的一种 Hash 算法。
SHA-1 是第一代 SHA 算法标准,后来的 SHA-224、SHA-256、SHA-384 和 SHA-512 被统称为 SHA-2。本文介绍SHA2-224算法的实现原理。
有关 SHA2-224 算法详情请参见 NIST.FIPS.180-4 。
NIST.FIPS.180-4 是SHA2-224算法的官方文档,(建议了解SHA2-224算法前,先了解下SHA2-256 sha2-256算法实现原理深剖 )其实现原理共分为5步:
数据先补上1个1比特,再补上k个0比特,使得补位后的数据比特数(n+1+k)满足(n+1+k) mod 512 = 448,k取最小正整数。
数据比特位的数据长度追加到最后8字节中。
这一步最简单了,定义ABCD四个4字节数组,分别赋初值即可。
uint32_t H0 = 0xC1059ED8;
uint32_t H1 = 0x367CD507;
uint32_t H2 = 0x3070DD17;
uint32_t H3 = 0xF70E5939;
uint32_t H4 = 0xFFC00B31;
uint32_t H5 = 0x68581511;
uint32_t H6 = 0x64F98FA7;
uint32_t H7 = 0xBEFA4FA4;
这个是SHA2-224算法最核心的部分了,对第2步组装数据进行分块依次处理。
这一步也非常简单,只需要将计算后的H0、H1、H2、H3、H4、H5、H6进行拼接输出即可。
由于SHA2–224与SHA2-256算法完全一致,只是hash value初始赋值和输出结果不同。
具体示例讲解看参考SHA2-256示例讲解,此处不再重复。
以下为C/C++代码实现:
#include <string.h>
#include <stdio.h>
#define HASH_BLOCK_SIZE 64 /* 512 bits = 64 bytes */
#define HASH_LEN_SIZE 8 /* 64 bits = 8 bytes */
#define HASH_LEN_OFFSET 56 /* 64 bytes - 8 bytes */
#define HASH_DIGEST_SIZE 16 /* 128 bits = 16 bytes */
#define HASH_ROUND_NUM 64
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
/* SHA256 Constants */
static const uint32_t K[HASH_ROUND_NUM] = {
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
};
/* Swap bytes in 32 bit value. 0x01234567 -> 0x67452301 */
#define __bswap_32(x) \
((((x) & 0xff000000) >> 24) \
| (((x) & 0x00ff0000) >> 8) \
| (((x) & 0x0000ff00) << 8) \
| (((x) & 0x000000ff) << 24))
static uint32_t Ch(uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) ^ ((~X) & Z);
}
static uint32_t Maj(uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) ^ (X & Z) ^ (Y & Z);
}
/* 循环向右移动offset个比特位 */
static uint32_t ROTR(uint32_t X, uint8_t offset)
{
uint32_t res = (X >> offset) | (X << (32 - offset));
return res;
}
/* 向右移动offset个比特位 */
static uint32_t SHR(uint32_t X, uint8_t offset)
{
uint32_t res = X >> offset;
return res;
}
/* SIGMA0 */
static uint32_t SIGMA0(uint32_t X)
{
return ROTR(X, 2) ^ ROTR(X, 13) ^ ROTR(X, 22);
}
/* SIGMA1 */
static uint32_t SIGMA1(uint32_t X)
{
return ROTR(X, 6) ^ ROTR(X, 11) ^ ROTR(X, 25);
}
/* sigma0, different from SIGMA0 */
static uint32_t sigma0(uint32_t X)
{
uint32_t res = ROTR(X, 7) ^ ROTR(X, 18) ^ SHR(X, 3);
return ROTR(X, 7) ^ ROTR(X, 18) ^ SHR(X, 3);
}
/* sigma1, different from SIGMA1 */
static uint32_t sigma1(uint32_t X)
{
return ROTR(X, 17) ^ ROTR(X, 19) ^ SHR(X, 10);
}
#define ASSERT_RETURN_INT(x, d) if(!(x)) { return d; }
int sha2_224(unsigned char *out, const unsigned char* in, const int inlen)
{
ASSERT_RETURN_INT(out && in && (inlen >= 0), 1);
int i = 0, j = 0, t = 0;
// step 1: 字节填充(Append Padding Bytes)
// 数据先补上1个1比特,再补上k个0比特,使得补位后的数据比特数(n+1+k)满足(n+1+k) mod 512 = 448,k取最小正整数
int iX = inlen / HASH_BLOCK_SIZE;
int iY = inlen % HASH_BLOCK_SIZE;
iX = (iY < HASH_LEN_OFFSET) ? iX : (iX + 1);
int iLen = (iX + 1) * HASH_BLOCK_SIZE;
unsigned char* X = malloc(iLen);
memcpy(X, in, inlen);
// 先补上1个1比特+7个0比特
X[inlen] = 0x80;
// 再补上(k-7)个0比特
for (i = inlen + 1; i < (iX * HASH_BLOCK_SIZE + HASH_LEN_OFFSET); i++)
{
X[i] = 0;
}
// step 2: 追加长度信息(Append Length)
uint8_t *pLen = (uint64_t*)(X + (iX * HASH_BLOCK_SIZE + HASH_LEN_OFFSET));
uint64_t iTempLen = inlen << 3;
uint8_t *pTempLen = &iTempLen;
pLen[0] = pTempLen[7]; pLen[1] = pTempLen[6]; pLen[2] = pTempLen[5]; pLen[3] = pTempLen[4];
pLen[4] = pTempLen[3]; pLen[5] = pTempLen[2]; pLen[6] = pTempLen[1]; pLen[7] = pTempLen[0];
// Step 3. 初始化MD Buffer(Initialize MD Buffer)
uint32_t H0 = 0xC1059ED8;
uint32_t H1 = 0x367CD507;
uint32_t H2 = 0x3070DD17;
uint32_t H3 = 0xF70E5939;
uint32_t H4 = 0xFFC00B31;
uint32_t H5 = 0x68581511;
uint32_t H6 = 0x64F98FA7;
uint32_t H7 = 0xBEFA4FA4;
uint32_t M[HASH_BLOCK_SIZE / 4] = { 0 };
uint32_t W[HASH_ROUND_NUM] = { 0 };
// step 4: 处理消息块(Process Message in 64-Byte Blocks)
for (i = 0; i < iLen / HASH_BLOCK_SIZE; i++)
{
/* Copy block i into M. */
for (j = 0; j < HASH_BLOCK_SIZE; j = j + 4)
{
uint64_t k = i * HASH_BLOCK_SIZE + j;
M[j / 4] = (X[k] << 24) | (X[k + 1] << 16) | (X[k + 2] << 8) | X[k + 3];
}
/* W[t]=M[t]; t:[0,15] */
for (t = 0; t <= 15; t++)
{
W[t] = M[t];
}
/* W[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) + W[t - 16]; t:[16,63] */
for (t = 16; t < HASH_ROUND_NUM; t++)
{
W[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) + W[t - 16];
}
uint32_t A = H0;
uint32_t B = H1;
uint32_t C = H2;
uint32_t D = H3;
uint32_t E = H4;
uint32_t F = H5;
uint32_t G = H6;
uint32_t H = H7;
for (t = 0; t < HASH_ROUND_NUM; t++)
{
uint32_t T1 = H + SIGMA1(E) + Ch(E, F, G) + K[t] + W[t];
uint32_t T2 = SIGMA0(A) + Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + T1;
D = C;
C = B;
B = A;
A = T1 + T2;
}
H0 = H0 + A;
H1 = H1 + B;
H2 = H2 + C;
H3 = H3 + D;
H4 = H4 + E;
H5 = H5 + F;
H6 = H6 + G;
H7 = H7 + H;
}
// step 5: 输出
uint32_t* pOut = (uint8_t*)out;
pOut[0] = __bswap_32(H0);
pOut[1] = __bswap_32(H1);
pOut[2] = __bswap_32(H2);
pOut[3] = __bswap_32(H3);
pOut[4] = __bswap_32(H4);
pOut[5] = __bswap_32(H5);
pOut[6] = __bswap_32(H6);
free(X);
return 0;
}
int main()
{
unsigned char digest[28] = { 0 };
sha2_224(digest, "Hello World!", strlen("Hello World!"));
return 0;
}
原文来自:https://www.cnblogs.com/Kingfans/p/16571435.html
SHA (Security Hash Algorithm) 是美国的 NIST 和 NSA 设计的一种标准的 Hash 算法,SHA 用于数字签名的标准算法的 DSS 中,也是安全性很高的一种 Hash 算法。
SHA-1 是第一代 SHA 算法标准,后来的 SHA-224、SHA-256、SHA-384 和 SHA-512 被统称为 SHA-2。本文介绍SHA2-256算法的实现原理。
有关 SHA2-256 算法详情请参见 NIST.FIPS.180-4 。
NIST.FIPS.180-4 是SHA2-256算法的官方文档,(建议了解SHA2-256算法前,先了解下SHA1 sha1算法实现原理深剖 )其实现原理共分为5步:
数据先补上1个1比特,再补上k个0比特,使得补位后的数据比特数(n+1+k)满足(n+1+k) mod 512 = 448,k取最小正整数。
数据比特位的数据长度追加到最后8字节中。【以上与sha1完全一致】
这一步最简单了,定义ABCD四个4字节数组,分别赋初值即可。
uint32_t H0 = 0x6A09E667;
uint32_t H1 = 0xBB67AE85;
uint32_t H2 = 0x3C6EF372;
uint32_t H3 = 0xA54FF53A;
uint32_t H4 = 0x510E527F;
uint32_t H5 = 0x9B05688C;
uint32_t H6 = 0x1F83D9AB;
uint32_t H7 = 0x5BE0CD19;
这个是SHA2-256算法最核心的部分了,对第2步组装数据进行分块依次处理。
这一步也非常简单,只需要将计算后的H0、H1、H2、H3、H4、H5、H6、H7进行拼接输出即可。
以下为C/C++代码实现:
#include <string.h>
#include <stdio.h>
#define HASH_BLOCK_SIZE 64 /* 512 bits = 64 bytes */
#define HASH_LEN_SIZE 8 /* 64 bits = 8 bytes */
#define HASH_LEN_OFFSET 56 /* 64 bytes - 8 bytes */
#define HASH_DIGEST_SIZE 16 /* 128 bits = 16 bytes */
#define HASH_ROUND_NUM 64
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
/* SHA256 Constants */
static const uint32_t K[HASH_ROUND_NUM] = {
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
};
/* Swap bytes in 32 bit value. 0x01234567 -> 0x67452301 */
#define __bswap_32(x) \
((((x) & 0xff000000) >> 24) \
| (((x) & 0x00ff0000) >> 8) \
| (((x) & 0x0000ff00) << 8) \
| (((x) & 0x000000ff) << 24))
static uint32_t Ch(uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) ^ ((~X) & Z);
}
static uint32_t Maj(uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) ^ (X & Z) ^ (Y & Z);
}
/* 循环向右移动offset个比特位 */
static uint32_t ROTR(uint32_t X, uint8_t offset)
{
uint32_t res = (X >> offset) | (X << (32 - offset));
return res;
}
/* 向右移动offset个比特位 */
static uint32_t SHR(uint32_t X, uint8_t offset)
{
uint32_t res = X >> offset;
return res;
}
/* SIGMA0 */
static uint32_t SIGMA0(uint32_t X)
{
return ROTR(X, 2) ^ ROTR(X, 13) ^ ROTR(X, 22);
}
/* SIGMA1 */
static uint32_t SIGMA1(uint32_t X)
{
return ROTR(X, 6) ^ ROTR(X, 11) ^ ROTR(X, 25);
}
/* sigma0, different from SIGMA0 */
static uint32_t sigma0(uint32_t X)
{
uint32_t res = ROTR(X, 7) ^ ROTR(X, 18) ^ SHR(X, 3);
return ROTR(X, 7) ^ ROTR(X, 18) ^ SHR(X, 3);
}
/* sigma1, different from SIGMA1 */
static uint32_t sigma1(uint32_t X)
{
return ROTR(X, 17) ^ ROTR(X, 19) ^ SHR(X, 10);
}
#define ASSERT_RETURN_INT(x, d) if(!(x)) { return d; }
int sha2_256(unsigned char *out, const unsigned char* in, const int inlen)
{
ASSERT_RETURN_INT(out && in && (inlen >= 0), 1);
int i = 0, j = 0, t = 0;
// step 1: 字节填充(Append Padding Bytes)
// 数据先补上1个1比特,再补上k个0比特,使得补位后的数据比特数(n+1+k)满足(n+1+k) mod 512 = 448,k取最小正整数
int iX = inlen / HASH_BLOCK_SIZE;
int iY = inlen % HASH_BLOCK_SIZE;
iX = (iY < HASH_LEN_OFFSET) ? iX : (iX + 1);
int iLen = (iX + 1) * HASH_BLOCK_SIZE;
unsigned char* X = malloc(iLen);
memcpy(X, in, inlen);
// 先补上1个1比特+7个0比特
X[inlen] = 0x80;
// 再补上(k-7)个0比特
for (i = inlen + 1; i < (iX * HASH_BLOCK_SIZE + HASH_LEN_OFFSET); i++)
{
X[i] = 0;
}
// step 2: 追加长度信息(Append Length)
uint8_t *pLen = (uint64_t*)(X + (iX * HASH_BLOCK_SIZE + HASH_LEN_OFFSET));
uint64_t iTempLen = inlen << 3;
uint8_t *pTempLen = &iTempLen;
pLen[0] = pTempLen[7]; pLen[1] = pTempLen[6]; pLen[2] = pTempLen[5]; pLen[3] = pTempLen[4];
pLen[4] = pTempLen[3]; pLen[5] = pTempLen[2]; pLen[6] = pTempLen[1]; pLen[7] = pTempLen[0];
// Step 3. 初始化MD Buffer(Initialize MD Buffer)
uint32_t H0 = 0x6A09E667;
uint32_t H1 = 0xBB67AE85;
uint32_t H2 = 0x3C6EF372;
uint32_t H3 = 0xA54FF53A;
uint32_t H4 = 0x510E527F;
uint32_t H5 = 0x9B05688C;
uint32_t H6 = 0x1F83D9AB;
uint32_t H7 = 0x5BE0CD19;
uint32_t M[HASH_BLOCK_SIZE / 4] = { 0 };
uint32_t W[HASH_ROUND_NUM] = { 0 };
// step 4: 处理消息块(Process Message in 64-Byte Blocks)
for (i = 0; i < iLen / HASH_BLOCK_SIZE; i++)
{
/* Copy block i into M. */
for (j = 0; j < HASH_BLOCK_SIZE; j = j + 4)
{
uint64_t k = i * HASH_BLOCK_SIZE + j;
M[j / 4] = (X[k] << 24) | (X[k + 1] << 16) | (X[k + 2] << 8) | X[k + 3];
}
/* W[t]=M[t]; t:[0,15] */
for (t = 0; t <= 15; t++)
{
W[t] = M[t];
}
/* W[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) + W[t - 16]; t:[16,63] */
for (t = 16; t < HASH_ROUND_NUM; t++)
{
W[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) + W[t - 16];
}
uint32_t A = H0;
uint32_t B = H1;
uint32_t C = H2;
uint32_t D = H3;
uint32_t E = H4;
uint32_t F = H5;
uint32_t G = H6;
uint32_t H = H7;
for (t = 0; t < HASH_ROUND_NUM; t++)
{
uint32_t T1 = H + SIGMA1(E) + Ch(E, F, G) + K[t] + W[t];
uint32_t T2 = SIGMA0(A) + Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + T1;
D = C;
C = B;
B = A;
A = T1 + T2;
//printf("t=%02d:\t 0x%02X\t\t 0x%02X\t\t 0x%02X\t\t 0x%02X\t\t \n", t, E, F, G, H);
}
H0 = H0 + A;
H1 = H1 + B;
H2 = H2 + C;
H3 = H3 + D;
H4 = H4 + E;
H5 = H5 + F;
H6 = H6 + G;
H7 = H7 + H;
}
// step 5: 输出
uint32_t* pOut = (uint8_t*)out;
pOut[0] = __bswap_32(H0);
pOut[1] = __bswap_32(H1);
pOut[2] = __bswap_32(H2);
pOut[3] = __bswap_32(H3);
pOut[4] = __bswap_32(H4);
pOut[5] = __bswap_32(H5);
pOut[6] = __bswap_32(H6);
pOut[7] = __bswap_32(H7);
free(X);
return 0;
}
int main()
{
unsigned char digest[32] = { 0 };
sha2_256(digest, "Hello World!", strlen("Hello World!"));
return 0;
}
原文来自
原文来自