簡體   English   中英

Python OpenSSL C擴展:未定義符號:AES_set_encrypt_key

[英]Python OpenSSL C extension: undefined symbol: AES_set_encrypt_key

我正在嘗試寫Python的OpenSSL C擴展。 共享庫(* .so文件)已生成,但是在導入模塊時遇到未定義的符號錯誤。 它將引發以下錯誤(未定義符號:AES_set_encrypt_key)

>>> import openssl_python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /home/rohith/python_c_extension/aes/openssl_python.cpython-35m-x86_64-linux-gnu.so: undefined symbol: AES_set_encrypt_key

以下是我的源代碼

setup.py

from distutils.core import setup, Extension

openssl_module = Extension('openssl_python',
                       sources = ['openssl_python.c'])

setup(name = 'openssl',
      version = '1.0',
      description = 'Python Package with OpenSSL C Extension',
      ext_modules = [openssl_module])

openssl_python.c

#include <Python.h>
#include <stdio.h>
#include <openssl/des.h>
#include <openssl/aes.h>

static PyObject* openssl_module_aes_encrypt(PyObject *self, PyObject *args){
    char* sn;
    if (!PyArg_ParseTuple(args, "s", &sn))
        return NULL;

    AES_KEY       key;
    unsigned char ivec[AES_BLOCK_SIZE];

    unsigned char outBuf[16];

    memcpy(ivec, sqlcFirmwareIvec, sizeof(sqlcFirmwareIvec));

    AES_set_encrypt_key(sqlcFirmwareKey,
                            sizeof(sqlcFirmwareKey) * 8,
                            &key);
    int dataLen = 16;
    int requiredLen = (dataLen / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;

    if (dataLen % AES_BLOCK_SIZE) {
        requiredLen += AES_BLOCK_SIZE;
    }

    AES_cbc_encrypt(sn, outBuf, requiredLen, &key, ivec, AES_ENCRYPT);

    return 1;
}

static PyMethodDef openssl_module_methods[] = { //Can add more functions here
    {   
        "aes_encrypt",
        openssl_module_aes_encrypt,
        METH_VARARGS,
        "Method to encrypt data using Openssl's AES algorithm"
    },  
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef openssl_module_definition = { 
    PyModuleDef_HEAD_INIT,
    "hello_module",
    "A Python module that prints 'hello world' from C code.",
    -1, 
    openssl_module_methods
};

PyMODINIT_FUNC PyInit_openssl_python(void)
{
    Py_Initialize();
    return PyModule_Create(&openssl_module_definition);
}

我使用CFLAGS="-lcrypto" python3 ./setup.py build_ext --inplace編譯它CFLAGS="-lcrypto" python3 ./setup.py build_ext --inplace

誰能幫我解決錯誤?

謝謝。 我沒有故意顯示key和Ivec的值。

編輯:

運行命令: python3 setup.py clean, CFLAGS="-Wl,-z,defs -lcrypto" python3 setup.py build_ext --inplace

這是輸出

running build_ext
building 'openssl_python' extension
creating build
creating build/temp.linux-x86_64-3.5
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wl,-z,defs -lcrypto -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.5m -c openssl_python.c -o build/temp.linux-x86_64-3.5/openssl_python.o
openssl_python.c: In function ‘openssl_module_aes_encrypt’:
openssl_python.c:49:21: warning: pointer targets in passing argument 1 of ‘AES_cbc_encrypt’ differ in signedness [-Wpointer-sign]
     AES_cbc_encrypt(sn,
                     ^
In file included from openssl_python.c:4:0:
/usr/include/openssl/aes.h:107:6: note: expected ‘const unsigned char *’ but argument is of type ‘char *’
 void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
      ^
openssl_python.c:61:12: warning: return makes pointer from integer without a cast [-Wint-conversion]
     return 1;
            ^
openssl_python.c:20:23: warning: unused variable ‘sqlcFirmwarePadding’ [-Wunused-variable]
  static unsigned char sqlcFirmwarePadding[] = {
                       ^
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,defs -lcrypto -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.5/openssl_python.o -o /home/rohith/python_c_extension/aes/openssl_python.cpython-35m-x86_64-linux-gnu.so
build/temp.linux-x86_64-3.5/openssl_python.o: In function `openssl_module_aes_encrypt':
/home/rohith/python_c_extension/aes/openssl_python.c:27: undefined reference to `PyArg_ParseTuple'
/home/rohith/python_c_extension/aes/openssl_python.c:37: undefined reference to `AES_set_encrypt_key'
/home/rohith/python_c_extension/aes/openssl_python.c:49: undefined reference to `AES_cbc_encrypt'
build/temp.linux-x86_64-3.5/openssl_python.o: In function `PyInit_openssl_python':
/home/rohith/python_c_extension/aes/openssl_python.c:84: undefined reference to `Py_Initialize'
/home/rohith/python_c_extension/aes/openssl_python.c:86: undefined reference to `PyModule_Create2'
collect2: error: ld returned 1 exit status
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

這里的本質問題是,當setup.py鏈接您的擴展名時,它會將-lcrypto放在命令行中包含代碼的目標文件之前 Unix鏈接器嚴格在命令行上從左到右處理對象和庫: -lcrypto foo.o將不使用libcrypto來解析foo.o符號。 這是出於歷史原因,不再具有很大的意義,但我們堅持使用它,因為它將破壞太多的Makefile文件以進行更改。 同樣由於歷史原因,這些不再有意義,如果您不在命令行上放置-Wl,-z,defs ,則共享庫(技術上是編譯后的Python擴展是共享庫)中包含未定義的符號這不是鏈接時錯誤,這就是構建似乎起作用的原因。

您的擴展程序本質上需要libcrypto。 如果我正確閱讀了Distutils文檔,則意味着您應該在Extension(...)libraries=關鍵字參數中指定它,而不是將其放在CFLAGS中。 像這樣:

openssl_module = Extension('openssl_python',
                       sources = ['openssl_python.c'],
                       libraries = ['crypto'])

zwol的解決方案要好得多。 但是我只是為了完整性而包括在內。

發出以下命令:

x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.5m -c openssl_python.c -lcrypto -o build/temp.linux-x86_64-3.5/openssl_python.o

其次是

x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.5/openssl_python.o -lcrypto -o /home/rohith/python_c_extension/aes/openssl_python.cpython-35m-x86_64-linux-gnu.so

現在將生成共享庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM