#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);// 解析外层SEQUENCEret = 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;}
