lundi 4 septembre 2023

Signature verifies in openssl command line but not c++ code

I am writing a C++ code using openssl api's to perform the following function

openssl dgst -sha256 -verify public_key.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -signature signature.sig sw-description

Following is the C++ Code I have attempted

#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/types.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>

bool verify_signature(const std::string& signature_file, const std::string& public_key_file, const std::string& data_file)
{
    // Read the signature file
    std::ifstream sig_file(signature_file, std::ios::binary);
    if (!sig_file.is_open()) {
        std::cerr << "Failed to open signature file: " << signature_file << std::endl;
        return false;
    }
    std::vector<unsigned char> signature((std::istreambuf_iterator<char>(sig_file)), std::istreambuf_iterator<char>());
    sig_file.close();

    
     BIO* publicKeyBio = BIO_new_file(public_key_file.c_str(), "rb");
    if (!publicKeyBio) {
        perror("Failed to open public key file");
        return false;
    }
    EVP_PKEY* pkey = PEM_read_bio_PUBKEY(publicKeyBio, nullptr, nullptr, nullptr);
   
    if (!pkey) {
        ERR_print_errors_fp(stderr);
         std::cout<<"22";
        return false;
    }
    
    
    // Read the data file
    std::ifstream data_file_stream(data_file, std::ios::binary);
    if (!data_file_stream.is_open()) {
        std::cerr << "Failed to open data file: " << data_file << std::endl;
        
        return false;
    }
    std::vector<unsigned char> data((std::istreambuf_iterator<char>(data_file_stream)), std::istreambuf_iterator<char>());
    data_file_stream.close();

    // Create a digest of the data using SHA-256
    EVP_MD_CTX* md_ctx = EVP_MD_CTX_new();
    if (!md_ctx) {
        std::cerr << "Failed to create message digest context" << std::endl;
       
        return false;
    }
    if (EVP_DigestInit_ex(md_ctx, EVP_sha256(), nullptr) != 1) {
        std::cerr << "Failed to initialize message digest context" << std::endl;
        EVP_MD_CTX_free(md_ctx);
      
        return false;
    }
    if (EVP_DigestUpdate(md_ctx, data.data(), data.size()) != 1) {
        std::cerr << "Failed to update message digest" << std::endl;
        EVP_MD_CTX_free(md_ctx);
      
        return false;
    }
    unsigned char digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    if (EVP_DigestFinal_ex(md_ctx, digest, &digest_len) != 1) {
        std::cerr << "Failed to finalize message digest" << std::endl;
        EVP_MD_CTX_free(md_ctx);
      
        return false;
    }
    
    
    EVP_MD_CTX_free(md_ctx);

    // Verify the signature using the public key and PSS padding scheme
   
    EVP_MD_CTX* verify_ctx = EVP_MD_CTX_new();
    if (!verify_ctx) {
        std::cerr << "Failed to create signature verification context" << std::endl;
        EVP_PKEY_free(pkey);
       
        return false;
    }
    if (EVP_DigestVerifyInit(verify_ctx, nullptr, EVP_sha256(), nullptr, pkey) != 1) {
        std::cerr << "Failed to initialize signature verification context" << std::endl;
        EVP_MD_CTX_free(verify_ctx);
        EVP_PKEY_free(pkey);
       
        return false;
    }
    if (EVP_PKEY_CTX_set_rsa_padding(EVP_MD_CTX_pkey_ctx(verify_ctx), RSA_PKCS1_PSS_PADDING) <= 0) {
        std::cerr << "Failed to set RSA-PSS padding in signature verification context" << std::endl;
        EVP_MD_CTX_free(verify_ctx);
        EVP_PKEY_free(pkey);
       
        return false;
    }
    if (EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_MD_CTX_pkey_ctx(verify_ctx), -1) <= 0) {
        std::cerr << "Failed to set RSA-PSS salt length in signature verification context" << std::endl;
        EVP_MD_CTX_free(verify_ctx);
        EVP_PKEY_free(pkey);
       
        return false;
    }
    
    
    if (EVP_DigestVerifyUpdate(verify_ctx, digest, digest_len) != 1) {
        ERR_print_errors_fp(stderr);
        EVP_MD_CTX_free(verify_ctx);
        EVP_PKEY_free(pkey);
        return false;
    }

    // Verify the signature
    if(EVP_DigestVerifyFinal(verify_ctx, signature.data(), signature.size()) != 1) 
    {
      ERR_print_errors_fp(stderr);
        std::cerr << "Signature verification failed" << std::endl;
        EVP_MD_CTX_free(verify_ctx);
        EVP_PKEY_free(pkey);
       
        return false;
    } 
    EVP_MD_CTX_free(verify_ctx);
    EVP_PKEY_free(pkey);
   

    std::cout << "Signature verification succeeded" << std::endl;
    return true;
}

int main()
{
    std::string signature_file = "signature_direct.sig";
    std::string public_key_file = "public_key.pem";
    std::string data_file = "sw.swu";

    if (!verify_signature(signature_file, public_key_file, data_file)) {
        std::cerr << "Signature verification failed" << std::endl;
        return 1;
    }

    return 0;
}

`

On running the openssl command above, the signature verification is OK, however on using the same files in the C++ code, the signature verification fails.

Can somebody please help, where am I wrong in the code?

Aucun commentaire:

Enregistrer un commentaire