基于 CS 模式或者 BS 模式 Hash 算法 软件包括客户端和服务器端,客户端实现文件 Hash 值计算,服务器端接收 的文件和 Hash 值,进行文件完整性验证。软件具体功能如下:
(1) 客户端文件 Hash 的计算 a)输入任意文件格式的文件
b)采用 Hash 算法计算 Hash 值,并十六进制显示 hash 值,然后把文件和 hash 值给服务器端
(2) 服务器端验证文件的完整性 a)接收端客户端文件和 Hash 值,然后分离得到文件和收到 Hash 值,然后 采用跟客户端一样 Hash 函数计算文件 Hash 值,计算 Hash 值与收到 Hash 比 较,若一致,则文件完整性认证通过,若不一致,则文件完整性验证不通过;
其它要求:
(1)用函数实现 Hash 算法
(2)可选择 C、C++、Java、Python 等任意一种编程语言实现。
核心代码:
//SHA-256 是一种密码学安全哈希函数,它能将不定长度的消息輸
// 入(input)進行加密,生成一个固定长度的哈希值(digest)。
#include <iostream>
#include <cstring>
#include <iomanip>
#include <sstream>
// 定义了一个右旋转操作 rightRotate,用于将二进制位向右旋转 n 位;
uint32_t rightRotate(uint32_t x, uint32_t n) {
return (x >> n) | (x << (32 - n));
}
//定义了一个常量数组 k,存储了 64 个常数,用于后续哈希计算;
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
};
// 定义了一个求 x 的 n 次方的函数 pow,用于一些哈希计算中;
uint32_t pow(uint32_t x, uint32_t n) {
uint32_t result = 1;
for (int i = 0; i < n; i++) {
result *= x;
}
return result;
}
// 定义了一个取 w 的第 n 个 32 位字的函数 getWord,用于一些哈希计算中;
uint32_t getWord(uint32_t w, uint32_t n) {
return (w >> (24 - n * 8)) & 0xff;
}
// 定义了 sha256 函数,实现 SHA-256 哈希计算,并将计算结果以字符串形式返回。
std::string sha256(const unsigned char* data, size_t length) {
//(1) 初始化 8 个 32 位的数(H0 ~ H7),用于后续哈希计算;
uint32_t h0 = 0x6a09e667; //存储哈希值H0
uint32_t h1 = 0xbb67ae85; //存储哈希值H1
uint32_t h2 = 0x3c6ef372; //存储哈希值H2
uint32_t h3 = 0xa54ff53a; //存储哈希值H3
uint32_t h4 = 0x510e527f; //存储哈希值H4
uint32_t h5 = 0x9b05688c; //存储哈希值H5
uint32_t h6 = 0x1f83d9ab; //存储哈希值H6
uint32_t h7 = 0x5be0cd19; //存储哈希值H7
//(2) 对输入的数据进行补位,使其长度满足 512 位的倍数,并且
// 在补位后的数据尾部添加一个 64 位的长度值,表示原始消息的长度(单位为位,64 位二进制数);
uint64_t bitLength = length * 8; //记录输入数据的长度
uint64_t paddingLength = (512 - (bitLength + 64) % 512) % 512; //计算需要补充的字节数
uint64_t newLength = length + paddingLength / 8 + 8; //计算补充后的总字节数,加上 8 是因为后面要在末尾加上一个长度为 64 位的值
uint8_t* newData = new uint8_t[newLength]; //创建一个新内存进行哈希计算
memset(newData, 0, newLength); //将新内存全部填充为 0
memcpy(newData, data, length); //将输入的数据复制到新内存中
newData[length] = 0x80; //在复制完数据后,末尾填充 1
for (int i = 0; i < 8; i++) {
//将长度为 64 位的消息长度写入末尾
newData[newLength - 8 + i] = (bitLength >> (56 - i * 8)) & 0xff;
}
//(3) 对于每个 512 位的消息块,进行哈希计算,最终得到的哈希值就是 sha256 算法的结果。
for (int i = 0; i < newLength; i += 64) {
//每次处理 512 位数据(64 个字),分为 16 组,每组 4 个字节(一个 uint32_t)
uint32_t w[64];
for (int j = 0; j < 16; j++) {
// 将 4 个字节组成一个 uint32_t
w[j] = (newData[i + j * 4] << 24) | (newData[i + j * 4 + 1] << 16) | (newData[i + j * 4 + 2] << 8) | newData[i + j * 4 + 3];
}
for (int j = 16; j < 64; j++) {
// 对 w[0] 到 w[15] 进行扩展
uint32_t s0 = rightRotate(w[j - 15], 7) ^ rightRotate(w[j - 15], 18) ^ (w[j - 15] >> 3);
uint32_t s1 = rightRotate(w[j - 2], 17) ^ rightRotate(w[j - 2], 19) ^ (w[j - 2] >> 10);
w[j] = w[j - 16] + s0 + w[j - 7] + s1;
}
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 (int j = 0; j < 64; j++) {
uint32_t S1 = rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25);
uint32_t ch = (e & f) ^ ((~e) & g);
uint32_t temp1 = h + S1 + ch + k[j] + w[j];
uint32_t S0 = rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22);
uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
uint32_t temp2 = S0 + maj;
h = g;
g = f;
f = e;
e = d + temp1;
d = c;
c = b;
b = a;
a = temp1 + temp2;
}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
h4 += e;
h5 += f;
h6 += g;
h7 += h;
}
delete[] newData; //释放内存
//将每个哈希值以 16 进制的形式表示,并拼接成一个字符串
std::stringstream ss;
ss << std::hex << std::setfill('0') << std::setw(8) << h0
<< std::setw(8) << h1 << std::setw(8) << h2 << std::setw(8) << h3
<< std::setw(8) << h4 << std::setw(8) << h5 << std::setw(8) << h6 << std::setw(8) << h7;
std::cout<<"生成的sha256哈希值是:"<<ss.str()<<std::endl;
return ss.str(); //返回哈希值
}
完整代码实现文件已经打包放在压缩包中,需要的自取:
链接: https://pan.baidu.com/s/1oo0I5elf3apYs9yUzWyhmg?pwd=mvuy 提取码: mvuy