// #ifdef USE_REAL_HEADERS
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/obj_mac.h>

/* =============================================================================
 * UTILITY FUNCTIONS - Common operations shared across signature APIs
 * =============================================================================
 */

/**
 * Create message digest from raw message data
 */
static int create_digest(const unsigned char *message, size_t message_len,
                        const EVP_MD *md, unsigned char *digest, unsigned int *digest_len) {
    EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
    int ret = 0;
    
    if (!md_ctx || 
        EVP_DigestInit_ex(md_ctx, md, NULL) != 1 ||
        EVP_DigestUpdate(md_ctx, message, message_len) != 1 ||
        EVP_DigestFinal_ex(md_ctx, digest, digest_len) != 1) {
        goto cleanup;
    }
    ret = 1;

cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/**
 * Allocate signature buffer with appropriate size
 */
static unsigned char* allocate_signature_buffer(size_t *sig_len, const EVP_PKEY *pkey) {
    *sig_len = EVP_PKEY_size(pkey);
    return OPENSSL_malloc(*sig_len);
}

/**
 * Helper to extract key from EVP_PKEY
 */
static RSA* get_rsa_from_pkey(EVP_PKEY *pkey) {
    return EVP_PKEY_get1_RSA(pkey);
}

static DSA* get_dsa_from_pkey(EVP_PKEY *pkey) {
    return EVP_PKEY_get1_DSA(pkey);
}

/* =============================================================================
 * EVP_SIGN/VERIFY API - Legacy high-level API (older, simpler)
 * =============================================================================
 */

/**
 * Sign message using EVP_Sign API (legacy)
 * Simple API with built-in hashing and signing
 */
int sign_using_evp_sign(const unsigned char *message, size_t message_len,
                        unsigned char **signature, size_t *signature_len,
                        EVP_PKEY *pkey, const EVP_MD *md) {
    EVP_MD_CTX *md_ctx = NULL;
    unsigned int sig_len = 0;
    int ret = 0;
    
    if (!(md_ctx = EVP_MD_CTX_new()) ||
        EVP_SignInit(md_ctx, md) != 1 ||
        EVP_SignUpdate(md_ctx, message, message_len) != 1) {
        goto cleanup;
    }

    // more updates
    EVP_SignUpdate(md_ctx, message+1, message_len-1);
    
    *signature = allocate_signature_buffer(signature_len, pkey);
    if (!*signature) goto cleanup;
    
    if (EVP_SignFinal(md_ctx, *signature, &sig_len, pkey) == 1) {
        *signature_len = sig_len;
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/**
 * Verify signature using EVP_Verify API (legacy)
 * Simple API with built-in hashing and verification
 */
int verify_using_evp_verify(const unsigned char *message, size_t message_len,
                           const unsigned char *signature, size_t signature_len,
                           EVP_PKEY *pkey, const EVP_MD *md) {
    EVP_MD_CTX *md_ctx = NULL;
    int ret = 0;
    
    if (!(md_ctx = EVP_MD_CTX_new()) ||
        EVP_VerifyInit(md_ctx, md) != 1 ||
        EVP_VerifyUpdate(md_ctx, message, message_len) != 1 ||
        EVP_VerifyUpdate(md_ctx, message+1, message_len-1) != 1 ||
        EVP_VerifyFinal(md_ctx, signature, (unsigned int)signature_len, pkey) != 1) {
        goto cleanup;
    }
    ret = 1;
    
cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/* =============================================================================
 * EVP_DIGESTSIGN/DIGESTVERIFY API - Modern recommended API 
 * =============================================================================
 */

/**
 * Sign message using EVP_DigestSign API (recommended)
 * Modern flexible API with better algorithm support
 */
int sign_using_evp_digestsign(const unsigned char *message, size_t message_len,
                              unsigned char **signature, size_t *signature_len,
                              EVP_PKEY *pkey, const EVP_MD *md) {
    EVP_MD_CTX *md_ctx = NULL;
    int ret = 0;
    
    if (!(md_ctx = EVP_MD_CTX_new()) ||
        EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1 ||
        EVP_DigestSignUpdate(md_ctx, message, message_len) != 1 ||
        EVP_DigestSignFinal(md_ctx, NULL, signature_len) != 1) {
        goto cleanup;
    }
    
    *signature = OPENSSL_malloc(*signature_len);
    if (!*signature) goto cleanup;
    
    if (EVP_DigestSignFinal(md_ctx, *signature, signature_len) == 1) {
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/**
 * Verify signature using EVP_DigestVerify API (recommended)
 * Modern flexible API with better algorithm support
 */
int verify_using_evp_digestverify(const unsigned char *message, size_t message_len,
                                 const unsigned char *signature, size_t signature_len,
                                 EVP_PKEY *pkey, const EVP_MD *md) {
    EVP_MD_CTX *md_ctx = NULL;
    int ret = 0;
    
    if (!(md_ctx = EVP_MD_CTX_new()) ||
        EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, pkey) != 1 ||
        EVP_DigestVerifyUpdate(md_ctx, message, message_len) != 1 ||
        EVP_DigestVerifyFinal(md_ctx, signature, signature_len) != 1) {
        goto cleanup;
    }
    ret = 1;
    
cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/**
 * Sign with explicit PKEY_CTX for fine-grained parameter control
 * Allows custom parameter settings (e.g., padding, salt length)
 */
int sign_using_digestsign_with_ctx(const unsigned char *message, size_t message_len,
                                  unsigned char **signature, size_t *signature_len,
                                  EVP_PKEY *pkey, const EVP_MD *md, 
                                  int (*param_setter)(EVP_PKEY_CTX *ctx)) {
    EVP_MD_CTX *md_ctx = NULL;
    EVP_PKEY_CTX *pkey_ctx = NULL;
    int ret = 0;
    
    if (!(md_ctx = EVP_MD_CTX_new()) ||
        EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) {
        goto cleanup;
    }
    
    if (param_setter && param_setter(pkey_ctx) != 1) goto cleanup;
    
    if (EVP_DigestSignUpdate(md_ctx, message, message_len) != 1 ||
        EVP_DigestSignFinal(md_ctx, NULL, signature_len) != 1) {
        goto cleanup;
    }
    
    *signature = OPENSSL_malloc(*signature_len);
    if (!*signature) goto cleanup;
    
    if (EVP_DigestSignFinal(md_ctx, *signature, signature_len) == 1) {
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/**
 * Verify with explicit PKEY_CTX for fine-grained parameter control
 */
int verify_using_digestverify_with_ctx(const unsigned char *message, size_t message_len,
                                      const unsigned char *signature, size_t signature_len,
                                      EVP_PKEY *pkey, const EVP_MD *md,
                                      int (*param_setter)(EVP_PKEY_CTX *ctx)) {
    EVP_MD_CTX *md_ctx = NULL;
    EVP_PKEY_CTX *pkey_ctx = NULL;
    int ret = 0;
    
    if (!(md_ctx = EVP_MD_CTX_new()) ||
        EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) {
        goto cleanup;
    }
    
    if (param_setter && param_setter(pkey_ctx) != 1) goto cleanup;
    
    if (EVP_DigestVerifyUpdate(md_ctx, message, message_len) != 1 ||
        EVP_DigestVerifyFinal(md_ctx, signature, signature_len) != 1) {
        goto cleanup;
    }
    ret = 1;
    
cleanup:
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

/* =============================================================================
 * EVP_PKEY_SIGN/VERIFY API - Lower level API with pre-hashed input
 * =============================================================================
 */

/**
 * Sign pre-hashed digest using EVP_PKEY_sign API
 * Lower-level API requiring pre-computed digest
 */
int sign_using_evp_pkey_sign(const unsigned char *digest, size_t digest_len,
                             unsigned char **signature, size_t *signature_len,
                             EVP_PKEY *pkey, const EVP_MD *md) {
    EVP_PKEY_CTX *pkey_ctx = NULL;
    int ret = 0;
    
    if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) ||
        EVP_PKEY_sign_init(pkey_ctx) != 1 ||
        EVP_PKEY_CTX_set_signature_md(pkey_ctx, md) != 1 ||
        EVP_PKEY_sign(pkey_ctx, NULL, signature_len, digest, digest_len) != 1) {
        goto cleanup;
    }
    
    *signature = OPENSSL_malloc(*signature_len);
    if (!*signature) goto cleanup;
    
    if (EVP_PKEY_sign(pkey_ctx, *signature, signature_len, digest, digest_len) == 1) {
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
cleanup:
    EVP_PKEY_CTX_free(pkey_ctx);
    return ret;
}

/**
 * Verify pre-hashed digest using EVP_PKEY_verify API
 * Lower-level API requiring pre-computed digest
 */
int verify_using_evp_pkey_verify(const unsigned char *digest, size_t digest_len,
                                const unsigned char *signature, size_t signature_len,
                                EVP_PKEY *pkey, const EVP_MD *md) {
    EVP_PKEY_CTX *pkey_ctx = NULL;
    int ret = 0;
    
    if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) ||
        EVP_PKEY_verify_init(pkey_ctx) != 1 ||
        EVP_PKEY_CTX_set_signature_md(pkey_ctx, md) != 1 ||
        EVP_PKEY_verify(pkey_ctx, signature, signature_len, digest, digest_len) != 1) {
        goto cleanup;
    }
    ret = 1;
    
cleanup:
    EVP_PKEY_CTX_free(pkey_ctx);
    return ret;
}

/* =============================================================================
 * EVP_PKEY_SIGN_MESSAGE API - Streamlined message signing
 * =============================================================================
 */

/**
 * Sign message using EVP_PKEY_sign_message API
 * Streamlined interface for direct message signing
 */
int sign_using_evp_pkey_sign_message(const unsigned char *message, size_t message_len,
                                     unsigned char **signature, size_t *signature_len,
                                     EVP_PKEY *pkey, const EVP_MD *md, const char *alg_name) {
    EVP_PKEY_CTX *pkey_ctx = NULL;
    EVP_SIGNATURE *alg = NULL;
    int ret = 0;

    if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto cleanup;
    
    alg = EVP_SIGNATURE_fetch(NULL, alg_name, NULL);
    
    if (EVP_PKEY_sign_message_init(pkey_ctx, alg, NULL) != 1 ||
        EVP_PKEY_sign_message_update(pkey_ctx, message, message_len) != 1 ||
        EVP_PKEY_sign_message_final(pkey_ctx, NULL, signature_len) != 1) {
        goto cleanup;
    }
    
    *signature = OPENSSL_malloc(*signature_len);
    if (!*signature) goto cleanup;
    
    if (EVP_PKEY_sign_message_final(pkey_ctx, *signature, signature_len) == 1) {
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
cleanup:
    EVP_PKEY_CTX_free(pkey_ctx);
    return ret;
}

/**
 * Verify message using EVP_PKEY_verify_message API
 * Streamlined interface for direct message verification
 */
int verify_using_evp_pkey_verify_message(const unsigned char *message, size_t message_len,
                                        const unsigned char *signature, size_t signature_len,
                                        EVP_PKEY *pkey, const EVP_MD *md, const char *alg_name) {
    EVP_PKEY_CTX *pkey_ctx = NULL;
    EVP_SIGNATURE *alg = NULL;
    int ret = 0;

    if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto cleanup;
    
    alg = EVP_SIGNATURE_fetch(NULL, alg_name, NULL);
    
    if (EVP_PKEY_verify_message_init(pkey_ctx, alg, NULL) != 1) goto cleanup;
    
    EVP_PKEY_CTX_set_signature(pkey_ctx, signature, signature_len);
    
    if (EVP_PKEY_verify_message_update(pkey_ctx, message, message_len) != 1 ||
        EVP_PKEY_verify_message_final(pkey_ctx) != 1) {
        goto cleanup;
    }
    ret = 1;
    
cleanup:
    EVP_PKEY_CTX_free(pkey_ctx);
    return ret;
}

/* =============================================================================
 * LOW-LEVEL RSA API - Algorithm-specific functions (deprecated)
 * =============================================================================
 */

/**
 * Sign using low-level RSA_sign API (deprecated, RSA-only)
 * Direct RSA signing with manual digest computation
 */
int sign_using_rsa_sign(const unsigned char *message, size_t message_len,
                       unsigned char **signature, size_t *signature_len,
                       RSA *rsa_key, int hash_nid, const EVP_MD *md) {
    unsigned char digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    int ret = 0;
    
    if (!create_digest(message, message_len, md, digest, &digest_len)) return 0;
    
    *signature_len = RSA_size(rsa_key);
    *signature = OPENSSL_malloc(*signature_len);
    if (!*signature) return 0;
    
    if (RSA_sign(hash_nid, digest, digest_len, *signature, 
                 (unsigned int*)signature_len, rsa_key) == 1) {
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
    return ret;
}

/**
 * Verify using low-level RSA_verify API (deprecated, RSA-only)
 * Direct RSA verification with manual digest computation
 */
int verify_using_rsa_verify(const unsigned char *message, size_t message_len,
                           const unsigned char *signature, size_t signature_len,
                           RSA *rsa_key, int hash_nid, const EVP_MD *md) {
    unsigned char digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    
    if (!create_digest(message, message_len, md, digest, &digest_len)) return 0;
    
    return RSA_verify(hash_nid, digest, digest_len, signature, 
                     (unsigned int)signature_len, rsa_key);
}

/* =============================================================================
 * LOW-LEVEL DSA API - Algorithm-specific functions (deprecated)
 * =============================================================================
 */

/**
 * Sign using low-level DSA_do_sign API (deprecated, DSA-only)
 * Direct DSA signing with manual digest and signature encoding
 */
int sign_using_dsa_sign(const unsigned char *message, size_t message_len,
                       unsigned char **signature, size_t *signature_len,
                       DSA *dsa_key, const EVP_MD *md) {
    unsigned char digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    DSA_SIG *sig = NULL;
    const BIGNUM *r = NULL, *s = NULL;
    unsigned int bn_len;
    int ret = 0;
    
    if (!create_digest(message, message_len, md, digest, &digest_len)) return 0;
    
    sig = DSA_do_sign(digest, digest_len, dsa_key);
    if (!sig) return 0;
    
    DSA_SIG_get0(sig, &r, &s);
    if (!r || !s) goto cleanup;
    
    bn_len = DSA_size(dsa_key) / 2;
    *signature_len = DSA_size(dsa_key);
    *signature = OPENSSL_malloc(*signature_len);
    if (!*signature) goto cleanup;
    
    memset(*signature, 0, *signature_len);
    
    if (BN_bn2bin(r, *signature + (bn_len - BN_num_bytes(r))) > 0 &&
        BN_bn2bin(s, *signature + bn_len + (bn_len - BN_num_bytes(s))) > 0) {
        ret = 1;
    } else {
        OPENSSL_free(*signature);
        *signature = NULL;
    }
    
cleanup:
    DSA_SIG_free(sig);
    return ret;
}

/**
 * Verify using low-level DSA_do_verify API (deprecated, DSA-only)
 * Direct DSA verification with manual digest and signature decoding
 */
int verify_using_dsa_verify(const unsigned char *message, size_t message_len,
                           const unsigned char *signature, size_t signature_len,
                           DSA *dsa_key, const EVP_MD *md) {
    unsigned char digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    DSA_SIG *sig = NULL;
    BIGNUM *r = NULL, *s = NULL;
    unsigned int bn_len;
    int ret = 0;
    
    if (!create_digest(message, message_len, md, digest, &digest_len)) return 0;
    
    sig = DSA_SIG_new();
    if (!sig) return 0;
    
    r = BN_new();
    s = BN_new();
    if (!r || !s) goto cleanup;
    
    bn_len = DSA_size(dsa_key) / 2;
    
    if (BN_bin2bn(signature, bn_len, r) &&
        BN_bin2bn(signature + bn_len, bn_len, s) &&
        DSA_SIG_set0(sig, r, s) == 1) {
        /* r and s are now owned by sig */
        r = s = NULL;
        ret = DSA_do_verify(digest, digest_len, sig, dsa_key);
    }
    
cleanup:
    DSA_SIG_free(sig);
    BN_free(r);
    BN_free(s);
    return (ret == 1);
}

/* =============================================================================
 * PARAMETER SETTERS - Helper functions for algorithm configuration
 * =============================================================================
 */

/**
 * Set RSA PSS padding mode
 */
int set_rsa_pss_padding(EVP_PKEY_CTX *ctx) {
    return EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING);
}

/**
 * No-op parameter setter for default behavior
 */
int no_parameter_setter(EVP_PKEY_CTX *ctx) {
    return 1;
}

/* =============================================================================
 * KEY GENERATION HELPERS
 * =============================================================================
 */

/**
 * Generate RSA key pair for testing
 */
static EVP_PKEY* generate_rsa_key(void) {
    EVP_PKEY_CTX *key_ctx = NULL;
    EVP_PKEY *key = NULL;
    
    key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    if (!key_ctx) return NULL;
    
    if (EVP_PKEY_keygen_init(key_ctx) <= 0 ||
        EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 ||
        EVP_PKEY_keygen(key_ctx, &key) <= 0) {
        EVP_PKEY_free(key);
        key = NULL;
    }
    
    EVP_PKEY_CTX_free(key_ctx);
    return key;
}

/**
 * Generate DSA key pair for testing
 */
static EVP_PKEY* generate_dsa_key(void) {
    EVP_PKEY_CTX *param_ctx = NULL, *key_ctx = NULL;
    EVP_PKEY *params = NULL, *key = NULL;
    
    /* Generate parameters first */
    param_ctx = EVP_PKEY_CTX_new_from_name(NULL, "dsa", NULL);
    if (!param_ctx) return NULL;
    
    if (EVP_PKEY_paramgen_init(param_ctx) <= 0 ||
        EVP_PKEY_CTX_set_dsa_paramgen_bits(param_ctx, 2048) <= 0 ||
        EVP_PKEY_paramgen(param_ctx, &params) <= 0) {
        goto cleanup;
    }
    
    /* Generate key using parameters */
    key_ctx = EVP_PKEY_CTX_new(params, NULL);
    if (!key_ctx ||
        EVP_PKEY_keygen_init(key_ctx) <= 0 ||
        EVP_PKEY_keygen(key_ctx, &key) <= 0) {
        EVP_PKEY_free(key);
        key = NULL;
    }
    
cleanup:
    EVP_PKEY_CTX_free(param_ctx);
    EVP_PKEY_CTX_free(key_ctx);
    EVP_PKEY_free(params);
    return key;
}

/* =============================================================================
 * TEST FUNCTIONS - Comprehensive API testing
 * =============================================================================
 */

/**
 * Test all signature APIs with a given key and algorithm
 * Demonstrates the 6 different signature API approaches
 */
int test_signature_apis(EVP_PKEY *key, const EVP_MD *md, 
                       int (*param_setter)(EVP_PKEY_CTX *ctx),
                       const char *algo_name) {
    const unsigned char message[] = "Test message for OpenSSL signature APIs";
    const size_t message_len = strlen((char *)message);
    
    unsigned char *sig1 = NULL, *sig2 = NULL, *sig3 = NULL, 
                  *sig4 = NULL, *sig6 = NULL;
    size_t sig_len1 = 0, sig_len2 = 0, sig_len3 = 0, sig_len4 = 0, sig_len6 = 0;
    
    unsigned char digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    int success = 1;
    
    printf("\nTesting signature APIs with %s:\n", algo_name);
    
    /* Test 1: EVP_Sign API */
    printf("1. EVP_Sign API: ");
    if (sign_using_evp_sign(message, message_len, &sig1, &sig_len1, key, md) &&
        verify_using_evp_verify(message, message_len, sig1, sig_len1, key, md)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    /* Test 2: EVP_DigestSign API */
    printf("2. EVP_DigestSign API: ");
    if (sign_using_evp_digestsign(message, message_len, &sig2, &sig_len2, key, md) &&
        verify_using_evp_digestverify(message, message_len, sig2, sig_len2, key, md)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    /* Test 3: EVP_PKEY_sign API (requires pre-hashed input) */
    printf("3. EVP_PKEY_sign API: ");
    if (create_digest(message, message_len, md, digest, &digest_len) &&
        sign_using_evp_pkey_sign(digest, digest_len, &sig3, &sig_len3, key, md) &&
        verify_using_evp_pkey_verify(digest, digest_len, sig3, sig_len3, key, md)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    /* Test 4: EVP_DigestSign with explicit PKEY_CTX */
    printf("4. EVP_DigestSign with explicit PKEY_CTX: ");
    if (sign_using_digestsign_with_ctx(message, message_len, &sig4, &sig_len4, 
                                      key, md, param_setter) &&
        verify_using_digestverify_with_ctx(message, message_len, sig4, sig_len4, 
                                          key, md, param_setter)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    /* Test 6: EVP_PKEY_sign_message API */
    printf("6. EVP_PKEY_sign_message API: ");
    if (sign_using_evp_pkey_sign_message(message, message_len, &sig6, &sig_len6, key, md, algo_name) &&
        verify_using_evp_pkey_verify_message(message, message_len, sig6, sig_len6, key, md, algo_name)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    /* Cleanup */
    OPENSSL_free(sig1);
    OPENSSL_free(sig2);
    OPENSSL_free(sig3);
    OPENSSL_free(sig4);
    OPENSSL_free(sig6);
    
    return success;
}

/**
 * Test RSA-specific signature APIs including low-level RSA functions
 */
int test_signature_apis_rsa(void) {
    EVP_PKEY *key = NULL;
    RSA *rsa_key = NULL;
    const EVP_MD *md = EVP_sha256();
    const unsigned char message[] = "Test message for OpenSSL signature APIs";
    const size_t message_len = strlen((char *)message);
    unsigned char *sig5 = NULL;
    size_t sig_len5 = 0;
    int success = 1;
    
    printf("\nGenerating RSA key pair...\n");
    key = generate_rsa_key();
    if (!key) return 0;
    
    rsa_key = get_rsa_from_pkey(key);
    if (!rsa_key) {
        EVP_PKEY_free(key);
        return 0;
    }
    
    /* Test generic APIs */
    if (!test_signature_apis(key, md, set_rsa_pss_padding, "RSA-SHA256")) {
        success = 0;
    }
    
    /* Test 5: Low-level RSA API */
    printf("5. Low-level RSA API: ");
    if (sign_using_rsa_sign(message, message_len, &sig5, &sig_len5, 
                           rsa_key, NID_sha256, md) &&
        verify_using_rsa_verify(message, message_len, sig5, sig_len5, 
                               rsa_key, NID_sha256, md)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    printf("\nRSA API Summary:\n");
    printf("1. EVP_Sign API: Legacy, simple\n");
    printf("2. EVP_DigestSign API: Modern, recommended\n");
    printf("3. EVP_PKEY_sign API: Lower-level, pre-hashed input\n");
    printf("4. EVP_DigestSign with PKEY_CTX: Fine-grained control\n");
    printf("5. Low-level RSA API: Deprecated, algorithm-specific\n");
    printf("6. EVP_PKEY_sign_message API: Streamlined message signing\n");
    
    /* Cleanup */
    OPENSSL_free(sig5);
    RSA_free(rsa_key);
    EVP_PKEY_free(key);
    
    return success;
}

/**
 * Test DSA-specific signature APIs including low-level DSA functions
 */
int test_signature_apis_dsa(void) {
    EVP_PKEY *key = NULL;
    DSA *dsa_key = NULL;
    const EVP_MD *md = EVP_sha256();
    const unsigned char message[] = "Test message for OpenSSL signature APIs";
    const size_t message_len = strlen((char *)message);
    unsigned char *sig5 = NULL;
    size_t sig_len5 = 0;
    int success = 1;
    
    printf("\nGenerating DSA key pair...\n");
    key = generate_dsa_key();
    if (!key) return 0;
    
    dsa_key = get_dsa_from_pkey(key);
    if (!dsa_key) {
        EVP_PKEY_free(key);
        return 0;
    }
    
    /* Test generic APIs */
    if (!test_signature_apis(key, md, no_parameter_setter, "dsa")) {
        success = 0;
    }
    
    /* Test 5: Low-level DSA API */
    printf("5. Low-level DSA API: ");
    if (sign_using_dsa_sign(message, message_len, &sig5, &sig_len5, dsa_key, md) &&
        verify_using_dsa_verify(message, message_len, sig5, sig_len5, dsa_key, md)) {
        printf("PASS\n");
    } else {
        printf("FAIL\n");
        success = 0;
    }
    
    printf("\nDSA API Summary:\n");
    printf("1. EVP_Sign API: Legacy, simple\n");
    printf("2. EVP_DigestSign API: Modern, recommended\n");
    printf("3. EVP_PKEY_sign API: Lower-level, pre-hashed input\n");
    printf("4. EVP_DigestSign with PKEY_CTX: Fine-grained control\n");
    printf("5. Low-level DSA API: Deprecated, algorithm-specific\n");
    printf("6. EVP_PKEY_sign_message API: Streamlined message signing\n");
    
    /* Cleanup */
    OPENSSL_free(sig5);
    EVP_PKEY_free(key);
    
    return success;
}

/* =============================================================================
 * MAIN FUNCTION - Entry point for testing all signature APIs
 * =============================================================================
 */

// /**
//  * Main function demonstrating all OpenSSL signature APIs
//  * Tests both RSA and DSA algorithms with all 6 API approaches
//  */
// int main(void) {
//     /* Initialize OpenSSL */
//     OpenSSL_add_all_algorithms();
//     ERR_load_crypto_strings();
    
//     printf("=================================================================\n");
//     printf("OpenSSL Signature API Demonstration\n");
//     printf("=================================================================\n");
    
//     printf("\n-------- TESTING RSA SIGNATURES --------\n");
//     int rsa_result = test_signature_apis_rsa();
    
//     printf("\n-------- TESTING DSA SIGNATURES --------\n");
//     int dsa_result = test_signature_apis_dsa();
    
//     printf("\n=================================================================\n");
//     if (rsa_result && dsa_result) {
//         printf("All tests completed successfully.\n");
//         return 0;
//     } else {
//         printf("Some tests failed.\n");
//         return 1;
//     }
// }