【加解密与C】HASH系列(二) SHA

发布于:2025-07-03 ⋅ 阅读:(13) ⋅ 点赞:(0)

SHA(安全散列算法)简介

SHA(Secure Hash Algorithm)是由美国国家安全局(NSA)设计的一系列密码散列函数,用于将任意长度的数据转换为固定长度的散列值。SHA家族包括SHA-1、SHA-2(含SHA-256、SHA-384、SHA-512等)和SHA-3,广泛应用于数据完整性验证、数字签名和密码学安全领域。

SHA算法的主要特性

  1. 确定性:相同的输入始终生成相同的散列值。
  2. 不可逆性:无法从散列值反推原始数据。
  3. 雪崩效应:输入的微小变化会导致输出散列值显著不同。
  4. 抗碰撞性:难以找到两个不同输入产生相同的散列值。

常见SHA算法及其区别

SHA-1
  • 输出长度:160位(20字节)。
  • 安全性:已不推荐用于安全场景,因存在理论碰撞攻击风险。
SHA-2
  • 包含多个变体:
    • SHA-256:输出256位(32字节),最常用。
    • SHA-384:输出384位(48字节)。
    • SHA-512:输出512位(64字节)。
  • 安全性:目前广泛使用,未发现有效攻击。
SHA-3
  • 基于Keccak算法,与SHA-2结构不同。
  • 输出长度可选(224、256、384、512位)。
  • 设计上更抗未来潜在攻击。

SHA的应用场景

  1. 数据完整性校验:验证文件或传输数据是否被篡改(如软件下载校验)。
  2. 密码存储:结合盐值(salt)存储用户密码散列值。
  3. 区块链:比特币等加密货币使用SHA-256计算区块哈希。
  4. 数字签名:生成消息摘要以进行签名验证。

本篇代码不包含sha-3

sha.h

#ifndef __SHA__
#define __SHA__

#include <stdint.h>

void sha128(const uint8_t* data, size_t len, uint8_t digest[16]);

void sha224(const uint8_t* data, size_t len, uint8_t digest[28]);

void sha256_full(const uint8_t* data, size_t len, uint8_t digest[32]);

void sha384(const uint8_t* data, size_t len, uint8_t digest[48]);

void sha512_full(const uint8_t* data, size_t len, uint8_t digest[64]);

void sha192(const uint8_t* data, size_t len, uint8_t digest[24]);

#endif

sha.cpp

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "sha.h"

// ======================== 通用工具函数 ========================
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))  // 32位循环左移
#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) // 循环左移
#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) // 循环右移

// 内存反转(大端序处理)
void mem_reverse(uint8_t *buf, size_t len) {
    for (size_t i = 0; i < len / 2; i++) {
        uint8_t tmp = buf[i];
        buf[i] = buf[len - 1 - i];
        buf[len - 1 - i] = tmp;
    }
}

// ======================== SHA-1 (160位) ========================
void sha1(const uint8_t *data, size_t len, uint8_t digest[20]) {
    // 初始化哈希值
    uint32_t h[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};
    uint64_t bit_len = len * 8;
    size_t new_len = ((len + 8) / 64 + 1) * 64;
    uint8_t *msg = (uint8_t*)calloc(new_len, 1);
    memcpy(msg, data, len);
    msg[len] = 0x80; // 添加填充位

    // 添加长度信息(大端序)
    memcpy(msg + new_len - 8, &bit_len, 8);
    mem_reverse(msg + new_len - 8, 8);

    // 处理每个512位块
    for (size_t i = 0; i < new_len; i += 64) {
        uint32_t w[80] = {0};
        for (int t = 0; t < 16; t++) 
            memcpy(&w[t], msg + i + t * 4, 4);

        // 扩展消息
        for (int t = 16; t < 80; t++) 
            w[t] = ROTL(w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16], 1);

        uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4];
        // 主循环
        for (int t = 0; t < 80; t++) {
            uint32_t f, k;
            if (t < 20) {
                f = (b & c) | ((~b) & d);
                k = 0x5A827999;
            } else if (t < 40) {
                f = b ^ c ^ d;
                k = 0x6ED9EBA1;
            } else if (t < 60) {
                f = (b & c) | (b & d) | (c & d);
                k = 0x8F1BBCDC;
            } else {
                f = b ^ c ^ d;
                k = 0xCA62C1D6;
            }
            uint32_t temp = ROTL(a, 5) + f + e + k + w[t];
            e = d; d = c; c = ROTL(b, 30); b = a; a = temp;
        }
        h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e;
    }
    free(msg);
    // 输出到digest(大端序)
    for (int i = 0; i < 5; i++) {
        mem_reverse((uint8_t*)&h[i], 4);
        memcpy(digest + i * 4, &h[i], 4);
    }
}

