You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用-pg与优化选项生成SHA3-512哈希时出现异常现象求助

问题分析与修复方案

核心问题根源

你的程序在同时启用-pg(gprof性能分析)和-O1/-O2/-O3优化时出现异常,本质是未定义行为在特定编译选项组合下触发了巧合的错误结果,具体问题点如下:

1. 未初始化的res_size参数导致哈希计算异常

tomcrypt的hash_memory函数要求最后一个参数outlen在调用前必须设置为输出缓冲区的大小(SHA3-512输出为64字节)。你的代码中unsigned long res_size;未初始化,传递给hash_memory后会引入随机值,在优化+gprof的环境下,这个随机值刚好导致哈希输出的前8字节被错误置零。

2. 哈希数据拼接逻辑完全错误

你设计的是随机字符串+nonce的组合哈希,但代码中把nonce写到了string[11...]的位置,覆盖了随机字符串的中间部分,并且哈希长度30+nonce_len会包含string[30...]的未初始化栈垃圾数据。在特定编译环境下,这些垃圾数据恰好让哈希前8位全零,导致循环直接退出。

3. 随机数生成的冗余与错误

randstring函数每次调用都执行srand(time(NULL)),如果函数被多次调用(当前代码仅调用一次,但属于不良设计),会导致随机数重复;同时rand() % 255生成的是0-254的值,无法覆盖完整的字节范围(应该用rand() % 256)。

修复后的代码

#include <tomcrypt.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

unsigned char* randstring(size_t length) {
    unsigned char* randomString = NULL;

    if (length) {
        randomString = malloc(sizeof(unsigned char) * length);
        if (randomString) {
            for (size_t n = 0; n < length; n++) {
                int key = rand() % 256; // 生成0-255的完整字节值
                randomString[n] = (unsigned char)key;
            }
        }
    }
    return randomString;
}

void find_nonce(int zeroes, int* nonce_ptr, unsigned char* returner, int hash_idx) {
    unsigned char string[40];
    memset(string, 0, sizeof(string)); // 初始化栈数组,避免垃圾数据

    unsigned char* rand_string = randstring(30);
    memcpy(string, rand_string, 30);
    free(rand_string);

    int nonce = 0;
    bool res_bool = false;
    unsigned char res[64];
    unsigned long res_size = sizeof(res); // 正确设置输出缓冲区大小
    char nonce_str[11];

    while (!res_bool) {
        sprintf(nonce_str, "%d", nonce);
        int nonce_len = strlen(nonce_str);

        // 将nonce追加到随机字符串末尾(string[30...]位置)
        memcpy(&string[30], nonce_str, nonce_len);

        // 计算哈希:随机字符串(30字节) + nonce字符串(nonce_len字节)
        hash_memory(hash_idx, string, 30 + nonce_len, res, &res_size);

        // 检查前导零数量
        res_bool = true;
        for (int i = 0; i < zeroes; i++) {
            if (res[i] != 0) {
                res_bool = false;
                break;
            }
        }
        nonce++;
    }

    *nonce_ptr = nonce;
    memcpy(returner, res, sizeof(res));
}

int main(int argc, char** argv) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <number_of_zeroes>\n", argv[0]);
        return 1;
    }

    int zeroes = atoi(argv[argc - 1]);
    if (zeroes < 1 || zeroes > 64) {
        fprintf(stderr, "Zeroes must be between 1 and 64\n");
        return 1;
    }

    // 只注册一次哈希算法
    if (register_hash(&sha3_512_desc) == -1) {
        fprintf(stderr, "Error registering SHA3-512.\n");
        return 1;
    }
    int hash_idx = find_hash("sha3-512");
    if (hash_idx == -1) {
        fprintf(stderr, "Invalid hash name!\n");
        return 1;
    }

    // 初始化随机数生成器(只执行一次)
    srand(time(NULL));

    int nonce;
    unsigned char hash[64];

    clock_t start, end;
    double cpu_time_used;

    start = clock();
    find_nonce(zeroes, &nonce, hash, hash_idx);
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;

    printf("Hash was ");
    for (int i = 0; i < 64; i++) {
        printf("%d ", (int)hash[i]);
    }
    printf("\nNonce to get the hash was %d\nIt took %f seconds to calculate\n", nonce, cpu_time_used);

    return 0;
}

关键修复点说明

  1. 正确初始化res_size:调用hash_memory前设置res_size = sizeof(res),确保函数知道输出缓冲区的大小。
  2. 修正哈希拼接逻辑:将nonce追加到随机字符串的末尾(string[30...]),确保哈希的是随机字符串+nonce的合法组合,避免读取未初始化的栈数据。
  3. 初始化栈数组:用memset初始化string数组,消除垃圾数据的影响。
  4. 优化随机数生成:将srand(time(NULL))移到main函数只执行一次,修正rand() % 256以覆盖完整字节范围。
  5. 哈希算法注册逻辑优化:将register_hash和find_hash移到main函数,只执行一次,避免重复注册的潜在问题。
  6. 增加参数校验:添加命令行参数的合法性检查,提升程序健壮性。

编译说明

修复后的代码无论是否启用-pg和优化选项,都会正常工作:

  • 普通编译:gcc -o hashcash hashcash.c -ltomcrypt
  • 带gprof的优化编译:gcc -pg -O2 -o hashcash hashcash.c -ltomcrypt

内容的提问来源于stack exchange,提问作者drake14w

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:06:24