C语言SHA512摘要转整数及取模问题求助(附Python对比代码)
问题描述
我用SHA512生成消息摘要,想在C语言里把它转成512位整数后对某个数(比如7)取模。但用atoi或strtol转换时总是得到0,而Python里用int.from_bytes能正常实现。作为C语言新手,我需要解决这个转换问题,或者找到更高效的摘要取模方法。
我的代码如下:
C语言代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <OpenSSL/sha.h> int main() { unsigned char message[] = "hello world"; unsigned char digest[SHA512_DIGEST_LENGTH]; // 注意:SHA512摘要长度为64字节,不是512 SHA512(message, strlen((char *)message), digest); int integer_value = atoi((char *)digest); printf("The integer value of the message is %d\n", integer_value); return 0; }
Python代码
import hashlib import sys Message = "hello world" integer_value = int.from_bytes(hashlib.sha512(Message.encode()).digest(), sys.byteorder)
取模示例(Python)
import hashlib import sys Message = "hello world" integer_value = int.from_bytes(hashlib.sha512(Message.encode()).digest(), sys.byteorder) Modulo = integer_value % 7
问题原因
用atoi转换得到0的核心原因是:SHA512生成的digest是二进制字节数组,不是ASCII数字字符串。atoi仅能将"123"这类ASCII字符序列转为整数,而二进制字节中大概率包含非数字ASCII字符,甚至第一个字节就是0x00(字符串终止符),因此atoi会直接返回0。
解决方案
方法一:直接对摘要字节数组取模(高效推荐)
无需将整个512位摘要转为整数,利用模运算性质(a * 256 + b) % m = ((a % m) * 256 + b) % m,逐字节处理即可得到最终模结果,既高效又避免了超大整数的存储问题。
示例代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <OpenSSL/sha.h> int main() { unsigned char message[] = "hello world"; unsigned char digest[SHA512_DIGEST_LENGTH]; SHA512(message, strlen((char *)message), digest); const int mod = 7; unsigned long long result = 0; // 用足够大的类型存储中间结果,防止溢出 // 与Python默认小端字节序对应,从最后一个字节开始遍历;若用大端序则从第一个字节开始 for (int i = SHA512_DIGEST_LENGTH - 1; i >= 0; i--) { result = (result * 256 + digest[i]) % mod; } printf("Digest mod %d is %llu\n", mod, result); return 0; }
方法二:转换为512位整数(仅作演示,不推荐)
C语言无原生512位整数类型,需借助大整数库(如OpenSSL的BIGNUM)实现。示例代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <OpenSSL/sha.h> #include <OpenSSL/bn.h> int main() { unsigned char message[] = "hello world"; unsigned char digest[SHA512_DIGEST_LENGTH]; SHA512(message, strlen((char *)message), digest); // 初始化大整数 BIGNUM *bn = BN_new(); BN_bin2bn(digest, SHA512_DIGEST_LENGTH, bn); // 计算模7 BIGNUM *mod = BN_new(); BN_set_word(mod, 7); BIGNUM *result = BN_new(); BN_mod(result, bn, mod, NULL); // 打印结果 char *result_str = BN_bn2dec(result); printf("Digest mod 7 is %s\n", result_str); // 释放资源 BN_free(bn); BN_free(mod); BN_free(result); OPENSSL_free(result_str); return 0; }
编译时需链接OpenSSL库:gcc your_code.c -o output -lcrypto
说明
- 方法一更高效,无需处理超大整数的存储与运算,适合绝大多数取模场景。
- 注意字节序匹配:Python的
int.from_bytes默认使用系统字节序(通常为小端),因此方法一中的循环顺序需对应调整。
内容的提问来源于stack exchange,提问作者hah
相关产品推荐
相关产品推荐

