我已经建立了OpenSSL-FIPS使用常规标志的模块(例如:no-asm, shared,一些古老的密码被禁用):
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049320993]> ~/sopr.sh
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
[064bit-prompt]> ls ssl/build/bin ssl/build/lib
ssl/build/bin:
c_rehash openssl
ssl/build/lib:
engines libcrypto.a libcrypto.so libcrypto.so.1.0.0 libssl.a libssl.so libssl.so.1.0.0 pkgconfig
并开始玩弄它:
[064bit-prompt]> ssl/build/bin/openssl version
OpenSSL 1.0.2h-fips 3 May 2016 (Library: OpenSSL 1.0.2g 1 Mar 2016)
请注意“(库:OpenSSL 1.0.2g 2016 年 3 月 1 日)”部分。(存在)表明openssl可执行文件正常(预期版本),但它使用wrong 加密库(这是系统默认安装的 - 在/lib- 通常情况下,它不是用FIPS支持)。
必须加载our库,这是通过设置完成的LD_LIBRARY_PATH(同样的行为也可以通过在构建时设置环境变量来实现OpenSSL这将设定rpath in the openssl可执行文件,但我忘记了,而且我不想再次构建它):
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl version
OpenSSL 1.0.2h-fips 3 May 2016
现在,设置成功了,让我们深入了解一下OPENSSL_FIPS env var:
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl md5 ./code00.py
MD5(./code00.py)= 47fb26ec5d1ca16d3537fe7fd12ea529
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl sha1 ./code00.py
SHA1(./code00.py)= 5188a221ba61309e78e70004285bc6fd148701b6
[064bit-prompt]> OPENSSL_FIPS=1 LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl sha1 ./code00.py
SHA1(./code00.py)= 5188a221ba61309e78e70004285bc6fd148701b6
[064bit-prompt]> OPENSSL_FIPS=1 LD_LIBRARY_PATH=ssl/build/lib ssl/build/bin/openssl md5 ./code00.py
Error setting digest md5
139778679649944:error:060A80A3:digital envelope routines:FIPS_DIGESTINIT:disabled for fips:fips_md.c:180:
从上面可以看出,md5哈希行为受以下因素影响OPENSSL_FIPS env var (when FIPS模式已打开,不允许使用)。
Notes:
Since OPENSSL_FIPS env var处理于openssl可执行级别,这将被绕过(如加密库会直接使用),对于目前的情况来说没有用,所以我们必须深入。这些是控制的函数FIPS模式在一个loaded 加密库实例:
它们将用于读/写FIPS模式。为了测试是否FIPS模式确实已设置,md5将使用哈希(来自上面的示例)。
代码00.py:
#!/usr/bin/env python
import ctypes as cts
import ssl
import sys
libcrypto = cts.CDLL("libcrypto.so.1.0.0")
#ssleay = libcrypto.SSLeay
#ssleay.argtypes = ()
#ssleay.restype = cts.c_ulong
fips_mode = libcrypto.FIPS_mode
fips_mode.argtypes = ()
fips_mode.restype = cts.c_int
fips_mode_set = libcrypto.FIPS_mode_set
fips_mode_set.argtypes = (cts.c_int,)
fips_mode_set.restype = cts.c_int
def main(*argv):
text = b""
print("OPENSSL_VERSION: {:s}".format(ssl.OPENSSL_VERSION))
enable_fips = len(sys.argv) > 1
print("FIPS_mode(): {:d}".format(fips_mode()))
if enable_fips:
print("FIPS_mode_set(1): {:d}".format(fips_mode_set(1)))
print("FIPS_mode(): {:d}".format(fips_mode()))
#print("SSLeay: {:X}".format(ssleay()))
import hashlib
print("SHA1: {:s}".format(hashlib.sha1(text).hexdigest()))
print("MD5: {:s}".format(hashlib.md5(text).hexdigest()))
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.")
sys.exit(rc)
Notes:
-
Set argtypes and restype对于 2 个函数。查看[SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案) https://stackoverflow.com/a/58611011/4788546更多细节
-
The md5哈希算法位于Python水平由[Python.Docs]:hashlib - 安全哈希和消息摘要 https://docs.python.org/library/hashlib.html#module-hashlib
-
重要的: the import hashlib
语句位于after设置FIPS模式(而不是在文件开头,因为它应该是),因为hashlib做一些缓存在导入时,所以它捕获了FIPS导入时的值,不关心之后是否改变
Output:
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ./code00.py
Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] 064bit on linux
OPENSSL_VERSION: OpenSSL 1.0.2h-fips 3 May 2016
FIPS_mode(): 0
FIPS_mode(): 0
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
MD5: d41d8cd98f00b204e9800998ecf8427e
Done.
[064bit-prompt]> LD_LIBRARY_PATH=ssl/build/lib ./code00.py 1
Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] 064bit on linux
OPENSSL_VERSION: OpenSSL 1.0.2h-fips 3 May 2016
FIPS_mode(): 0
FIPS_mode_set(1): 1
FIPS_mode(): 1
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
fips_md.c(149): OpenSSL internal error, assertion failed: Digest Final previous FIPS forbidden algorithm error ignored
Aborted (core dumped)
如图所示,设置FIPS模式通过CTypes, really设置它。
我不知道为什么SegFaults,但是md5相关代码仅用于测试目的,因此在生产中不需要它。
我记得在一些Nix版本(可能是RH基于),FIPS还可以通过编辑某些条目(在系统全局范围内)来设置模式/proc?),但我不记得了。
A more elegant approach would be to expose Python wrappers for the 2 functions.
Check [Python.Bugs]: FIPS_mode() and FIPS_mode_set() functions in Python (ssl) https://bugs.python.org/issue27592, I've also submitted a patch for Python 3.4 (where they were exposed by the ssl module), but it was rejected based on the following arguments (out of which the 1st 2 are relevant):
-
FIPS是一个糟糕的标准
-
OpenSSL将放弃对其的支持
-
它打破了普遍性
您可以将其应用到Python 3.6(我认为这不会起作用OOTB,因为行号很可能发生变化),并且(显然)你必须构建Python从来源。
底线:
-
有一个big之间的区别FIPS working and FIPS已验证,我确信您已经阅读过[OpenSSL]:OpenSSL FIPS 对象模块 v2.0 用户指南 https://www.openssl.org/docs/fips/UserGuide-2.0.pdf
-
[AskUbuntu]:在 ubuntu 中启用 FIPS 140-2 https://askubuntu.com/q/903127/452474可能还包含一些有用的信息
一些可能有用的参考文献(尽管最后的参考文献可能有点太“深”):
-
[SO]:如何使用 SSL 在 RHEL 上编译 python3? SSL无法导入(@CristiFati的回答) https://stackoverflow.com/a/69670925/4788546
-
[SO]:如何在Python 3.6的ssl模块中实现FIPS_mode()和FIPS_mode_set()? (@CristiFati 的回答) https://stackoverflow.com/a/49494549/4788546
-
[SO]:OpenSSL FIPS_mode_set 无法在 Python 加密库中工作(@CristiFati 的回答) https://stackoverflow.com/a/58311407/4788546
-
[SO]:OpenSSL 3.0.8:FIPS 功能无法与自定义路径中的 libcrypto 库一起使用(@CristiFati 的回答) https://stackoverflow.com/a/75917800/4788546
Update #0
你所遇到的行为让我震惊[SO]:无法使用 Python ctypes 调用 libcrypto.so 的 FIPS_mode_set() [重复] https://stackoverflow.com/q/49381134/4788546也可能与wrong 加密库正在加载(检查openssl version
测试有/无LD_LIBRARY_PATH从一开始就)。
A non FIPS有能力的OpenSSL仍然会导出这 2 个函数,但它们都只是返回 0。
[064bit-prompt]> ./code00.py 1
Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] 064bit on linux
OPENSSL_VERSION: OpenSSL 1.0.2g 1 Mar 2016
FIPS_mode(): 0
FIPS_mode_set(1): 0
FIPS_mode(): 0
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
MD5: d41d8cd98f00b204e9800998ecf8427e
Done.
所以,请确保通过指定加载正确的库LD_LIBRARY_PATH! (还有其他方法,但这是最直接的方法)。