#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;
}
