Python:3.9.16 OpenSSL:3.0.8
fips_ccode.c
#include <stdio.h>
#include <stdlib.h>
#include <openssl/provider.h>
#include "openssl/md5.h"
int main(void)
{
OSSL_PROVIDER* fips;
OSSL_PROVIDER* base;
const char* default_search_path = "/tmp/fips_files/";
OSSL_PROVIDER_set_default_search_path(NULL, default_search_path);
int load_config = OSSL_LIB_CTX_load_config(NULL, "/tmp/fips_files/openssl.cnf") ;
printf("loading config:%d\n", load_config);
fips = OSSL_PROVIDER_load(NULL, "fips");
printf("value:%x\n",fips);
printf("Success to load FIPS provider\n");
base = OSSL_PROVIDER_load(NULL, "base");
printf("Success to load base provider\n");
}
fips_python.py
import ctypes
import os
import ssl
import ssl, os
import hashlib
BASEDIR="/tmp/"
FILENAME="libcrypto.so.3"
def get_crypto_lib_path():
return os.path.join(BASEDIR, FILENAME)
crypto_context = ctypes.CDLL(os.path.join(BASEDIR, get_crypto_lib_path()))
crypto_context.OSSL_PROVIDER_set_default_search_path.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_PROVIDER_set_default_search_path.restype = ctypes.c_char
crypto_context.OSSL_PROVIDER_set_default_search_path(None, "/tmp/fips_files/")
crypto_context.OSSL_LIB_CTX_load_config.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_LIB_CTX_load_config.restype = ctypes.c_int
load_config = crypto_context.OSSL_LIB_CTX_load_config(None, "/tmp/fips_files/openssl.cnf")
print("load config:", load_config)
crypto_context.OSSL_PROVIDER_load.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_PROVIDER_load.restype = ctypes.c_wchar_p
base_load = crypto_context.OSSL_PROVIDER_load(None, "base")
print("base load ret value:", base_load)
crypto_context.OSSL_PROVIDER_load.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_PROVIDER_load.restype = ctypes.c_wchar_p
fips_load = crypto_context.OSSL_PROVIDER_load(None, "fips")
print("fips load ret value:", fips_load)
在这里,我在使用 ctypes 的 python 中使用“OSSL_PROVIDER_load”函数加载提供程序“fips”和“base”时遇到问题。 在这里加载 c 函数的正确方法是什么?使用的参数类型是否正确?
清单 [Python.Docs]:ctypes - Python 的外部函数库。
代码中有一堆错误:
LibCrypto的路径计算不正确(BASEDIR前缀两次)
您想要使用 OpenSSL v3.0 功能,但 LibCrypto 的名称表明是 v1.1。 2者差别很大
显然(除非 libcrypto.so.1.1 是一个误导性的名称 SymLink),这些函数将不存在,因此无法加载
Python 函数原型与 C 函数原型不同,可以在以下位置找到:
这会产生Un定义B行为。检查[SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案)了解更多详细信息
还有其他的(比如不检查函数返回码),但与之前的相比,这些只是轻量级的
我准备了一个小例子来修复第 3rd 点。
code00.py:
#!/usr/bin/env python
import ctypes as cts
import os
import sys
PATH_LIBCRYPTO = "../q069539286/docker/openssl-1.1.1g/lib/libcrypto.so.1.1.1g"
PATH_LIBCRYPTO = "/tmp/libcrypto.so.1.1"
PATH_CFG = b"/tmp/fips_files/"
# @TODO - cfati: Use my paths
PATH_OSSL3_BASE = "/usr/local/pc064/openssl/openssl/3.0.10"
PATH_LIBCRYPTO = os.path.join(PATH_OSSL3_BASE, "lib", "libcrypto.so.3")
PATH_CFG = os.path.join(PATH_OSSL3_BASE.encode(), b"ssl")
POSSL_LIB_CTX = cts.c_void_p
POSSL_PROVIDER = cts.c_void_p
def main(*argv):
libcrypto = cts.CDLL(PATH_LIBCRYPTO)
OSSL_PROVIDER_set_default_search_path = libcrypto.OSSL_PROVIDER_set_default_search_path
OSSL_PROVIDER_set_default_search_path.argtypes = (POSSL_LIB_CTX, cts.c_char_p)
OSSL_PROVIDER_set_default_search_path.restype = cts.c_int
OSSL_LIB_CTX_load_config = libcrypto.OSSL_LIB_CTX_load_config
OSSL_LIB_CTX_load_config.argtypes = (POSSL_LIB_CTX, cts.c_char_p)
OSSL_LIB_CTX_load_config.restype = cts.c_int
OSSL_PROVIDER_load = libcrypto.OSSL_PROVIDER_load
OSSL_PROVIDER_load.argtypes = (POSSL_LIB_CTX, cts.c_char_p)
OSSL_PROVIDER_load.restype = POSSL_PROVIDER
res = OSSL_PROVIDER_set_default_search_path(None, PATH_CFG)
if res == 0:
print("OSSL_PROVIDER_set_default_search_path error")
return 1
res = OSSL_LIB_CTX_load_config(None, os.path.join(PATH_CFG, b"openssl.cnf"))
if res == 0:
print("OSSL_LIB_CTX_load_config error")
return 1
base_provider = OSSL_PROVIDER_load(None, b"base")
fips_provider = OSSL_PROVIDER_load(None, b"fips")
print(f"Base: {base_provider}\nFIPS: {fips_provider}")
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
输出:
[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q075889485]> python ./code00.py Python 3.8.18 (default, Aug 25 2023, 13:20:30) [GCC 11.4.0] 064bit on linux Base: 17667472 FIPS: None Done.
注释:
以上输出:
可以工作,但FIPS在默认配置中未启用
使用过 [GitHub]:CristiFati/Prebuilt-Binaries -(主)Prebuilt-Binaries/OpenSSL
虽然CTypes是Python和C之间的一个很好的桥梁(我个人很喜欢它),但它需要编写大量的样板代码。对于您的情况,可能有更好的替代方案来实现所需的功能。您可能会研究一些 Python 的 OpenSSL 包装器,例如:
可能还想检查: