一、SHA256算法介绍
SHA256算法总体上来说就是对原始数据进行分段加密,并且当前分段的加密结果受到上一分段加密结果的影响,最后一段的加密结果就是最终的结果(和混沌系统有点类似)。
具体的算法细节见博客《SHA256算法原理详解》
二、SHA256算法C++实现
1)sha256.h
/*
* Copyright (c)
* Filename: sha256.h
* Brief: SHA256算法实现
* Depend: C++11
*
* Version: V1.0.0
* Date: 2019/11/08-2019/11/13
* Author: LucianY
* Note: 初次版本。
*
* Version: V2.0.0
* Date: 2023/01/04
* Author: LucianY
* Note: 1、代码优化:使用单例模式;
* 2、debug:支持加密空字符串;
* 3、性能优化。
*
* Attention: 输入信息中有中文时,得到的数字指纹与使用其他工具得到数字指纹可能不相同。原因是不同平台中文的编码方式不同。
*/
#ifndef LY_SHA256_H
#define LY_SHA256_H
#include <cstdint>
#include <string>
#include <vector>
namespace Ly {
/**
* @brief SHA256加密类
*/
class Sha256 {
public:
//! 获取单例
inline static Sha256 &getInstance()
{
static Sha256 instance;
return instance;
}
/**
* @brief: 使用SHA256算法,加密输入信息(获取数字指纹)
* @param[in] message: 输入信息
* @return: 摘要(数字指纹)
*/
std::vector<uint8_t> encrypt(std::vector<uint8_t> message) const;
/**
* @brief: 获取十六进制表示的信息摘要(数字指纹)
* @param[in] message: 输入信息
* @return: 十六进制表示的信息摘要(数字指纹)
*/
std::string getHexMessageDigest(const std::string &message) const;
protected:
/// SHA256算法中定义的6种逻辑运算 ///
inline uint32_t ch(uint32_t x, uint32_t y, uint32_t z) const noexcept
{
return (x & y) ^ ((~x) & z);
}
inline uint32_t maj(uint32_t x, uint32_t y, uint32_t z) const noexcept
{
return (x & y) ^ (x & z) ^ (y & z);
}
inline uint32_t bigSigma0(uint32_t x) const noexcept
{
return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10);
}
inline uint32_t bigSigma1(uint32_t x) const noexcept
{
return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7);
}
inline uint32_t smallSigma0(uint32_t x) const noexcept
{
return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3);
}
inline uint32_t smallSigma1(uint32_t x) const noexcept
{
return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10);
}
/**
* @brief: SHA256算法对输入信息的预处理,包括“附加填充比特”和“附加长度值”
附加填充比特: 在报文末尾进行填充,先补第一个比特为1,然后都补0,直到长度满足对512取模后余数是448。需要注意的是,信息必须进行填充。
附加长度值: 用一个64位的数据来表示原始消息(填充前的消息)的长度,并将其补到已经进行了填充操作的消息后面。
* @param[in][out] message: 待处理的信息
*/
void preprocessing(std::vector<uint8_t> &message) const;
/**
* @brief: 将信息分解成连续的64Byte大小的数据块
* @param[in] message: 输入信息,长度为64Byte的倍数
* @return: 输出数据块
*/
std::vector<std::vector<uint8_t>> breakTextInto64ByteChunks(const std::vector<uint8_t> &message) const;
/**
* @brief: 由64Byte大小的数据块,构造出64个4Byte大小的字。
构造算法:前16个字直接由数据块分解得到,其余的字由如下迭代公式得到:
W[t] = smallSigma1(W[t-2]) + W[t-7] + smallSigma0(W[t-15]) + W[t-16]
* @param[in] chunk: 输入数据块,大小为64Byte
* @return: 输出字
*/
std::vector<uint32_t> structureWords(const std::vector<uint8_t> &chunk) const;
/**
* @breif: 基于64个4Byte大小的字,进行64次循环加密
* @param[in] words: 64个4Byte大小的字
* @param[in][out] message_digest: 信息摘要
*/
void transform(const std::vector