☰
cryptography 常见问题完全指南:从安装排错到 PEM 解析的实战 FAQ
2026/9/27 8:39:20 网站建设 项目流程
  • 密码学

【免费下载链接】cryptography

cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.

项目地址:https://gitcode.com/gh_mirrors/cr/cryptography
点击查看免费下载

cryptography是 Python 生态中最主流的密码学工具库之一,为开发者提供加密原语(primitives)与开箱即用的配方(recipes)。本篇指南以官方 docs/faq.rst 为骨架,系统梳理安装失败、警告抑制、OpenSSL 版本、Rust 构建、InternalError、PEM 导入等高频问题,并结合仓库源码与测试给出可复现的排查路径与最佳实践。

读完本文,你将掌握:如何快速解决pip install cryptography失败、如何正确抑制 import 时的弃用警告、如何应对 OpenSSL 版本过低与缺失 Rust 编译器、如何定位InternalError的根因、如何规范 PEM 文件使其可被顺利加载,以及如何理解backend参数的历史演进与当前现状。

问题追踪的原则:先分清是不是 cryptography 的锅

官方 FAQ 明确指出,issue tracker 的首要目的是定位并修复cryptography自身的 bug 与功能请求。因此每当用户报障时,项目组首先会问一个问题:这是 cryptography 的 bug,还是其他环节的 bug?

项目组会尽力帮助用户排查代码或环境层面的问题,但也坦诚存在边界:当问题与用户特定环境强相关、且无法复现时,协助能力有限;同时项目组不提供通用 Python 或 Python 打包(packaging)问题的支持。这一原则决定了你提 bug 时的预期管理:尽量提供最小可复现示例,并先排除自身代码与环境因素。

无法抑制的 import 弃用警告:为什么 filterwarnings 不生效

警告类型:不是 DeprecationWarning,而是 UserWarning

FAQ 特别用 hint 强调:cryptography在 import 时发出的弃用警告并不继承DeprecationWarning,而是继承UserWarning。这一设计在源码中有明确注释:src/cryptography/utils.py:

# We use a UserWarning subclass, instead of DeprecationWarning, because CPython # decided deprecation warnings should be invisible by default. class CryptographyDeprecationWarning(UserWarning): pass

CPython 自 2.7 起默认隐藏DeprecationWarning(仅开发者可见),为了确保弃用提示真正被用户看到,cryptography刻意选择继承UserWarning。

pytest 场景下的抑制方法

如果你的 pytest 遵循最佳实践、把警告视为错误(filterwarnings = error),import 时弹出的弃用警告会导致测试直接失败。官方给出的解决方案是在filterwarnings列表末尾追加一条 ignore 规则:

ignore:Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.:UserWarning

为什么不能用 CryptographyDeprecationWarning 类名来过滤

FAQ 特别强调了一个容易踩的坑:不要试图用cryptography.utils.CryptographyDeprecationWarning作为 ignore 的类别参数。原因在于:指定该类别时,pytest/过滤器解析过程会内部触发import cryptography,而这会在 ignore 规则生效之前就把警告发射出来,规则形同虚设。

同样的规则适用于 warnings.filterwarnings 与 -W 参数

除了 pytest,FAQ 指出同样的原理适用于代码内调用warnings.filterwarnings,或者用 CPython 的-W命令行选项启动解释器。示例:

import warnings warnings.filterwarnings("ignore", message=r"Python 2 is no longer supported.*")

命令行方式:

$ python -W "ignore:Python 2 is no longer supported.*:UserWarning" your_script.py

从源码看,CryptographyDeprecationWarning同时是多个版本系列的弃用别名(DeprecatedIn36~DeprecatedIn51),见 src/cryptography/utils.py,这意味着未来仍会有同类警告出现,掌握上述匹配模式比记住某条具体消息更有价值。

cryptography 安装失败的通用排错路径

第一步:升级 pip 再试

安装失败的第一排查步骤永远是升级 pip 后重装。FAQ 给出的命令:

$ pip install -U pip

