C语言中比特与无符号字符数组比较及SHA256部分碰撞测试技术问询
解决SHA256哈希前24比特与十六进制参数的比较问题
我来帮你搞定这个C语言里的比特级比较需求,结合你的场景(检测SHA256哈希前24比特是否匹配2612c7),咱们一步步实现:
核心思路
要完成这个比较,需要分三个关键步骤:
- 把命令行传入的十六进制字符串(
argv[1])转换成对应的24比特数值 - 从SHA256哈希结果(
buffer)中提取前24比特并转换成相同格式的数值 - 直接比较两个数值是否相等,相等即找到部分碰撞
具体实现代码
结合OpenSSL的EVP库,给你一个完整的可运行代码片段:
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <openssl/evp.h> #include <openssl/rand.h> int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "Usage: %s <24-bit-hex-prefix>\n", argv[0]); return EXIT_FAILURE; } // 步骤1:解析命令行参数为24比特目标值 uint32_t target_prefix = 0; if (sscanf(argv[1], "%x", &target_prefix) != 1) { fprintf(stderr, "Invalid hexadecimal input\n"); return EXIT_FAILURE; } // 掩码确保只保留低24比特(防止输入超过6位十六进制的情况) target_prefix &= 0xFFFFFF; // 初始化SHA256上下文 EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); if (!mdctx) { fprintf(stderr, "Failed to create EVP context\n"); return EXIT_FAILURE; } if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1) { fprintf(stderr, "Failed to initialize SHA256\n"); EVP_MD_CTX_free(mdctx); return EXIT_FAILURE; } // 随机字节缓冲区(可根据需求调整大小) unsigned char random_data[32]; unsigned char hash_buffer[EVP_MAX_MD_SIZE]; unsigned int hash_len; printf("Searching for SHA256 prefix matching: %s\n", argv[1]); // 循环生成随机数据并检测哈希前缀 while (1) { // 生成高质量随机数据(比rand()更安全) if (RAND_bytes(random_data, sizeof(random_data)) != 1) { fprintf(stderr, "Failed to generate random data\n"); break; } // 计算SHA256哈希 if (EVP_DigestUpdate(mdctx, random_data, sizeof(random_data)) != 1) { fprintf(stderr, "Failed to update digest\n"); break; } if (EVP_DigestFinal_ex(mdctx, hash_buffer, &hash_len) != 1) { fprintf(stderr, "Failed to finalize digest\n"); break; } // 重置上下文,准备下一次哈希计算 EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); // 步骤2:提取哈希的前24比特(SHA256输出是大端序,按字节拼接) uint32_t hash_prefix = ((uint32_t)hash_buffer[0] << 16) | ((uint32_t)hash_buffer[1] << 8) | hash_buffer[2]; // 步骤3:比较前缀 if (hash_prefix == target_prefix) { printf("Found match!\n"); printf("Random data: "); for (int i = 0; i < sizeof(random_data); i++) { printf("%02x", random_data[i]); } printf("\nSHA256 hash: "); for (int i = 0; i < hash_len; i++) { printf("%02x", hash_buffer[i]); } printf("\n"); break; } } EVP_MD_CTX_free(mdctx); return EXIT_SUCCESS; }
关键细节解释
- 十六进制参数解析:
- 用
sscanf("%x", ...)把字符串转成32位整数,再用0xFFFFFF掩码确保只保留低24比特,避免输入过长的十六进制字符串导致错误。
- 用
- 哈希前缀提取:
- SHA256的输出是大端字节序,所以哈希的第一个字节是最高8位,第二个是中间8位,第三个是最低8位。通过左移操作把这三个字节拼接成一个32位整数,刚好对应前24比特的数值。
- 随机数据生成:
- 用OpenSSL的
RAND_bytes生成随机数据,比标准库的rand()安全性更高,更适合碰撞测试场景。
- 用OpenSSL的
- 上下文重置:
- 每次计算哈希后,需要用
EVP_DigestInit_ex重置上下文,才能重新计算下一个随机数据的哈希。
- 每次计算哈希后,需要用
编译与运行
编译时需要链接OpenSSL库:
gcc -o sha256 sha256_collision.c -lcrypto
运行时传入目标前缀:
./sha256 2612c7
内容的提问来源于stack exchange,提问作者bli00
相关产品推荐
相关产品推荐

