C++ Shared Library: Hashing function is returning no value when called with Python CTypes

  c++, ctypes, python

I have a simple C++ shared library that I am trying to use in Python with CTypes. It has one hash function which takes a char* as a param and returns a type char* hash value. I am able to build and run this just fine on mac as a .dylib, but when I try to run it on Linux as a .so the function works as expected except it returns nothing. The only thing I’ve found that could cause this is having the wrong restype, but as far as I can tell the typing is correct here. Can someone help me figure out what I’m doing wrong?

library.cpp:

#include "library.h"
#include <ostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <openssl/evp.h>

const char* computeHash(const std::string& message, std::string& hashed)
{
        EVP_MD_CTX* context = EVP_MD_CTX_new();

        if(context != nullptr)
        {
            if(EVP_DigestInit_ex(context, EVP_sha256(), nullptr))
            {
                if(EVP_DigestUpdate(context, message.c_str(), message.length()))
                {
                    unsigned char hash[EVP_MAX_MD_SIZE];
                    unsigned int lengthOfHash = 0;

                    if(EVP_DigestFinal_ex(context, hash, &lengthOfHash))
                    {
                        std::stringstream ss;
                        for(unsigned int i = 0; i < lengthOfHash; ++i)
                        {
                            ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
                        }

                        hashed = ss.str();
                    }
                }
            }

            EVP_MD_CTX_free(context);
        }

    return hashed.c_str();
}

const char* hashData(const char* message) {
    std::string message_str(message);
    std::string generatedHash;
    return computeHash(message, generatedHash);
}

library.h:

#ifndef SIGN_DATA_LIBRARY_H
#define SIGN_DATA_LIBRARY_H

#include <string>
#include <openssl/evp.h>


extern "C"
{
    const char* hashData(const char* message);
}

#endif //SIGN_DATA_LIBRARY_H

CMakeLists.txt:

cmake_minimum_required(VERSION 3.17)
project(shared-library)

set(CMAKE_CXX_STANDARD 14)
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)

add_library(hash-data SHARED library.cpp library.h)

add_executable(sign_data main.cpp)

target_link_libraries(sign_data PRIVATE hash-data)


find_package(OpenSSL REQUIRED)
target_include_directories(hash-data PUBLIC ${OPENSSL_INCLUDE_DIR})
target_link_libraries(hash-data OpenSSL::SSL)

hash-data.py:

import base64
from ctypes import CDLL, create_string_buffer, c_char_p


libc = CDLL("build/libhash-data.so")


def hash_transaction(message: bytes) -> str:
    libc.hashData.argtypes = [c_char_p]
    libc.hashData.restype = c_char_p
    signature = libc.hashData(create_string_buffer(message))
    return base64.b64encode(signature).decode("ascii")


def main():
    print(hash_transaction(b'xccx96xf8xbapNxbbxe5xd6xb8x12"/xaf<xa4x89&}xe3xebxe2p`dxc6Wxe3x1fx0exb0'))


if __name__ == '__main__':
    main()

Source: Windows Questions C++

LEAVE A COMMENT