Windows 平台则建议使用:

$ python -m pip install -U pip

绝大多数安装问题(尤其是旧 pip 无法识别新格式 wheel)都能在这一步解决。升级后重新执行pip install cryptography,若仍报错,再参考完整的 docs/installation.rst 文档按平台逐项排查。

第二步:区分报错类型定位根因

常见报错可归为三类,对应 FAQ 中三个独立条目:

报错现象根因处理方向
Can not find Rust compiler本地无 Rust 工具链,需从源码构建升级 pip 获取预编译 wheel,或安装 Rust(见下文)
安装时因 OpenSSL 过旧失败系统 OpenSSL 低于 3.0.0升级到 OpenSSL 3.0.0+(可能需要升级操作系统)
构建时报错error: Can not find Rust compiler源码构建缺少 Rust参照 docs/installation.rst 的 Rust 章节安装

为什么 cryptography 需要 Rust:内存安全与性能的取舍

FAQ 明确回答了"为什么需要 Rust"这一高频疑问:

cryptography的密码学运算依赖 OpenSSL(详见 docs/openssl.rst)——OpenSSL 是事实上的密码学标准实现,性能高、附带多种对开发者有价值的认证。但它是 C 语言编写,缺乏内存安全性。项目组的策略是:保留 OpenSSL 的高性能优势,同时把非密码学运算(例如 ASN.1 解析)重写为高性能、内存安全的 Rust。

这一架构决策在仓库中清晰可见:src/rust/下存在多个 Rust crate,如负责 ASN.1 解析与编解码的src/rust/declarative_asn1/、负责密钥解析的 src/rust/cryptography-key-parsing/,以及cryptography-openssl、cryptography-x509、cryptography-x509-verification等模块化 crate(见 src/rust/Cargo.toml 及各 crate 的 Cargo.toml)。

Rust 只在构建期需要

FAQ 特别澄清:Rust 仅在 cryptography 的构建阶段需要,构建完成后使用 cryptography 无需 Rust 环境。这与 C 编译器工具链的情况完全一致——都是"构建需要、运行不需要"。当前最低支持的 Rust 版本为 1.83.0(见 docs/installation.rst 的 Rust 章节),部分发行版(如 Alpine < 3.21、Debian 早于 Trixie 的版本、RHEL/CentOS 9.6 之前的版本)自带的 Rust 过旧,需要按官方指引安装较新版本。

在 Docker 等部署场景中,推荐多阶段构建:构建阶段安装 Rust 和 C 工具链,运行镜像中则不包含它们。

遇到 InternalError 该怎么办

InternalError 从哪来

InternalError的定义位于 src/cryptography/exceptions.py,其抛出点在 OpenSSL 绑定层。核心逻辑在 src/cryptography/hazmat/bindings/openssl/binding.py:

def _openssl_assert(ok: bool) -> None: if not ok: errors = openssl.capture_error_stack() raise InternalError( "Unknown OpenSSL error. This error is commonly encountered when " "another library is not cleaning up the OpenSSL error stack. ...", errors, )

最常见的根因:OpenSSL 错误栈被"污染"

FAQ 明确指出:InternalError最常见的原因是同一进程内其他也使用 OpenSSL 的库把错误留在了 OpenSSL 错误栈上。排查步骤:

  1. 逐个移除进程中的其他 OpenSSL 使用方(如 PyOpenSSL、requests 的某些后端、其他加密库),看问题是否消失;
  2. 若移除后仍有问题,或确认其他库无责,则可能是 cryptography 自身 bug,请携带可复现步骤到项目 issue 区提交。

OpenSSL 版本过低导致安装失败

OpenSSL 项目已停止维护 0.9.8、1.0.0、1.0.1、1.0.2、1.1.0、1.1.1 这些发布系列,这些版本不再获得上游安全补丁,cryptography也随之放弃对它们的支持。因此安装或构建 cryptography 时遇到 OpenSSL 相关失败,处理方式就是升级到 OpenSSL 3.0.0 或更高版本——这可能意味着需要升级到更新的操作系统发行版。