// ======================== SHA-256/224 ========================
void sha256(const uint8_t *data, size_t len, uint8_t digest[32], int is224) {
    // 初始化哈希值
    uint32_t h[8] = {
        0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
        0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
    };
    if (is224) {
        h[0] = 0xC1059ED8; h[1] = 0x367CD507; h[2] = 0x3070DD17; h[3] = 0xF70E5939;
        h[4] = 0xFFC00B31; h[5] = 0x68581511; h[6] = 0x64F98FA7; h[7] = 0xBEFA4FA4;
    }

    // 常量表
    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
    };

    // 预处理(填充)
    uint64_t bit_len = len * 8;
    size_t new_len = ((len + 8) / 64 + 1) * 64;
    uint8_t *msg = (uint8_t *)calloc(new_len, 1);
    memcpy(msg, data, len);
    msg[len] = 0x80;
    memcpy(msg + new_len - 8, &bit_len, 8);
    mem_reverse(msg + new_len - 8, 8);

    // 处理每个512位块
    for (size_t i = 0; i < new_len; i += 64) {
        uint32_t w[64] = {0};
        for (int t = 0; t < 16; t++) {
            memcpy(&w[t], msg + i + t * 4, 4);
            mem_reverse((uint8_t*)&w[t], 4); // 转大端序
        }

        // 扩展消息
        for (int t = 16; t < 64; t++) {
            uint32_t s0 = ROTR(w[t-15], 7) ^ ROTR(w[t-15], 18) ^ (w[t-15] >> 3);
            uint32_t s1 = ROTR(w[t-2], 17) ^ ROTR(w[t-2], 19) ^ (w[t-2] >> 10);
            w[t] = w[t-16] + s0 + w[t-7] + s1;
        }

        uint32_t a = h[0], b = h[1], c = h[2], d = h[3];
        uint32_t e = h[4], f = h[5], g = h[6], h_val = h[7];

        // 主循环
        for (int t = 0; t < 64; t++) {
            uint32_t S1 = ROTR(e, 6) ^ ROTR(e, 11) ^ ROTR(e, 25);
            uint32_t ch = (e & f) ^ ((~e) & g);
            uint32_t temp1 = h_val + S1 + ch + k[t] + w[t];
            uint32_t S0 = ROTR(a, 2) ^ ROTR(a, 13) ^ ROTR(a, 22);
            uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
            uint32_t temp2 = S0 + maj;

            h_val = g; g = f; f = e; e = d + temp1;
            d = c; c = b; b = a; a = temp1 + temp2;
        }
        h[0] += a; h[1] += b; h[2] += c; h[3] += d;
        h[4] += e; h[5] += f; h[6] += g; h[7] += h_val;
    }
    free(msg);

    // 输出结果
    for (int i = 0; i < (is224 ? 7 : 8); i++) {
        mem_reverse((uint8_t*)&h[i], 4);
        memcpy(digest + i * 4, &h[i], 4);
    }
}

