SM3 是中国国家密码管理局(State Cryptography Administration,SCA)发布的一种密码散列函数,属于SHA-3 候选算法,也是我国的商用密码算法标准之一。SM3 是一种密码学安全性较高的密码散列函数,广泛应用于数字签名、消息认证码(MAC)等安全领域。
以下是 SM3 密码散列函数的主要知识点:
在 OpenSSL 中,你可以使用 EVP(Envelope)接口来进行 SM3 哈希计算。以下是一个简单的 OpenSSL SM3 哈希计算的示例代码:
#include
#include
#include
#include
#include
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
void sm3_hash(const unsigned char *input, size_t input_len, unsigned char *output)
{
EVP_MD_CTX *mdctx;
const EVP_MD *md;
int md_len;
md = EVP_sm3(); // 使用 SM3 算法
mdctx = EVP_MD_CTX_new();
if (mdctx == NULL)
handleErrors();
if (1 != EVP_DigestInit_ex(mdctx, md, NULL))
handleErrors();
if (1 != EVP_DigestUpdate(mdctx, input, input_len))
handleErrors();
if (1 != EVP_DigestFinal_ex(mdctx, output, &md_len))
handleErrors();
EVP_MD_CTX_free(mdctx);
}
int main(void)
{
unsigned char data[] = "Hello, SM3!";
unsigned char hash_value[EVP_MAX_MD_SIZE];
int i;
printf("Original Data: %s\n", data);
sm3_hash(data, strlen((char *)data), hash_value);
printf("SM3 Hash Value: ");
for (i = 0; i < EVP_MD_size(EVP_sm3()); i++)
printf("%02x", hash_value[i]);
printf("\n");
return 0;
}
g++ -o main main.cpp -lssl -lcrypto
在此代码中,我们使用了 OpenSSL 的 EVP 接口来计算 SM3 哈希值。函数 sm3_hash
接受输入数据和其长度,然后计算 SM3 哈希值并将结果存储在 output
中。在 main
函数中,我们提供了一个简单的字符串作为输入数据,计算它的 SM3 哈希值并将结果输出。请确保你的系统上已经正确安装了 OpenSSL 库。
要使用 OpenSSL 计算文件的 SM3 哈希值,你可以使用以下的代码示例。这个示例会读取文件的内容并计算它的 SM3 哈希值:
#include
#include
#include
#include
#include
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
void sm3_file_hash(const char *file_path, unsigned char *output)
{
FILE *file = fopen(file_path, "rb");
if (file == NULL)
{
perror("Error opening file");
handleErrors();
}
EVP_MD_CTX *mdctx;
const EVP_MD *md;
unsigned int md_len;
unsigned char buffer[1024];
md = EVP_sm3(); // 使用 SM3 算法
mdctx = EVP_MD_CTX_new();
if (mdctx == NULL)
handleErrors();
if (1 != EVP_DigestInit_ex(mdctx, md, NULL))
handleErrors();
size_t bytes;
while ((bytes = fread(buffer, 1, sizeof(buffer), file)) != 0)
{
if (1 != EVP_DigestUpdate(mdctx, buffer, bytes))
handleErrors();
}
if (1 != EVP_DigestFinal_ex(mdctx, output, &md_len))
handleErrors();
fclose(file);
EVP_MD_CTX_free(mdctx);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s \n" , argv[0]);
return 1;
}
const char *file_path = argv[1];
unsigned char hash_value[EVP_MAX_MD_SIZE];
int i;
sm3_file_hash(file_path, hash_value);
printf("SM3 Hash Value: ");
for (i = 0; i < EVP_MD_size(EVP_sm3()); i++)
printf("%02x", hash_value[i]);
printf("\n");
return 0;
}
在这个示例中,sm3_file_hash
函数接受文件路径作为输入,然后计算文件的 SM3 哈希值并将结果存储在 output
中。在 main
函数中,我们通过命令行参数传递文件路径,并计算文件的 SM3 哈希值。
请确保在编译时链接 OpenSSL 库。你可以使用以下命令进行编译:
g++ -o main main.cpp -lssl -lcrypto
其中,sm3hash.c
是包含上述代码的源文件,-lssl
和 -lcrypto
用于链接 OpenSSL 库。编译后,你可以通过命令行运行可执行文件,指定要计算 SM3 哈希值的文件路径。
https://gitcode.net/arv002/qt/-/tree/master/Openssl/hash/sm3
Bit Padding(比特填充)是一种在密码学中常用的数据填充方式,通常用于将不定长的数据(比如消息)扩展为固定长度的块,以便进行加密或哈希处理。在使用密码散列函数(如MD5、SHA-1、SHA-256、SM3等)处理不定长数据时,需要将数据填充至块的整数倍长度,而Bit Padding是其中一种填充方法。
Bit Padding 的具体步骤如下:
在消息末尾加入一个比特"1"。例如,如果原始消息以0110 1101
结尾,添加比特"1"后为0110 1101 1
。
在上一步骤的结果后面填充零(“0”),直到消息的总长度(包括填充位)满足块长度的要求。例如,如果块长度为512比特,而消息长度(包括填充位和"1"位)为510比特,那么还需填充2个零。
在填充的零位之后,附加一个整数(以二进制形式表示)来表示原始消息的长度。通常,这个整数是原始消息的比特数,以64位(或128位,具体取决于算法)的形式表示。这一步骤确保了在处理时可以知道原始消息的实际长度。
举个例子,如果原始消息的长度为417比特,算法需要使用512比特的块进行处理,那么Bit Padding的步骤如下:
原始消息末尾添加比特"1":...111 0101 01 1
。
在上一步骤的结果后填充零,直到总长度为512比特:...111 0101 01 1000 0000
。
在填充的零位之后附加消息的长度,长度为417的二进制表示为1101 0001
,所以填充后的消息为:...111 0101 01 1000 0000 0000 0000 1101 0001
。
这样,填充后的消息长度满足块长度(512比特)的要求,并且算法在处理时可以知道原始消息的实际长度。填充的过程保证了消息在进行密码学操作时的标准化处理,确保了数据的完整性和安全性。