从 docs/installation.rst 可以看到,项目当前测试覆盖OpenSSL 3.0-latest、3.4-latest、3.5-latest、3.6-latest、4.0-latest,以及 BoringSSL、aws-lc 与仍在安全支持期的 LibreSSL。多数主流平台通过manylinux/musllinux静态链接 wheel 即可获得最新 OpenSSL,无需关心系统自带版本。

构建报错 "Can not find Rust compiler"

若从源码构建 cryptography 时出现该错误,说明环境中没有 Rust 工具链。两条解决路径:

  1. 升级 pip:新版 pip 会优先安装预编译的abi3wheel,多数用户升级 pip 后即可跳过源码构建、不再需要 Rust;
  2. 安装 Rust:按 docs/installation.rst 中的指引安装较新版本的 Rust(推荐用 rustup,最低 1.83.0),并确保rustc/cargo在PATH中。

同样强调:Rust 只在构建阶段需要。Linux 下常见发行版安装命令(取自 docs/installation.rst):

# Alpine $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev cargo pkgconfig # Debian/Ubuntu $ sudo apt-get install build-essential libssl-dev libffi-dev \ python3-dev cargo pkg-config # Fedora/RHEL/CentOS(需 9.6+) $ sudo dnf install redhat-rpm-config gcc libffi-devel python3-devel \ openssl-devel cargo pkg-config

强制从源码构建(不使用 manylinux wheel)时可加--no-binary:

$ pip install cryptography --no-binary cryptography

AWS Lambda 上的安装/导入错误

在 AWS Lambda 上遇到安装或导入错误时,FAQ 建议严格遵循 AWS 官方文档来构建部署包:

  • 构建 Lambda 的 .zip 归档时,按 AWS 的 Python 打包文档操作;
  • 使用容器镜像时,按 AWS 的容器镜像构建文档操作。

核心要点是:Lambda 环境精简且架构可能非 x86-64,依赖需随包带上或打进镜像,且要注意为对应架构(如 ARM64 Graviton)获取正确的 wheel。

abi3 wheel:为什么你的 Python 版本没有专属 wheel

FAQ 解释了一个常见疑惑:"为什么没有针对我的 Python 3.x 版本的 wheel?"

答案在于 cryptography 的 Python 3 wheel 是abi3wheel(即 CPython ABI 稳定 ABI)。这类 wheel 标注了一个最低 Python 版本,并可在大于或等于该版本的任何 Python 版本上使用。新版 pip 会自动选择并安装 abi3 wheel,因此不需要为每个 Python 3 小版本单独发布 wheel。

这意味着:即使 PyPI 页面上没有与你 Python 3.x 精确匹配的 wheel 文件,只要你的 Python 版本不低于 abi3 wheel 声明的基线(例如 cp39),安装也能正常进行。

PEM 文件无法导入:格式校验清单

PEM 是什么

PEM 是一种将密钥、证书等密码学数据编码为普通文本的格式(最初定义于 RFC 1421,后被多个 RFC 沿用)。数据先做 base64 编码,再用头尾行包裹。

可导入的 PEM 必须满足三条规则

FAQ 给出明确校验清单:

  1. 头行必须为单行,形如-----BEGIN [FILE TYPE]-----,其中[FILE TYPE]为CERTIFICATE、PUBLIC KEY、PRIVATE KEY等;
  2. 尾行必须为单行,形如-----END [FILE TYPE]-----;
  3. 除最后一行外,所有行必须恰好为 64 个字符(base64 编码的 64 字符折行标准)。

