#include <iostream>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <cstring>
int main() {
    // 初始化 OpenSSL 库
    OpenSSL_add_all_algorithms();

    // 从文件中读取公钥
    FILE* pubKeyFile = fopen("public_key.pem", "rb");
    EVP_PKEY* publicKey = PEM_read_PUBKEY(pubKeyFile, NULL, NULL, NULL);

    if (!publicKey) {
           std::cerr << "Error reading public key." << std::endl;
           fclose(pubKeyFile);
           return 1;
    }
    fclose(pubKeyFile);

    // 待加密的明文
    const unsigned char plaintext[] = "Hello, ECC Encryption!";
    size_t plaintext_len = strlen((const char*)plaintext);

    // 获取密文的长度
    size_t encrypted_text_len;
    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(publicKey, NULL);
    if(nullptr == ctx){
        std::cerr << "ctx failed."<< std::endl;
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(publicKey);
        return 1;
    }
    int res = EVP_PKEY_encrypt_init(ctx);
    if (res <= 0) {
        char error_buf[256];
        ERR_error_string_n(ERR_get_error(), error_buf, sizeof(error_buf));
        std::cerr << "EVP_PKEY_encrypt_init failed: " << error_buf <<",res="<< res << std::endl;
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(publicKey);
        return 1;
    }
    int ret  = EVP_PKEY_encrypt(ctx, NULL, &encrypted_text_len, plaintext, plaintext_len);
    if (ret <= 0) {
        char error_buf[256];
        ERR_error_string_n(ERR_get_error(), error_buf, sizeof(error_buf));
        std::cerr << "Encryption failed: " << error_buf <<",ret="<< ret << std::endl;
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(publicKey);
        return 1;
    }
    // 分配内存存储加密后的数据
    unsigned char *encrypted_text = (unsigned char *)malloc(encrypted_text_len);
    if (encrypted_text == NULL) {
        std::cerr << "Memory allocation failed." << std::endl;
        EVP_PKEY_free(publicKey);
        return 1;
    }

    // 使用 ECC 公钥进行加密

    EVP_PKEY_encrypt_init(ctx);
    if (EVP_PKEY_encrypt(ctx, encrypted_text, &plaintext_len, plaintext, plaintext_len) <= 0) {
        std::cerr << "Encryption failed." << std::endl;
        free(encrypted_text);
        EVP_PKEY_CTX_free(ctx);
        EVP_PKEY_free(publicKey);
        return 1;
    }
    EVP_PKEY_CTX_free(ctx);

    // 输出加密后的数据
    std::cout << "Encrypted Text: ";
    for (int i = 0; i < encrypted_text_len; i++) {
        printf("%02x", encrypted_text[i]);
    }
    std::cout << std::endl;

    // 释放资源
    free(encrypted_text);
    EVP_PKEY_free(publicKey);

    // 清理 OpenSSL 库
    EVP_cleanup();

    return 0;
}