// ======================== SHA-512/384 ========================
void sha512(const uint8_t *data, size_t len, uint8_t digest[64], int is384) {
    // 初始化哈希值
    uint64_t h[8] = {
        0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
        0x510E527FADE682D1, 0x9B05688C2B3E6C1F, 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
    };
    if (is384) {
        h[0] = 0xCBBB9D5DC1059ED8; h[1] = 0x629A292A367CD507; h[2] = 0x9159015A3070DD17;
        h[3] = 0x152FECD8F70E5939; h[4] = 0x67332667FFC00B31; h[5] = 0x8EB44A8768581511;
        h[6] = 0xDB0C2E0D64F98FA7; h[7] = 0x47B5481DBEFA4FA4;
    }

    // 常量表
    const uint64_t k[80] = {
        0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
        0x3956C25BF348B538, 0x59F111F1B605D019, 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
        0xD807AA98A3030242, 0x12835B0145706FBE, 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
        0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, 0x9BDC06A725C71235, 0xC19BF174CF692694,
        0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
        0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
        0x983E5152EE66DFAB, 0xA831C66D2DB43210, 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
        0xC6E00BF33DA88FC2, 0xD5A79147930AA725, 0x06CA6351E003826F, 0x142929670A0E6E70,
        0x27B70A8546D22FFC, 0x2E1B21385C26C926, 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
        0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, 0x81C2C92E47EDAEE6, 0x92722C851482353B,
        0xA2BFE8A14CF10364, 0xA81A664BBC423001, 0xC24B8B70D0F89791, 0xC76C51A30654BE30,
        0xD192E819D6EF5218, 0xD69906245565A910, 0xF40E35855771202A, 0x106AA07032BBD1B8,
        0x19A4C116B8D2D0C8, 0x1E376C085141AB53, 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
        0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
        0x748F82EE5DEFB2FC, 0x78A5636F43172F60, 0x84C87814A1F0AB72, 0x8CC702081A6439EC,
        0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, 0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
        0xCA273ECEEA26619C, 0xD186B8C721C0C207, 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
        0x06F067AA72176FBA, 0x0A637DC5A2C898A6, 0x113F9804BEF90DAE, 0x1B710B35131C471B,
        0x28DB77F523047D84, 0x32CAAB7B40C72493, 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
        0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817
    };

    // 预处理(填充)
    uint64_t bit_len = len * 8;
    size_t new_len = ((len + 16) / 128 + 1) * 128;
    uint8_t *msg = (uint8_t*)calloc(new_len, 1);
    memcpy(msg, data, len);
    msg[len] = 0x80;
    memcpy(msg + new_len - 16, &bit_len, 8); // 长度存储在后128位的最后16字节中
    mem_reverse(msg + new_len - 16, 8);

    // 处理每个1024位块
    for (size_t i = 0; i < new_len; i += 128) {
        uint64_t w[80] = {0};
        for (int t = 0; t < 16; t++) {
            memcpy(&w[t], msg + i + t * 8, 8);
            mem_reverse((uint8_t*)&w[t], 8); // 转大端序
        }

        // 扩展消息
        for (int t = 16; t < 80; t++) {
            uint64_t s0 = ROTR64(w[t-15], 1) ^ ROTR64(w[t-15], 8) ^ (w[t-15] >> 7);
            uint64_t s1 = ROTR64(w[t-2], 19) ^ ROTR64(w[t-2], 61) ^ (w[t-2] >> 6);
            w[t] = w[t-16] + s0 + w[t-7] + s1;
        }

        uint64_t a = h[0], b = h[1], c = h[2], d = h[3];
        uint64_t e = h[4], f = h[5], g = h[6], h_val = h[7];

        // 主循环
        for (int t = 0; t < 80; t++) {
            uint64_t S1 = ROTR64(e, 14) ^ ROTR64(e, 18) ^ ROTR64(e, 41);
            uint64_t ch = (e & f) ^ ((~e) & g);
            uint64_t temp1 = h_val + S1 + ch + k[t] + w[t];
            uint64_t S0 = ROTR64(a, 28) ^ ROTR64(a, 34) ^ ROTR64(a, 39);
            uint64_t maj = (a & b) ^ (a & c) ^ (b & c);
            uint64_t temp2 = S0 + maj;

            h_val = g; g = f; f = e; e = d + temp1;
            d = c; c = b; b = a; a = temp1 + temp2;
        }
        h[0] += a; h[1] += b; h[2] += c; h[3] += d;
        h[4] += e; h[5] += f; h[6] += g; h[7] += h_val;
    }
    free(msg);

    // 输出结果
    for (int i = 0; i < (is384 ? 6 : 8); i++) {
        mem_reverse((uint8_t*)&h[i], 8);
        memcpy(digest + i * 8, &h[i], 8);
    }
}

// ======================== 用户接口函数 ========================
void sha128(const uint8_t *data, size_t len, uint8_t digest[16]) {
    uint8_t full_digest[20];
    sha1(data, len, full_digest);
    memcpy(digest, full_digest, 16); // 截取前128位
}

void sha224(const uint8_t *data, size_t len, uint8_t digest[28]) {
    sha256(data, len, digest, 1);
}

void sha256_full(const uint8_t *data, size_t len, uint8_t digest[32]) {
    sha256(data, len, digest, 0);
}

void sha384(const uint8_t *data, size_t len, uint8_t digest[48]) {
    sha512(data, len, digest, 1);
}

void sha512_full(const uint8_t *data, size_t len, uint8_t digest[64]) {
    sha512(data, len, digest, 0);
}

void sha192(const uint8_t *data, size_t len, uint8_t digest[24]) {
    uint8_t full_digest[64];
    sha512_full(data, len, full_digest);
    memcpy(digest, full_digest, 24); // 截取前192位
}


网站公告

今日签到

点亮在社区的每一天
去签到