合法 PEM 示例(RSA 公钥)

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7CsKFSzq20NLb2VQDXma 9DsDXtKADv0ziI5hT1KG6Bex5seE9pUoEcUxNv4uXo2jzAUgyRweRl/DLU8SoN8+ WWd6YWik4GZvNv7j0z28h9Q5jRySxy4dmElFtIRHGiKhqd1Z06z4AzrmKEzgxkOk LJjY9cvwD+iXjpK2oJwNNyavvjb5YZq6V60RhpyNtKpMh2+zRLgIk9sROEPQeYfK 22zj2CnGBMg5Gm2uPOsGDltl/I/Fdh1aO3X4i1GXwCuPf1kSAg6lPJD0batftkSG v0X0heUaV0j1HSNlBWamT4IR9+iJfKJHekOqvHQBcaCu7Ja4kXzx6GZ3M2j/Ja3A 2QIDAQAB -----END PUBLIC KEY-----

若你的 PEM 导入失败,对照上述三条规则逐一检查:头尾行是否有额外空格或换行、中间行长度是否严格 64 字符、文件是否混入了不可见字符或非 base64 字符。

对应加载 API

PEM 加载入口集中在 src/cryptography/hazmat/primitives/serialization/base.py,例如:

from cryptography.hazmat.primitives import serialization private_key = serialization.load_pem_private_key(data, password=None) public_key = serialization.load_pem_public_key(data)

其中load_pem_private_key、load_pem_public_key直接映射到 Rust 侧的密钥解析实现(rust_openssl.keys.load_pem_private_key等),而load_pem_parameters(DH 参数)映射到rust_openssl.dh.from_pem_parameters。这正是 FAQ"为什么需要 Rust"一节所述架构的具体体现:PEM/ASN.1 解析已由 Rust 实现。

backend 参数去哪了:一个历史演进问题

FAQ 记录了一次重要的 API 演进:

  • 版本 3.1 起,cryptography不再要求提供backend参数;
  • 版本 36.0 起,正式弃用backend参数;
  • 如果你仍在使用旧版本且依赖该参数,请查看对应版本的文档或直接升级到最新版。

FAQ 特别说明:出于向前兼容考虑,backend仍会被静默接受——传了也不会报错,但会被忽略且不再出现在文档中。因此在新代码中无需(也不应)再传递backend。

非 x86 非 ARM64 架构:为什么没有你的 CPU 的 wheel

FAQ 坦诚回应了"为什么不为我的 CPU 架构上传 wheel"的问题:

  • 上传到 PyPI 的 wheel 必须经过该架构上的完整 CI 测试(每个 commit 都跑),因为 cryptography 大量使用按架构优化的汇编代码;
  • 将某架构纳入 CI 需要满足:有能提供该架构构建、能集成进现有 workflow、容量足够且性能不拖累贡献者体验的 CI 提供方。

FAQ 认为这不是不可逾越的门槛,但也不轻松。若你希望支持新 CPU 架构,欢迎联系项目组讨论并贡献支持——项目组会尽量配合,但无法承诺亲自完成这项工作。

总结:FAQ 中的通用排错方法论

纵观 docs/faq.rst,可以提炼出一条通用的排错方法论:

  1. 先升级 pip 再重装——解决大多数 wheel 识别与源码构建误判问题;
  2. 区分"项目 bug"与"环境问题"——InternalError优先排查 OpenSSL 错误栈是否被其他库污染;
  3. 理解构建期依赖(Rust、C 工具链、OpenSSL)与运行期依赖的区别——构建时缺什么补什么,运行时不需要 Rust;
  4. 校验输入格式——PEM 导入失败按 64 字符折行与头尾行规则逐条核对;
  5. 跟紧 API 演进——backend参数已弃用但可静默兼容,新代码不要传;
  6. 遵循官方文档——Lambda、各发行版、Windows 编译等场景均有对应章节指引,详见 docs/installation.rst。

这套方法论配合仓库内的源码(绑定层、Rust 解析器、序列化 API)与测试(如 tests/test_warnings.py 中对deprecated机制的验证),足以应对绝大多数 cryptography 的日常使用与排障场景。

  • 密码学

【免费下载链接】cryptography

cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.

项目地址:https://gitcode.com/gh_mirrors/cr/cryptography
点击查看免费下载

相关推荐

上一篇:终极ffmpeg-python视频增强指南:AI超分辨率技术应用
下一篇:android-async-http容器化部署:Docker集成测试

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询