概述:使用 OpensSSL 进行 SM3 加密

以下是使用 OpenSSL 库进行 SM3 消息摘要和文件加密的 C++ 示例代码:

#include <iostream>
#include <fstream>
#include <string>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/sm3.h>
 
// 计算字符串的 SM3 摘要值
std::string sm3_hash_string(const std::string& str) {
    unsigned char md[SM3_DIGEST_LENGTH];
    SM3(reinterpret_cast<const unsigned char*>(str.data()), str.size(), md);
    std::string hash_str(reinterpret_cast<const char*>(md), SM3_DIGEST_LENGTH);
    return hash_str;
}
 
// 计算文件的 SM3 摘要值
std::string sm3_hash_file(const std::string& file_path) {
    unsigned char md[SM3_DIGEST_LENGTH];
    std::ifstream input(file_path, std::ios::binary);
    if (input) {
        EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
        EVP_DigestInit_ex(mdctx, EVP_sm3(), nullptr);
        const size_t buf_size = 4096;
        char buf[buf_size];
        while (input.read(buf, buf_size)) {
            EVP_DigestUpdate(mdctx, buf, buf_size);
        }
        size_t remain_size = input.gcount();
        EVP_DigestUpdate(mdctx, buf, remain_size);
        EVP_DigestFinal_ex(mdctx, md, nullptr);
        EVP_MD_CTX_free(mdctx);
        input.close();
        std::string hash_str(reinterpret_cast<const char*>(md), SM3_DIGEST_LENGTH);
        return hash_str;
    }
    else {
        throw std::runtime_error("fail to open file " + file_path);
    }
}
 
// 使用密码对文件进行加密
void encrypt_file(const std::string& input_file_path, const std::string& output_file_path, const std::string& password) {
    std::ifstream input(input_file_path, std::ios::binary);
    std::ofstream output(output_file_path, std::ios::binary);
    if (input && output) {
        const int key_len = EVP_MAX_KEY_LENGTH;
        const int iv_len = EVP_MAX_IV_LENGTH;
        unsigned char key[key_len];
        unsigned char iv[iv_len];
        EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sm3(), nullptr, reinterpret_cast<const unsigned char*>(password.data()), password.size(), 1, key, iv);
        EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
        EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, iv);
        const size_t buf_size = 4096;
        char buf[buf_size];
        while (input.read(buf, buf_size)) {
            int len = input.gcount();
            int out_len = 0;
            EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(buf), &out_len, reinterpret_cast<unsigned char*>(buf), len);
            output.write(buf, out_len);
        }
        int len = input.gcount();
        int out_len = 0;
        EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(buf), &out_len);
        output.write(buf, out_len);
        EVP_CIPHER_CTX_free(ctx);
        input.close();
        output.close();
    }
    else {
        throw std::runtime_error("fail to open input/output file.");
    }
 
}
 
int main() {
    std::string str = "message to be hashed";
    std::cout << "SM3 hash of string \"" << str << "\": " << sm3_hash_string(str) << std::endl;
    std::string file_path = "test.txt";
    std::cout << "SM3 hash of file \"" << file_path << "\": " << sm3_hash_file(file_path) << std::endl;
    std::string password = "123456";
    try {
        encrypt_file(file_path, "test_encrypted.txt", password);
    }
    catch (const std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
    }
    return 0;
}

上述代码中,使用 SM3 函数对字符串或文件内容进行摘要;使用 EVP_BytesToKey 函数生成密码加密密钥和初始化向量,并使用 EVP_EncryptInit_ex 函数初始化加密上下文,在循环中调用 EVP_EncryptUpdate 函数对文件进行逐块加密,最后调用 EVP_EncryptFinal_ex 函数完成加密过程,将结果写入新的加密文件中。