SM3算法调用示例
将以下代码保存为sm3_demo.c后,编译运行。
gcc -o sm3_demo sm3_demo.c -lssl -lcrypto -ldl ./sm3_demo
/**
* sm3_demo.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#define ENGINE_SO_PATH "/usr/lib64/libsdf_engine.so"
#define SDF_LIB_PATH "/usr/lib64/libsdf.so"
static ENGINE *g_engine = NULL;
/* 预期的 SM3("abc") 哈希值 */
static const unsigned char expected_sm3_hash[] = {
0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9,
0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2,
0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2,
0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0
};
static ENGINE* load_engine(const char *so_path, const char *sdf_lib_path) {
ENGINE_load_dynamic();
ENGINE *e = ENGINE_by_id("dynamic");
if (!e) {
fprintf(stderr, "Failed to get dynamic ENGINE\n");
return NULL;
}
if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", so_path, 0)) goto err;
if (!ENGINE_ctrl_cmd_string(e, "ID", "sdf", 0)) goto err;
if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) goto err;
if (!ENGINE_ctrl_cmd_string(e, "SDF_LIB_PATH", sdf_lib_path, 0)) goto err;
if (!ENGINE_init(e)) goto err;
return e;
err:
ENGINE_free(e);
return NULL;
}
static void test_sm3_oneshot(void) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen = 0;
const char *msg = "abc";
if (EVP_Digest((const unsigned char*)msg, strlen(msg), md, &mdlen, EVP_sm3(), g_engine) != 1) {
fprintf(stderr, "EVP_Digest failed\n");
exit(EXIT_FAILURE);
}
if (mdlen != 32 || memcmp(md, expected_sm3_hash, 32) != 0) {
fprintf(stderr, "SM3 oneshot hash mismatch\n");
exit(EXIT_FAILURE);
}
printf("SM3 oneshot: OK\n");
}
static void test_sm3_stream(void) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdlen = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (!ctx) {
fprintf(stderr, "EVP_MD_CTX_new failed\n");
exit(EXIT_FAILURE);
}
if (EVP_DigestInit_ex(ctx, EVP_sm3(), g_engine) != 1) {
fprintf(stderr, "DigestInit failed\n");
EVP_MD_CTX_free(ctx);
exit(EXIT_FAILURE);
}
if (EVP_DigestUpdate(ctx, "abc", 3) != 1) {
fprintf(stderr, "DigestUpdate failed\n");
EVP_MD_CTX_free(ctx);
exit(EXIT_FAILURE);
}
if (EVP_DigestFinal_ex(ctx, md, &mdlen) != 1) {
fprintf(stderr, "DigestFinal failed\n");
EVP_MD_CTX_free(ctx);
exit(EXIT_FAILURE);
}
EVP_MD_CTX_free(ctx);
if (mdlen != 32 || memcmp(md, expected_sm3_hash, 32) != 0) {
fprintf(stderr, "SM3 stream hash mismatch\n");
exit(EXIT_FAILURE);
}
printf("SM3 stream: OK\n");
}
int main(void) {
printf("Loading ENGINE...\n");
g_engine = load_engine(ENGINE_SO_PATH, SDF_LIB_PATH);
if (!g_engine) {
fprintf(stderr, "Engine load failed\n");
return EXIT_FAILURE;
}
printf("Engine loaded.\n");
test_sm3_oneshot();
test_sm3_stream();
ENGINE_free(g_engine);
ENGINE_cleanup();
printf("All SM3 tests passed.\n");
return EXIT_SUCCESS;
}