openssl编程之sm2加解密代码示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>


// 解析您的SM2密文数据
void parse_your_sm2_ciphertext(const unsigned char* asn1_data, size_t asn1_len)
{
	const unsigned char* p = asn1_data;
	long length;
	int tag, xclass;
	int offset = 0;
	int ret = 0;

	printf("=== Manual SM2 Ciphertext Analysis ===\n");
	printf("Total ASN.1 length: %ld bytes\n", asn1_len);

	// 解析外层SEQUENCE
	ret = ASN1_get_object(&p, &length, &tag, &xclass, asn1_len);
	if (tag != V_ASN1_SEQUENCE) {
		printf("Not a valid ASN.1 sequence at offset %ld\n", p - asn1_data);
		return;
	}
	printf("Outer SEQUENCE length: %ld\n", length);

	// 解析第一个INTEGER (X坐标)
	ret = ASN1_get_object(&p, &length, &tag, &xclass, p - asn1_data);
	if (tag != V_ASN1_INTEGER) {
		printf("Failed to parse X coordinate INTEGER at offset %ld\n", p - asn1_data);
		return;
	}
	printf("X coordinate INTEGER (%ld bytes): ", length);
	for (int i = 0; i < length; i++) printf("%02X", p[i]);
	printf("\n");
	p += length;

	// 解析第二个INTEGER (Y坐标)
	ret = ASN1_get_object(&p, &length, &tag, &xclass, p - asn1_data);
	if ( tag!= V_ASN1_INTEGER) {
		printf("Failed to parse Y coordinate INTEGER at offset %ld\n", p - asn1_data);
		return;
	}
	printf("Y coordinate INTEGER (%ld bytes): ", length);
	for (int i = 0; i < length; i++) printf("%02X", p[i]);
	printf("\n");
	p += length;

	// 解析OCTET STRING (哈希值)
	ret = ASN1_get_object(&p, &length, &tag, &xclass, p - asn1_data);
	if ( tag!= V_ASN1_OCTET_STRING) {
		printf("Failed to parse hash OCTET_STRING at offset %ld\n", p - asn1_data);
		return;
	}
	printf("Hash (%ld bytes): ", length);
	for (int i = 0; i < length; i++) printf("%02X", p[i]);
	printf("\n");
	p += length;

	// 解析最后一个OCTET STRING (实际密文)
	ret = ASN1_get_object(&p, &length, &tag, &xclass, p - asn1_data);
	if ( tag!= V_ASN1_OCTET_STRING) {
		printf("Failed to parse ciphertext OCTET_STRING at offset %ld\n", p - asn1_data);
		return;
	}
	printf("Actual ciphertext (%ld bytes): ", length);
	for (int i = 0; i < length; i++) printf("%02X", p[i]);
	printf("\n");

	printf("======================================\n\n");
}

int openssl_sm2_enc() {
	
	EVP_PKEY_CTX* pctx = NULL,* ectx=NULL;
	EVP_PKEY* pkey = NULL;
	char* message = "1234";
	int message_len = strlen(message);
	unsigned char* ciphertext=NULL,* plaintext=NULL;
	size_t ciphertext_len = 0, plaintext_len=0;
	int i = 0;

	// ========== 1. 生成 SM2 密钥对 ==========
	pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL);
	if (!pctx) {
		printf("EVP_PKEY_CTX_new_id failed\n");
		return -1;
	}

	if (EVP_PKEY_keygen_init(pctx) <= 0) {
		printf("EVP_PKEY_keygen_init failed\n");
		return -1;
	}

	if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
		printf("EVP_PKEY_keygen failed\n");
		return -1;
	}
	EVP_PKEY_CTX_free(pctx);
	pctx = NULL;
	printf("SM2 KeyPair generated successfully!\n");


	/* compute SM2 encryption */
	if (!(ectx = EVP_PKEY_CTX_new(pkey, NULL))) {
		goto clean_up;
	}
	if ((EVP_PKEY_encrypt_init(ectx)) != 1) {
		goto clean_up;
	}
	//预估缓冲区大小
	if ((EVP_PKEY_encrypt(ectx, NULL, &ciphertext_len, (unsigned char *)message, message_len)) != 1) {
		goto clean_up;
	}
	if (!(ciphertext = (unsigned char*)malloc(ciphertext_len))) {
		goto clean_up;
	}
	if ((EVP_PKEY_encrypt(ectx, ciphertext, &ciphertext_len, (unsigned char*)message, message_len)) != 1) {
		goto clean_up;
	}

	printf("Ciphertext length: %ld bytes.\n", ciphertext_len);
	printf("Ciphertext (ASN.1 encode):\n");
	for (i = 0; i < (int)ciphertext_len; i++) {
		printf("%02x", ciphertext[i]);
	}
	printf("\n\n");
	parse_your_sm2_ciphertext(ciphertext, ciphertext_len);

	/* compute SM2 decryption */
	if ((EVP_PKEY_decrypt_init(ectx)) != 1) {
		goto clean_up;
	}

	if ((EVP_PKEY_decrypt(ectx, NULL, &plaintext_len, ciphertext, ciphertext_len)) != 1) {
		goto clean_up;
	}

	if (!(plaintext = (unsigned char*)malloc(plaintext_len))) {
		goto clean_up;
	}

	if ((EVP_PKEY_decrypt(ectx, plaintext, &plaintext_len, ciphertext, ciphertext_len)) != 1) {
		goto clean_up;
	}

	printf("Decrypted plaintext length: %ld bytes.\n", plaintext_len);
	printf("Decrypted plaintext:\n");
	for (i = 0; i < (int)plaintext_len; i++) {
		printf("0x%x  ", plaintext[i]);
	}
	printf("\n\n");

	if (plaintext_len != message_len) {
		printf("Decrypted data length error!\n");
		goto clean_up;
	}

	if (memcmp(plaintext, message, message_len)) {
		printf("Decrypt data failed!\n");
		goto clean_up;
	}
	else {
		printf("Encrypt and decrypt data succeeded!\n");
	}
clean_up:

	if (pctx) {
		EVP_PKEY_CTX_free(pctx);
	}
	if (pkey) {
		EVP_PKEY_free(pkey);
	}

	if (ectx) {
		EVP_PKEY_CTX_free(ectx);
	}
	if (ciphertext) {
		free(ciphertext);
	}
	if (plaintext) {
		free(plaintext);
	}

	return 0;


}

image

posted @ 2025-09-11 10:41  我不是萧海哇~~~  阅读(31)  评论(0)    收藏  举报