开发者
资源
文档评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

SM4-CBC算法调用示例

保存以下代码至sm4_cbc_demo.c,编译运行。

gcc -o sm4_cbc_demo sm4_cbc_demo.c -lssl -lcrypto -ldl
./sm4_cbc_demo
/**
 * sm4_cbc_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;
static const unsigned char g_key16[] = {
    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
    0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
static const unsigned char g_iv16[] = {
    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
    0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
};
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_sm4_cbc(void) {
    unsigned char pt[32] = "abcdefghijklmnopqrstuvwxyz012345";
    unsigned char ct[48] = {0};
    unsigned char dt[48] = {0};
    int outl = 0, totl = 0;
    /* 加密 */
    EVP_CIPHER_CTX *ectx = EVP_CIPHER_CTX_new();
    if (!ectx) {
        fprintf(stderr, "Encrypt ctx new failed\n");
        exit(EXIT_FAILURE);
    }
    if (EVP_EncryptInit_ex(ectx, EVP_sm4_cbc(), g_engine, g_key16, g_iv16) != 1) {
        fprintf(stderr, "EncryptInit failed\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    if (EVP_EncryptUpdate(ectx, ct, &outl, pt, 32) != 1) {
        fprintf(stderr, "EncryptUpdate failed\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    totl = outl;
    if (EVP_EncryptFinal_ex(ectx, ct + totl, &outl) != 1) {
        fprintf(stderr, "EncryptFinal failed\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    totl += outl;
    if (totl != 48) {
        fprintf(stderr, "CBC ciphertext length wrong\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    EVP_CIPHER_CTX_free(ectx);
    /* 解密 */
    EVP_CIPHER_CTX *dctx = EVP_CIPHER_CTX_new();
    if (!dctx) {
        fprintf(stderr, "Decrypt ctx new failed\n");
        exit(EXIT_FAILURE);
    }
    if (EVP_DecryptInit_ex(dctx, EVP_sm4_cbc(), g_engine, g_key16, g_iv16) != 1) {
        fprintf(stderr, "DecryptInit failed\n");
        EVP_CIPHER_CTX_free(dctx);
        exit(EXIT_FAILURE);
    }
    if (EVP_DecryptUpdate(dctx, dt, &outl, ct, 48) != 1) {
        fprintf(stderr, "DecryptUpdate failed\n");
        EVP_CIPHER_CTX_free(dctx);
        exit(EXIT_FAILURE);
    }
    totl = outl;
    if (EVP_DecryptFinal_ex(dctx, dt + totl, &outl) != 1) {
        fprintf(stderr, "DecryptFinal failed\n");
        EVP_CIPHER_CTX_free(dctx);
        exit(EXIT_FAILURE);
    }
    totl += outl;
    EVP_CIPHER_CTX_free(dctx);
    if (totl != 32 || memcmp(dt, pt, 32) != 0) {
        fprintf(stderr, "CBC round-trip failed\n");
        exit(EXIT_FAILURE);
    }
    printf("SM4-CBC encryption/decryption: 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_sm4_cbc();
    ENGINE_free(g_engine);

    printf("SM4-CBC test passed.\n");
    return EXIT_SUCCESS;
}