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