0

I have written this C code for creating an es384 signature with sha 384 which I will base 64 encode and use to create a JWT. But for some reason, the signature is not correct and I have no clue why

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>
#include <json-c/json.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/hmac.h>


int generate_ecdsa_signature(FILE *private_key_file, const unsigned char *data,unsigned char **signature1, size_t data_len) {
    // Load private key
    //
    unsigned char hash[EVP_MAX_MD_SIZE];
    printf("2\n");
    EVP_MD_CTX mdctx;

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, EVP_sha384(), NULL);
    EVP_DigestUpdate(&mdctx, data, data_len);
    EVP_DigestFinal_ex(&mdctx, hash, NULL);
    EVP_MD_CTX_cleanup(&mdctx);
    printf("HASH : \n");
    for (unsigned int i = 0; i < strlen(hash); i++) {
        printf("%02x", hash[i]);
    }
    printf("\n");
    EC_KEY *ec_key = PEM_read_ECPrivateKey(private_key_file, NULL, NULL, NULL);
    fclose(private_key_file);
    if (!ec_key) {
        ERR_print_errors_fp(stderr);
        return NULL;
    }
    ECDSA_SIG *signature = ECDSA_do_sign(hash, strlen(hash), ec_key);
    if (!signature) {
        ERR_print_errors_fp(stderr);
        EC_KEY_free(ec_key);
        return NULL;
    }

    FILE *pubKeyFile = fopen("public_key.pem", "r");
    if (!pubKeyFile) {
        perror("Error opening public key file");
        return 1;
    }

    EC_KEY *ecKey = EC_KEY_new_by_curve_name(NID_secp384r1);
    if (!ecKey) {
        perror("Error creating EC key");
        fclose(pubKeyFile);
        return 1;
    }

    if (!PEM_read_EC_PUBKEY(pubKeyFile, &ecKey, NULL, NULL)) {
        perror("Error reading public key");
        EC_KEY_free(ecKey);
        fclose(pubKeyFile);
        return 1;
    }
    int verify_status = ECDSA_do_verify(hash, strlen(hash), signature, ecKey);
    const int verify_success = 1;
    if (verify_success != verify_status)
     {
          printf("Failed to verify EC Signature\n");
                            //function_status = -1;
     }
    else if(verify_status==1)
     {
          printf("Verifed EC Signature\n");
                            //function_status = 1;
     }
    else{
          printf("Failed verification!\n");
     }
    // Convert signature to DER format
    unsigned char *der_signature = NULL;
    int der_length = i2d_ECDSA_SIG(signature, &der_signature);
    if (der_length <= 0) {
        ERR_print_errors_fp(stderr);
        EC_KEY_free(ec_key);
           return NULL;
    }
    //verify_ecds(hash,der_signature);
    printf("SIGNATURE : \n");
    for (unsigned int i = 0; i < strlen(der_signature); i++) {
        printf("%02x", der_signature[i]);
    }
    printf("\n");
    *signature1=calloc(strlen(der_signature)+1,1);
    memset(*signature1,0,strlen(der_signature)+1);
    memcpy(*signature1,der_signature,strlen(der_signature));

    // Clean up resources
    //BIO_free_all(bio_b64);
    EC_KEY_free(ec_key);
    ECDSA_SIG_free(signature);
    return 1;
}

I tried to verify this code with the public key stored as .pem and after several attempts, it shows verified but until that it shows failed to verify.

 if (!PEM_read_EC_PUBKEY(pubKeyFile, &ecKey, NULL, NULL)) {
        perror("Error reading public key");
        EC_KEY_free(ecKey);
        fclose(pubKeyFile);
        iReturnVal=0;
        goto FREE_AND_RETURN;
    }
    fclose(pubKeyFile);        //int verify_status;int signature_der_length;const int verify_success;
    verify_status = ECDSA_do_verify(hash, strlen(hash), signature, ecKey);
    verify_success = 1;
    if (verify_success != verify_status)
     {
          printf("Failed to verify EC Signature\n");
          iReturnVal=0;
          goto FREE_AND_RETURN;
                            //function_status = -1;
     }
    else if(verify_status==1)
     {
          printf("Verifed EC Signature\n");
                            //function_status = 1;
     }
    else{
          printf("Failed verification!\n");
          iReturnVal=0;
          goto FREE_AND_RETURN;
     }
    // Convert signature to DER format
FREE_AND_RETURN:
    return iReturnVal;

}

This is the output of the generate_ecdsa_signature function. HASH : db479c1c0ac587e447465c6c23e4bc4f243274b4c040fb89eccdfe6b84e9f44589d728913b231e530559f0a457e9120d5a Verifed EC Signature SIGNATURE : 306402303657bd986acffa4eccda51c3370a980af890c290a1bd61d0479195769e5740ad5a7a755feb69d223c4ddc24cd674a0bb02300a1d20051f5798a697cc717fb67030eb9badc0051773dc3fcab44ce7ac7bf70847fac8c09777d33dd94bb268198fdc74

pmacfarlane
  • 3,057
  • 1
  • 7
  • 24

0 Answers0