Skip to main content

易加密(easy_encryption_tool)

工具的安装

基础安装(仅国际算法)

以下命令安装后即可使用 AES、RSA、ECC、SHA 系列、HMAC(国际哈希)等算法:

pip install easy-encryption-tool

国密算法支持(可选)

3.0 起,国密算法(SM2、SM3、SM4、SM9、ZUC、SM3-KDF)改为直连 GmSSL C 库(版本 >= 3.1.1),不再依赖任何 Python 国密包。工具在运行时自动探测原生库:

  • 默认候选路径:~/.gmssl_3.1.1_install/lib/ 下的 libgmssl.so.3.1 / libgmssl.3.1.dylib(含不带版本号的软链接名),以及系统 find_library("gmssl") 能找到的位置;
  • 显式指定:设置环境变量 EET_GMSSL_LIB_PATH 指向 libgmssl 共享库文件(推荐做法,见下节环境变量表)。

自行编译 GmSSL 的方法见官方仓库 guanzhi/GmSSL;图文指南可参考 easy-gmssl-sdk(博客站)。

依赖国密算法的命令:hash -a sm3、hmac -a sm3、sm2、sm4、sm9、zuc、kdf -a sm3、kdf -a pbkdf2-sm3、cert-parse -g(kdf -a hkdf 走 cryptography,不在此列)。库缺失时执行这些命令会输出结构化错误并给出修复指引(构建 GmSSL 或设置 EET_GMSSL_LIB_PATH),不会静默回退。

环境变量

变量 作用 说明
EET_GMSSL_LIB_PATH 指定 libgmssl 共享库的文件路径 显式指定但加载失败时给出含路径的明确报错,不回退默认候选
EET_DEBUG_TIMING 输出命令耗时调试信息 仅排障用
# 示例:显式指定原生库后运行国密命令
export EET_GMSSL_LIB_PATH=~/.gmssl_3.1.1_install/lib/libgmssl.3.1.dylib
easy_encryption_tool sm2 --help

口令与机密数据的使用边界

  • 命令行上的口令对同用户进程可见:-p/--password、-k/--key 这类值经 argv 传入,同一台主机上能查看你进程列表的同一用户(或 root)可用 ps 读到明文。共享主机或高敏感环境请改用密钥文件输入,或只在独占环境中传口令。
  • -i 的值不做掩码:eet shell 交互历史(~/.eet_shell_history)会自动把口令、密钥、IV、种子等敏感选项值掩成 ***,但 -i 按普通数据处理、原文记录;在你自己的终端里,整条命令同样会进该 shell 的历史文件。机密明文请用文件输入(-f/输入文件参数),或事后清理历史。
  • 密钥文件拒绝覆盖是刻意设计:-f 前缀对应的公私钥文件已存在时命令直接失败,工具不提供 --force——旧私钥一旦被覆盖,用它加密过的数据将永久无法解开。脚本化场景请先显式移走旧文件,或换一个新的 -f 前缀。

后量子算法支持(可选)

如需使用 后量子算法(ML-KEM 密钥封装、ML-DSA 签名),需要 cryptography >= 47(ML-DSA ExternalMu 模式需 >= 49):

# 推荐:通过 [pqc] extra 一次性安装并保证 cryptography 版本(>= 50)
pip install "easy-encryption-tool[pqc]"

# 或:单独升级 cryptography(若已安装 easy-encryption-tool)
pip install "cryptography>=47"

依赖后量子的命令:pqc mlkem、pqc mldsa。cryptography 版本过旧时,执行这些命令会提示升级;参数集(如 ML-KEM-512)是否可用取决于 cryptography 版本,easy_encryption_tool version 的 Dependencies 行会列出。

Server 模式(可选,实验性)

如需以 HTTP 服务方式使用 CLI 能力,安装 [server] extra(FastAPI + uvicorn):

pip install "easy-encryption-tool[server]"

未安装时执行 easy_encryption_tool server 会输出结构化错误并给出安装指引,不影响其他命令。用法见下文 Server 模式 一节。

实验性声明:server 命令自 3.0.x 起入口已注释停用(eet server 返回 "No such command"):并发请求下的进程内哨兵存在已知竞态(评审 R4-1),修复并稳定前不提供该命令。server_command 模块与 create_app 保留在代码库中,供测试与将来修复后重新启用。

项目地址:easy-encryption-tool · PyPI


国密算法支持说明

算法 说明 对应命令 需 GmSSL 原生库
SM2 国密非对称算法,对标 RSA sm2(加解密、签名验签) ✓
SM3 国密哈希算法 hash -a sm3 ✓
SM4 国密对称算法,对标 AES sm4(CBC/GCM/CTR 模式) ✓
SM9 国密标识密码(IBC) sm9(主密钥生成、用户密钥派生、加解密、签名验签) ✓
ZUC 祖冲之流密码 zuc ✓
HKDF RFC 5869 密钥派生(SHA-2 族,3.2.0 起默认) kdf -a hkdf
SM3-KDF SM3 密钥派生 kdf -a sm3 ✓
PBKDF2-HMAC-SM3 口令派生 kdf -a pbkdf2-sm3 ✓
SM2 证书 国密证书解析 cert-parse -g ✓

国际算法(AES、RSA、ECC、SHA、HMAC 等)无需 GmSSL 原生库,仅安装 easy-encryption-tool 即可使用。


工具支持的命令

❯ easy_encryption_tool --help

Usage: easy_encryption_tool [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  aes         aes加解密工具,默认支持 aes-cbc-256 和 aes-gcm-256
  cert-parse  解析 pem 或 der 格式的证书,支持国际算法及国密 SM2(-g)
  convert     字符串格式转换工具,支持 UTF-8、Base64、Hex 互转
  doctor      环境与可选能力体检(cryptography/PQC、GmSSL 原生库与 external-mu 能力、七家云 KMS)
  ecc         ecc签名验签和密钥交换验证工具
  envelope    信封加密:非对称密钥包裹数据密钥(DEK)
  hash        哈希摘要工具,支持 SM3、SHA256、SHA384、SHA512
  hmac        hmac消息验证码工具,支持 SM3 及国际哈希算法
  int-to-bytes 整数与大/小端十六进制字节互转
  kdf         密钥派生工具,支持 HKDF(RFC 5869,默认,无需原生库)、SM3-KDF 与 PBKDF2-HMAC-SM3(需 GmSSL 原生库)
  pqc         后量子命令组:ML-KEM 密钥封装与 ML-DSA 签名验签(需 cryptography>=47)
  random-bytes 随机字节流生成器(1-1024 字节,默认 Base64 输出)
  random-str  随机字符串生成器
  rsa         rsa加解密和签名验签工具
  server      以 HTTP 服务方式提供 CLI 能力(FastAPI,需 [server] extra;3.0.x 实验特性,入口已注释停用)
  sm2         国密 SM2 加解密和签名验签工具(多种密文/签名格式)
  sm4         国密 SM4 对称加解密工具,支持 cbc、gcm 和 ctr 模式
  sm9         国密 SM9 标识密码命令组(主密钥/用户密钥/加解密/签名验签)
  structured  结构化文件加密:JSON/YAML/INI 叶子级 AEAD 加密
  ts          时间戳转换工具(秒级,本地/UTC/毫秒互转)
  version     展示当前版本信息以及运行时信息
  zuc         ZUC 祖冲之流密码加解密工具
  install-completion  安装 Shell Tab 自动补全(bash/zsh/fish)

Shell Tab 自动补全

支持对子命令、选项及选项值进行 Tab 补全,提升命令行使用效率。安装方式:

# 生成补全脚本并加载(zsh 示例)
easy_encryption_tool install-completion --shell zsh -p ~/.easy_encryption_tool_complete.sh
source ~/.easy_encryption_tool_complete.sh

补全能力包括:子命令补全、选项补全、固定可选值补全(如 -A encrypt/decrypt、-m cbc/gcm)、文件路径补全(如 -i 在指定 -f 时、-o、密钥文件路径等)。详见 CLI 使用说明。

环境与能力体检(eet doctor)

一行命令检查本机环境与全部可选能力,缺什么给什么修复命令:

❯ easy_encryption_tool doctor
╭────────────────────────────────  eet doctor  ────────────────────────────────╮
│                                                                              │
│    python                ✓ ok              3.12.7                            │
│    eet                   ✓ ok              v3.0.0                            │
│                                                                              │
│    cryptography          ✓ ok              50.0.1                            │
│    pqc                   ✓ ok              available                         │
│                                            (ML-KEM-768/1024, ML-DSA-44/65/87) │
│                                            external-mu ok                   │
│    ── native libraries ──                                                    │
│    gmssl (native)        ✓ ok              GmSSL 3.1.1                       │
│                                            (/Users/cyx/.gmssl_3.1.1_in…      │
│    ML-DSA external-mu    ✓ ok              native                            │
│                                            (cryptography 50.0.1)             │
│                                                                              │
│    ── cloud KMS backends ──                                                  │
│    kms aws               ✓ ok              1.35.53 (boto3)                   │
│    kms tencentcloud      ✓ ok              3.1.87 (tencentcloud.kms.…        │
│    kms aliyun            ✓ ok              2.4.0 (alibabacloud_kms2…         │
│    kms huawei            ✓ ok              3.1.186 (huaweicloudsdkkms)       │
│    kms google            ✓ ok              3.11.0 (google.cloud.kms_v1)      │
│    kms vault             ✓ ok              2.4.0 (hvac)                      │
│    kms azure             ✗ missing         azure.keyvault.keys.crypt…        │
│    ── guides ──                                                              │
│                          azure-keyvault-keys https://pypi.org/projec…        │
╰──────────────────────────────────────────────────────────────────────────────╯

体检项分四组:核心运行时(python/eet)、密码栈(cryptography 及 PQC 参数集)、原生库与能力(GmSSL 国密依赖;ML-DSA external-mu 能力行——3.1 起走 cryptography 原生 sign_mu/verify_mu(>= 49),不再探测系统 OpenSSL)、七家云 KMS SDK。缺失项的 Fix 列给出修复方式:KMS SDK 缺失给 pip install 命令;GmSSL 缺失给构建指引与 EET_GMSSL_LIB_PATH;external-mu 缺失给 [pqc] extra 安装命令。表尾 guides 小节只为非 ok 的行列出官方与博客链接。doctor 默认输出表格适合直接阅读与截图排障;--json / --pretty-json 走统一输出契约,供脚本消费。

显示版本

缺省输出 rich 面板:版本号、功能清单、运行时环境、依赖画像(GmSSL 原生库版本与路径、external-mu 能力(cryptography 原生)、cryptography / rich / click、PQC 参数集、七家云 KMS SDK 安装状态)。

3.0 起 version 支持 --json / --pretty-json,输出与其他加密命令一致的标准输出契约,result.dependencies 携带完整依赖画像快照,便于脚本化采集:

❯ easy_encryption_tool version --json

{"metadata": {"operation": "version", "algorithm": "version", "input": {"type": "none", "size": 0}}, "result": {"version": "v3.2.1", "dependencies": {"gmssl_native_lib": {"available": true, "version": "GmSSL 3.1.1", "path": "/Users/cyx/.gmssl_3.1.1_install/lib/libgmssl.3.1.dylib"}, "external_mu": {"available": true, "via": "cryptography sign_mu/verify_mu", "cryptography": "50.0.1"}, "cryptography": "50.0.1", "rich": "15.0.0", "click": "8.0.4", "pqc": "available (ML-KEM-768/1024, ML-DSA-44/65/87); external-mu ok", "kms_sdks": {"kms aws": "not installed", "kms tencentcloud": "not installed", "kms aliyun": "not installed", "kms huawei": "not installed", "kms google": "not installed", "kms vault": "not installed", "kms azure": "not installed"}}}, "runtime": {"request_id": "e05f7c02-2d02-4dba-8f5b-f292cd502b6a", "timestamp": "2026-09-02T19:06:26.624378+08:00", "duration_ms": 2.784, "host": "MacM2Max-2.local", "version": "v3.2.1"}}

生成随机字符串

支持的参数

❯ easy_encryption_tool random-str --help
Usage: main.py random-str [OPTIONS]

Options:
  -l, --length INTEGER RANGE  最小生成一个字节字符串,最大长度由系统最大整型值决定  [default: 32;
                              1<=x<=9223372036854775807]
  -o, --output-file TEXT      指定输出的文件,文件需要具有可写权限
  --help                      Show this message and exit.

直接输出到 stdout

# -l指定随机字符串的长度为32字节
❯ easy_encryption_tool random-str -l 32

------ 632aebf88dfe8f93 begin@2024-04-04_15:01:23.987 ------
qBg@G%Tp((@2h81tg@9II7#0Su4`B06$
------ 632aebf88dfe8f93 took 0.049 milli-seconds to execute ------

输出到文件

❯ easy_encryption_tool random-str -l 37 -o test_random

------ 71a2d32b0816349f begin@2024-04-04_15:24:22.476 ------
write to test_random success
------ 71a2d32b0816349f took 0.299 milli-seconds to execute ------

❯ cat test_random
_9@mL1`D2#NZz5m@!X7sdHKqQEowM6%o3E`bj

当指定的文件不可写时

❯ easy_encryption_tool random-str -l 37 -o test_random

------ 0e4094ce6a4fe22c begin@2024-04-04_15:25:49.125 ------
try write to test_random failed
------ 0e4094ce6a4fe22c took 0.030 milli-seconds to execute ------

AES对称加密算法

支持的命令参数

❯ easy_encryption_tool aes --help
 Usage: eet aes [OPTIONS]                                                       
                                                                                
 AES encrypt/decrypt. Encrypt: each missing key/IV piece (-k/-v or b64          
 variants) is generated from full-entropy CSPRNG bytes and output as base64.    
 Decrypt: requires explicit key/IV (--key-b64/--iv-b64 or -k/-v). Input:        
 plaintext (-i), base64 (-e), or file (-f).                                     
                                                                                
╭─ Options ────────────────────────────────────────────────────────────────────╮
│    --mode               -m  [cbc|gcm]          AES mode: cbc or gcm          │
│                                                [default: cbc]                │
│    --key                -k  TEXT               Key string (normalized to 32  │
│                                                bytes / 256-bit,              │
│                                                CipherHUB-compatible).        │
│                                                Encrypt: a missing key is     │
│                                                randomly generated (base64 in │
│                                                output); decrypt requires it. │
│                                                The CipherHUB web preset key  │
│                                                applies only when passed      │
│                                                explicitly                    │
│    --iv-nonce           -v  TEXT               CBC uses IV (16 bytes); GCM   │
│                                                uses nonce (12 bytes).        │
│                                                Encrypt: a missing IV/nonce   │
│                                                is randomly generated (base64 │
│                                                in output); decrypt requires  │
│                                                it                            │
│    --aad                    TEXT               GCM additional authenticated  │
│                                                data (AAD), default:          │
│                                                "密码学人 CipherHUB 默认 AAD  │
│                                                数据" [default: 密码学人      │
│                                                CipherHUB 默认 AAD 数据]      │
│    --random-key-iv      -r                     Force both key and IV/nonce   │
│                                                random (encrypt only). On     │
│                                                encrypt any missing           │
│                                                -k/-v/--key-b64/--iv-b64      │
│                                                piece is randomly generated   │
│                                                anyway and shown as base64;   │
│                                                use --key-b64/--iv-b64 for    │
│                                                decrypt. Mutually exclusive   │
│                                                with                          │
│                                                -k/-v/--key-b64/--iv-b64.     │
│    --key-b64                TEXT               Base64 key bytes (must decode │
│                                                to 32 bytes). Use for decrypt │
│                                                with key from encrypt -r      │
│                                                output. Mutually exclusive    │
│                                                with -k                       │
│    --iv-b64                 TEXT               Base64 IV/nonce bytes (CBC    │
│                                                16, GCM 12). Use for decrypt  │
│                                                with IV from encrypt -r       │
│                                                output. Mutually exclusive    │
│                                                with -v                       │
│    --action             -A  [encrypt|decrypt]  Action: encrypt or decrypt    │
│                                                [default: encrypt]            │
│ *  --input-data         -i  TEXT               Input data. Encrypt:          │
│                                                text/base64/file. Decrypt:    │
│                                                base64/file [required]        │
│    --is-base64-encoded  -e                     Interpret -i as base64 data   │
│                                                (mutually exclusive with -f)  │
│    --is-a-file          -f                     Interpret -i as file path     │
│                                                (mutually exclusive with -e)  │
│    --input-limit        -l  INTEGER            Max non-file input size in MB │
│                                                [default: 1]                  │
│    --output-file        -o  TEXT               Output file path (required    │
│                                                with -f)                      │
│    --no-force                                  Do not overwrite an existing  │
│                                                output file                   │
│    --gcm-pad                                   [GCM only] Enable PKCS#7      │
│                                                padding before encrypt and    │
│                                                unpadding after decrypt.      │
│                                                Default is no padding;        │
│                                                encrypt and decrypt must both │
│                                                use or both omit --gcm-pad.   │
│                                                File decrypt with --gcm-pad   │
│                                                loads entire file into        │
│                                                memory; large files may cause │
│                                                OOM.                          │
│    --pretty-json                               Output colored pretty JSON    │
│                                                (default)                     │
│    --json                                      Output single-line JSON (use  │
│                                                with jq for field extraction) │
│    --help                                      Show this message and exit.   │
╰──────────────────────────────────────────────────────────────────────────────╯

关于密钥、IV和模式的预设

  • 加密模式:仅支持 CBC 模式和 GCM 模式
  • 填充规则:CBC 模式始终按 PKCS#7 填充;GCM 模式默认不填充(与 CipherHUB stream_cipher 兼容),若需填充可加 --gcm-pad,加密与解密需一致使用
  • 密钥:长度必须恰好 32 字节(256 位)。加密时完全不给则随机生成并以 base64 输出;给了但不足 32 字节会被拒绝(2.8.1 起不再随机补齐——补齐过的密钥无法复现,密文将永远解不开);超过 32 字节会截断并警告
  • IV:CBC 模式下时 IV 长度默认 16 字节,GCM 模式下 Nonce 长度默认 12 字节(其中 4 字节预留作为计数器,由算法自行处理);与密钥同理——不给则加密时随机生成,给短了拒绝,给长了截断并警告

关于输入数据的预设

加密行为支持三种数据输入方式:

  • 字符串如:hello,world
  • Base64 编码的字节流如:aGVsbG8sd29ybGQK(生成的 shell 命令:echo "hello,world"|base64)
  • 文件名路径:~/data/test_plain.txt

解密行为支持两种数据输入方式:

  • Base64 编码的字节流如:/hEP3J5KHZgNnCeBD/W5MQ==
  • 文件名路径:~/data/test_cipher.bin

指定密钥和 IV

使用默认的密钥

# 加密hello,world,密钥和 iv 均为默认数据
❯ easy_encryption_tool aes -m cbc -a encrypt -i hello,world

------ 15ec713c1b8c0ef3 begin@2024-04-04_15:29:25.203 ------
plain size:11
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvvvvvv
cipher size:16
cipher:PcgHm88aPtUjwVx+SDvMqw==
auth_tag_size:0
auth_tag:
------ 15ec713c1b8c0ef3 took 26.874 milli-seconds to execute ------

# 解密hello,world
❯ easy_encryption_tool aes -m cbc -a decrypt -i PcgHm88aPtUjwVx+SDvMqw== -e

------ fb11b7f46716698e begin@2024-04-04_15:29:40.648 ------
cipher size:16
plain size:11
str plain:hello,world
------ fb11b7f46716698e took 13.754 milli-seconds to execute ------

使用随机生成的密钥

# 加密 -r 表示随机生成密钥和 IV
❯ easy_encryption_tool aes -m cbc -a encrypt -i hello,world -r

------ d39dbe0c997a868b begin@2024-04-04_15:29:54.358 ------
plain size:11
key:Ta9M^p)+L1+_L^26!Xmcs6AR2^3p_5FY
iv:9*H`JW(dzpi5HBd0
cipher size:16
cipher:h7lMpOimKxO0zr7AMVsI9w==
auth_tag_size:0
auth_tag:
------ d39dbe0c997a868b took 14.258 milli-seconds to execute ------

# 解密
# -k 和 -v 的值使用引号是为了预防里面带有特殊 shell 命令的字符比如‘&’、‘!’等等
❯ easy_encryption_tool aes -m cbc -a decrypt -i h7lMpOimKxO0zr7AMVsI9w== -e -k 'Ta9M^p)+L1+_L^26!Xmcs6AR2^3p_5FY' -v '9*H`JW(dzpi5HBd0'

------ 1332e834884e2b0e begin@2024-04-04_15:31:06.666 ------
cipher size:16
plain size:11
str plain:hello,world
------ 1332e834884e2b0e took 15.691 milli-seconds to execute ------

使用指定的密钥

密钥或 iv 长度不够时会自动填充
# 加密,此时 key(1234) 和 iv(1234) 长度都不足
❯ easy_encryption_tool aes -m cbc -a encrypt -i hello,world -k 1234 -v 4321

------ c5abaa3af64a5f6c begin@2024-04-04_15:31:34.231 ------
plain size:11
key:1234g6Z0GE$Z@ybb^IIb3FN5Ux%BE=00
iv:4321nJ4j*Nud(yH4
cipher size:16
cipher:dHJKRtSi8KsCe6ZFltF0kA==
auth_tag_size:0
auth_tag:
------ c5abaa3af64a5f6c took 14.648 milli-seconds to execute ------
                
# 解密
❯ easy_encryption_tool aes -m cbc -a decrypt -i dHJKRtSi8KsCe6ZFltF0kA== -e -k '1234g6Z0GE$Z@ybb^IIb3FN5Ux%BE=00' -v '4321nJ4j*Nud(yH4'

------ 7c2018bd08e58a63 begin@2024-04-04_15:32:16.014 ------
cipher size:16
plain size:11
str plain:hello,world
------ 7c2018bd08e58a63 took 14.343 milli-seconds to execute ------
密钥或iv超长时会自动截取
# 加密,此时密钥和 iv 的长度都超长
❯ easy_encryption_tool aes -m cbc -a encrypt -i hello,world -k 12345678901234567890123456789012abcde -v 1234567890123456abcde

------ 8ff4bd52df0a0865 begin@2024-04-04_15:32:31.104 ------
plain size:11
key:12345678901234567890123456789012
iv:1234567890123456
cipher size:16
cipher:wOXlD3Ie7xiQh81aR8N1tQ==
auth_tag_size:0
auth_tag:
------ 8ff4bd52df0a0865 took 13.849 milli-seconds to execute ------

# 解密
❯ easy_encryption_tool aes -m cbc -a decrypt -i wOXlD3Ie7xiQh81aR8N1tQ== -e -k 12345678901234567890123456789012 -v 1234567890123456

------ 50ea907cc74207ad begin@2024-04-04_15:32:46.937 ------
cipher size:16
plain size:11
str plain:hello,world
------ 50ea907cc74207ad took 13.690 milli-seconds to execute ------

指定明文

输入字符串作为明文

# 加密
❯ easy_encryption_tool aes -m cbc -a encrypt -i hello,world

------ e6dc33dc9ca747d0 begin@2024-04-04_15:33:05.505 ------
plain size:11
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvvvvvv
cipher size:16
cipher:PcgHm88aPtUjwVx+SDvMqw==
auth_tag_size:0
auth_tag:
------ e6dc33dc9ca747d0 took 14.098 milli-seconds to execute ------

输入base64编码的字节流作为明文

# 加密 -e 表明输入的数据经过了 base64 编码,加密或解密时需要先将数据做 base64 解码
❯ easy_encryption_tool aes -m cbc -a encrypt -i 9H8InkmnUjgVHC8elQxThUSmzkO0tuGlP0Si4X1kmoK7azOIDoFnt8dXjeWNGb+dc7qiEBPi+jymax4i+24KBQ== -e

------ fc5b00c0a79ff88e begin@2024-04-04_15:33:17.585 ------
plain size:64
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvvvvvv
cipher size:80
cipher:ZHq7uJQjkx/2Bm5ZmrcuS/5c/s/qayDVcuWZmvsTle1RAUKyv0dvGhOVYEINmL35eSMVoT3Bx/M6lU9NGCuiM5OxyJ2VcuB30dp8GVZg0oQ=
auth_tag_size:0
auth_tag:
------ fc5b00c0a79ff88e took 14.382 milli-seconds to execute ------

输入文件作为明文

# 加密
❯ easy_encryption_tool aes -m cbc -a encrypt -i ./test_data/test_plain.txt -f -o ./tmp_cipher.bin

------ 1d5fb25a63f1ed4d begin@2024-04-04_15:33:57.461 ------
input file size:64
cipher size:80
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvvvvvv
auth_tag_size:0
auth_tag:
------ 1d5fb25a63f1ed4d took 14.859 milli-seconds to execute ------

# 查看文件大小,密文文件比明文文件多了16 字节,这是因为明文的最后一个 block 会做 PKCS#7 数据填充
❯ cat ./test_data/test_plain.txt
123456789012345612345678901234561234567890123456123456789012345
❯ ll ./test_data/test_plain.txt
-rw-r--r--  1 xxxx  staff  64 Apr  2 21:06 ./test_data/test_plain.txt
❯ ll ./tmp_cipher.bin
-rw-r--r--  1 xxxx  staff  80 Apr  4 15:33 ./tmp_cipher.bin

指定密文

输入base64编码的字节流作为密文

如果解密出来的明文直接可以以字符串方式打印
# 明文本身为 hello,world
❯ easy_encryption_tool aes -m cbc -a decrypt -i PcgHm88aPtUjwVx+SDvMqw== -e

------ 2b6a86223a0ba102 begin@2024-04-04_15:35:26.995 ------
cipher size:16
plain size:11
str plain:hello,world
------ 2b6a86223a0ba102 took 13.676 milli-seconds to execute ------
如果解密出来的密文不能以字符串方式打印
# 明文本身是字节流
❯ easy_encryption_tool aes -m cbc -a decrypt -i ZHq7uJQjkx/2Bm5ZmrcuS/5c/s/qayDVcuWZmvsTle1RAUKyv0dvGhOVYEINmL35eSMVoT3Bx/M6lU9NGCuiM5OxyJ2VcuB30dp8GVZg0oQ= -e

------ d399aa241aa6b691 begin@2024-04-04_15:35:39.781 ------
cipher size:80
plain size:64
b64 encoded plain:9H8InkmnUjgVHC8elQxThUSmzkO0tuGlP0Si4X1kmoK7azOIDoFnt8dXjeWNGb+dc7qiEBPi+jymax4i+24KBQ==
------ d399aa241aa6b691 took 13.869 milli-seconds to execute ------

输入文件作为密文

❯ easy_encryption_tool aes -m cbc -a decrypt -i ./tmp_cipher.bin -f -o ./tmp_plain.txt

------ 1f27fb444d1139b2 begin@2024-04-04_15:36:03.267 ------
input file size:80
decrypt ./tmp_cipher.bin success
write to ./tmp_plain.txt
plain size:64
------ 1f27fb444d1139b2 took 14.259 milli-seconds to execute ------

# 文件大小一致、内容一致
❯ ll ./tmp_plain.txt ./test_data/test_plain.txt
-rw-r--r--  1 xxxx  staff  64 Apr  2 21:06 ./test_data/test_plain.txt
-rw-r--r--  1 xxxx  staff  64 Apr  3 10:58 ./tmp_plain.txt
❯ cat tmp_plain.txt ./test_data/test_plain.txt
123456789012345612345678901234561234567890123456123456789012345
123456789012345612345678901234561234567890123456123456789012345

使用GCM模式

GCM 填充说明:GCM 模式默认不对明文做 PKCS#7 填充,直接加密原始数据,与 CipherHUB stream_cipher 兼容。若需 PKCS#7 填充,请加 --gcm-pad,加密与解密必须一致使用。

代码层面的预设

代码中,对于加密的明文默认使用固定的上下文数据作为验证数据

        if mode == aes_gcm_mode:
            self.__auth_data = json.dumps({
                'mode': mode, # 值为 gcm
                'obj': 'aes_operator',
            }).encode(encoding = 'utf-8')
            if action == aes_encrypt_action:
                self.__aes_gcm_obj = Cipher(algorithms.AES(self.__key), modes.GCM(self.__iv), backend = default_backend())
                self.__aes_gcm_enc_op = self.__aes_gcm_obj.encryptor()
                self.__aes_gcm_enc_op.authenticate_additional_data(self.__auth_data)

对字符串做加解密

# gcm模式加密
❯ easy_encryption_tool aes -m gcm -a encrypt -i hello,world

------ b8e914a4634acde7 begin@2024-04-04_15:36:39.558 ------
plain size:11
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvv
cipher size:16
cipher:TajM7IwxIZIoqHkU87dY7w==
auth_tag_size:16
auth_tag:df8z3ccRyGOQTluw26dIlA==
------ b8e914a4634acde7 took 14.280 milli-seconds to execute ------

对 base64 编码的字节流做加解密

# 加密
❯ easy_encryption_tool aes -m gcm -a encrypt -i 9H8InkmnUjgVHC8elQxThUSmzkO0tuGlP0Si4X1kmoK7azOIDoFnt8dXjeWNGb+dc7qiEBPi+jymax4i+24KBQ== -e

------ 7781b5bffdcef12b begin@2024-04-04_15:37:05.562 ------
plain size:64
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvv
cipher size:80
cipher:0bKoHqq6BMVP2DIPY74Ob2tGi69gVzHSZREJT3DAeCsVU52ykLcfKZIq/GD2PEkCwLLE8o37nvPK9t/pr4LStVy5unAN/EVllIvvopq2pis=
auth_tag_size:16
auth_tag:B1Jp0FuxyNXAOVAvj9S+Ow==
------ 7781b5bffdcef12b took 13.915 milli-seconds to execute ------


# 解密
❯ easy_encryption_tool aes -m gcm -a decrypt -i 0bKoHqq6BMVP2DIPY74Ob2tGi69gVzHSZREJT3DAeCsVU52ykLcfKZIq/GD2PEkCwLLE8o37nvPK9t/pr4LStVy5unAN/EVllIvvopq2pis= -e -t B1Jp0FuxyNXAOVAvj9S+Ow==

------ 5bcc82c4235dcde4 begin@2024-04-04_15:37:17.397 ------
cipher size:80
plain size:64
b64 encoded plain:9H8InkmnUjgVHC8elQxThUSmzkO0tuGlP0Si4X1kmoK7azOIDoFnt8dXjeWNGb+dc7qiEBPi+jymax4i+24KBQ==
------ 5bcc82c4235dcde4 took 13.844 milli-seconds to execute ------

对文件做加解密

# 加密
❯ easy_encryption_tool aes -m gcm -a encrypt -i ./test_data/test_plain.txt -f -o ./tmp_gcm_cipher.bin

------ 0c4605fe37eb7e4b begin@2024-04-04_15:37:45.621 ------
input file size:64
cipher size:80
key:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
iv:vvvvvvvvvvvv
auth_tag_size:16
auth_tag:krJchuyaDRYHnu5tsy8UzA==
------ 0c4605fe37eb7e4b took 14.347 milli-seconds to execute ------

# 解密
❯ easy_encryption_tool aes -m gcm -a decrypt -i ./tmp_gcm_cipher.bin -f -o tmp_gcm_plain.txt -t krJchuyaDRYHnu5tsy8UzA==

------ d181cab086ebaeaa begin@2024-04-04_15:38:00.709 ------
input file size:80
decrypt ./tmp_gcm_cipher.bin success
write to tmp_gcm_plain.txt
plain size:64
------ d181cab086ebaeaa took 14.397 milli-seconds to execute ------

tag值对解密很重要

# gcm模式正常解密
❯ easy_encryption_tool aes -m gcm -a decrypt -i TajM7IwxIZIoqHkU87dY7w== -e -t df8z3ccRyGOQTluw26dIlA==

------ 86699527d1227e39 begin@2024-04-04_15:38:22.322 ------
cipher size:16
plain size:11
str plain:hello,world
------ 86699527d1227e39 took 13.987 milli-seconds to execute ------

# 不传 gcm tag 会报错
❯ easy_encryption_tool aes -m gcm -a decrypt -i TajM7IwxIZIoqHkU87dY7w== -e

------ 11c1531f0fd5b7a8 begin@2024-04-04_15:38:32.957 ------
expected a gcm tag(16 Bytes)
------ 11c1531f0fd5b7a8 took 0.030 milli-seconds to execute ------

# 传错误的 tag 会解密失败
❯ easy_encryption_tool aes -m gcm -a decrypt -i TajM7IwxIZIoqHkU87dY7w== -e -t H7n7OzKgQyHL86zbnQ0r+g==

------ 90580b5c3649a1ba begin@2024-04-04_15:38:46.823 ------
decrypt TajM7IwxIZIoqHkU87dY7w== failed:
------ 90580b5c3649a1ba took 14.030 milli-seconds to execute ------

常用的参数合法性检查

-m 模式参数

easy_encryption_tool aes -m abc -a encrypt -i 1234
Usage: main.py aes [OPTIONS]
Try 'main.py aes --help' for help.

Error: Invalid value for '-m' / '--mode': 'abc' is not one of 'cbc', 'gcm'.

-a 动作参数

easy_encryption_tool aes -m cbc -a abc -i 1234
Usage: main.py aes [OPTIONS]
Try 'main.py aes --help' for help.

Error: Invalid value for '-a' / '--action': 'abc' is not one of 'encrypt', 'decrypt'.

-i 输入参数

字符串超限
# 这里设置最大限制为0MBytes,也就是不允许加密,这里是故意预留的
❯ easy_encryption_tool aes -m cbc -a encrypt -i 1234 -l 0

------ 5ce766f36cc28968 begin@2024-04-04_15:39:42.675 ------
the data exceeds the maximum bytes limit, limited to:0Bytes, now:4Bytes
------ 5ce766f36cc28968 took 0.023 milli-seconds to execute ------
非法的base64编码数据
# 任意构造的字符串
❯ easy_encryption_tool aes -m cbc -a encrypt -i qwert -e

------ 4844fa0e0939482d begin@2024-04-04_15:39:53.597 ------
invalid b64 encoded data:qwert
------ 4844fa0e0939482d took 0.044 milli-seconds to execute ------

# base64数据缺少字符(正确的是:ZUD3MJT3ohiimrryNW7jBw==)
❯ easy_encryption_tool aes -m cbc -a encrypt -i ZUD3MJT3ohiimrryNW7jBw -e

------ 22301b388db43f9d begin@2024-04-04_15:40:05.092 ------
invalid b64 encoded data:ZUD3MJT3ohiimrryNW7jBw
------ 22301b388db43f9d took 0.036 milli-seconds to execute ------
文件不可读
# 创建文件并设置为只可root读
sudo touch test_plain
sudo chmod 400 test_plain
# 查看文件
ll test_plain
-r--------  1 root  staff  0 Apr  3 11:29 test_plain

# 使用其他用户运行命令访问
easy_encryption_tool aes -m cbc -a encrypt -i test_plain -f
test_plain may not exist or may be unreadable
------ aes_command took 0.076 milli-seconds to execute ------
文件不可写
# 文件写权限检查失败
easy_encryption_tool aes -m cbc -a encrypt -i  tmp_gcm_plain.txt -f -o test_plain

tmp_gcm_plain.txt opened in mode rb success
test_plain may not exist or may not writable
tmp_gcm_plain.txt closed success
------ aes_command took 0.126 milli-seconds to execute ------
-e 与 -f 参数互斥
❯ easy_encryption_tool aes -m cbc -a encrypt -i test_plain -f -e

------ 75998f7a4a1364f6 begin@2024-04-04_15:40:30.038 ------
the input data cannot be used as both a file and base64 encoded data
------ 75998f7a4a1364f6 took 0.026 milli-seconds to execute ------
对文件加密或解密时,必须指定输出的文件名
# 加密不指定输出文件
❯ easy_encryption_tool aes -m gcm -a encrypt -i ./test_data/test_plain.txt -f

------ 3564874090cf12d5 begin@2024-04-04_15:40:55.522 ------
need a output file specified and writable
------ 3564874090cf12d5 took 0.074 milli-seconds to execute ------

# 解密不指定输出文件
❯ easy_encryption_tool aes -m gcm -a decrypt -i ./test_data/test_plain.txt -f -t df8z3ccRyGOQTluw26dIlA==

------ c3dee26a5649a077 begin@2024-04-04_15:41:07.541 ------
need a output file specified and writable
------ c3dee26a5649a077 took 0.084 milli-seconds to execute ------

HMAC验证码

支持的命令参数

❯ easy_encryption_tool hmac --help
                                                                                
 Usage: eet hmac [OPTIONS]                                                      
                                                                                
╭─ Options ────────────────────────────────────────────────────────────────────╮
│ *  --input-data         -i  TEXT                     Input data: text,       │
│                                                      base64, or file path    │
│                                                      [required]              │
│    --is-base64-encoded  -e                           Interpret -i as base64  │
│                                                      data (mutually          │
│                                                      exclusive with -f)      │
│    --is-a-file          -f                           Interpret -i as file    │
│                                                      path (mutually          │
│                                                      exclusive with -e)      │
│    --hash-alg           -a  [sha224|sha256|sha384|s  HMAC digest algorithm   │
│                             ha512|sha3_224|sha3_256  [default: sha256]       │
│                             |sha3_384|sha3_512|sm3]                          │
│    --key                -k  TEXT                     Key string. A missing   │
│                                                      key is randomly         │
│                                                      generated (length       │
│                                                      matches the hash digest │
│                                                      size, base64 in         │
│                                                      output); the CipherHUB  │
│                                                      web preset key applies  │
│                                                      only when passed        │
│                                                      explicitly              │
│    --random-key         -r                           Auto-generate random    │
│                                                      key (length matches     │
│                                                      digest size). Default   │
│                                                      when -k/--key-b64 not   │
│                                                      given. Mutually         │
│                                                      exclusive with          │
│                                                      -k/--key-b64.           │
│    --key-b64                TEXT                     Base64 key bytes (use   │
│                                                      for HMAC verify with    │
│                                                      key from random-key     │
│                                                      output). Mutually       │
│                                                      exclusive with -k       │
│    --input-limit        -l  INTEGER                  Max non-file input size │
│                                                      in MB [default: 1]      │
│    --pretty-json                                     Output colored pretty   │
│                                                      JSON (default)          │
│    --json                                            Output single-line JSON │
│                                                      (use with jq for field  │
│                                                      extraction)             │
│    --help                                            Show this message and   │
│                                                      exit.                   │
╰──────────────────────────────────────────────────────────────────────────────╯

关于输入数据和密钥的预设

  • 输入数据支持三种方式:字符串明文、base64 编码的字节流(-e)、文件路径(-f)
  • 密钥没有默认值:不给 -k 时自动生成随机密钥(长度对齐所选哈希算法的摘要长度),以 base64 回显在输出的 result.key,供验证方复用;显式指定 -k 时输出不回显密钥
  • 要与 CipherHUB 网页工具的默认密钥对齐,需显式传入网页端默认密钥 01234567890123456789012345678901(CLI 不会在不给 -k 时使用它)
  • SM3 需 GmSSL 原生库,且密钥长度限制为 16-64 字节

指定密钥

不指定密钥(自动随机)

❯ easy_encryption_tool hmac -i hello,world

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha256",
    "input": {
      "type": "text",
      "size": 11
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "493412f4bd78348692e9ab210427cb1c7b92b3e0125b268a67d05ed15570e9b3",
    "key": "UKAqp1XGjkPO+h/qAoogcxxSVHrkb/UOyVOhD8j8Dqk=",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "86c4917d-53bf-48ff-8f57-ea21c4d8e43f",
    "timestamp": "2026-09-01T20:43:29.963649+08:00",
    "duration_ms": 0.027,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

result.key 是本次随机生成的密钥(base64),验证同一份数据时用 --key-b64 传入即可复现。

显式指定密钥

❯ easy_encryption_tool hmac -i hello,world -k 01234567890123456789012345678901

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha256",
    "input": {
      "type": "text",
      "size": 11
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "a5e8ea8f0fbaf97fbc08841be49271b52b8c2ddb1c521e14b10608db68205220",
    "formats": {
      "hmac": "hex"
    }
  },
  "runtime": {
    "request_id": "3001aa9d-7a2c-4f91-83c1-affeea182d49",
    "timestamp": "2026-09-01T20:43:30.607722+08:00",
    "duration_ms": 0.032,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

显式给 -k 时密钥不回显,只输出 HMAC 值。

强制随机密钥

❯ easy_encryption_tool hmac -i hello,world -r

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha256",
    "input": {
      "type": "text",
      "size": 11
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "35027f23283ebc4a67b03fd05c5609deacc2cd2565ddc36ed550e39a00c04bd3",
    "key": "5z+2SDM6PstT65SY1I/pCJit3ht3sDwCVDzwgBpMhi8=",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "3e0723c0-d67d-445b-9324-7eadbc98c392",
    "timestamp": "2026-09-01T20:43:30.281768+08:00",
    "duration_ms": 0.029,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

-r 与 -k/--key-b64 互斥;不给任何密钥选项时默认走随机(同上文第一种)。

指定输入

输入字符串

❯ easy_encryption_tool hmac -i hello,world

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha256",
    "input": {
      "type": "text",
      "size": 11
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "ebeb118a5fc3115c9485573f92ef7e42a33834164ea957d874989db9bd53fce5",
    "key": "SfLNkGNbfxngQdeA0UJE5W7zZB6cij1EerRo8quhWpc=",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "97703ae4-b1c6-4504-9065-8b485e1d0223",
    "timestamp": "2026-09-01T20:45:50.508979+08:00",
    "duration_ms": 0.029,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

输入 base64 编码的字节流

❯ easy_encryption_tool hmac -i aGVsbG8sd29ybGQ= -e

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha256",
    "input": {
      "type": "binary",
      "size": 11
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "1ff87ae95b2da86edade3f51fdb3f5eb777eaa84e3edbee6acf07861f2efdd5c",
    "key": "2fbc0j3mslVyQHNzNk/fk+K+iB9L/4Y0tiaAnnQFQoc=",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "2946dc66-3945-4a6b-9e22-e5f704878c4a",
    "timestamp": "2026-09-01T20:43:31.590283+08:00",
    "duration_ms": 0.03,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

输入文件

❯ easy_encryption_tool hmac -i /tmp/eet_doc_plain.txt -f

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha256",
    "input": {
      "type": "file",
      "size": 47
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "93eb116fa254e9729d1901cacc852ff926f53a51a059df7aa901492ebd4f3050",
    "key": "4iJ7Wlv/A/SrDP/vypJPicbA4jMljZFatjJxzSCUdco=",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "e17cfec1-6d9e-46cd-8db5-513a9efbebf9",
    "timestamp": "2026-09-01T20:45:11.403918+08:00",
    "duration_ms": 0.249,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

指定哈希算法

# 支持的哈希列表:
# [sha224 | sha256 | sha384 | sha512 | sha3_224 | sha3_256 | sha3_384 | sha3_512 | sm3]

# 使用 sha512
❯ easy_encryption_tool hmac -i /tmp/eet_doc_plain.txt -f -a sha512

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha512",
    "input": {
      "type": "file",
      "size": 47
    },
    "parameters": {
      "digest_size": 64,
      "key_size": 64
    }
  },
  "result": {
    "hmac": "8909cf54de94efc9961b967604bbad4bf28a5943fe41931724a5c378065c829490dcdf3a516a82ed1a075aec9ed8a9a4dcbe3e682a6fbd7c7a911c4c0d967f1f",
    "key": "zFJXjCegRtUvA9PfQ7clS6nwuVwvlCgCjtUpcuBPM6cM/xOudgOGbTg+R44bctQGSTmX61tzosY3pNNmswe3qQ==",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "fabcf24e-43dd-4397-8d6d-93f168291063",
    "timestamp": "2026-09-01T20:43:30.938513+08:00",
    "duration_ms": 0.107,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

# 使用 sha3_256
❯ easy_encryption_tool hmac -i /tmp/eet_doc_plain.txt -f -a sha3_256

{
  "metadata": {
    "operation": "hmac",
    "algorithm": "sha3_256",
    "input": {
      "type": "file",
      "size": 47
    },
    "parameters": {
      "digest_size": 32,
      "key_size": 32
    }
  },
  "result": {
    "hmac": "76478f7367d32b2db8d7d2a0dcf04c01c609a3f85257808071c95f85017ce883",
    "key": "9Lt+8z2nqOLclPJIyUmWDmM5TXV0O9gwEYoKN3Qk1Hs=",
    "formats": {
      "hmac": "hex",
      "key": "base64"
    }
  },
  "runtime": {
    "request_id": "25cbedf7-7dc3-429f-9a3c-48a4d860425b",
    "timestamp": "2026-09-01T20:43:31.259750+08:00",
    "duration_ms": 0.102,
    "host": "MacM2Max-2.local",
    "version": "v3.0.1"
  }
}

RSA非对称密钥

支持的命令

❯ easy_encryption_tool rsa --help
Usage: main.py rsa [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  decrypt
  encrypt
  generate
  sign
  verify

生成密钥对

支持的参数

❯ easy_encryption_tool rsa generate --help
Usage: main.py rsa generate [OPTIONS]

Options:
  -s, --size [2048|3072|4096]  密钥位数  [default: 2048]
  -e, --encoding [pem|der]     密钥格式  [default: pem]
  -f, --file-name TEXT         输出密钥对的文件名前缀,最终写入数据时会创建文件并加上文件名后缀  [default:
                               demo; required]
  -p, --password TEXT          私钥密码,使用私钥时需要输入正确的密码
  -r, --random-password        是否生成私钥的随机密码,如果带上 -r 标识,则随机生成32字节的密码
  --help                       Show this message and exit.

默认生成

# 密钥长度2048位,私钥不带密码
❯ easy_encryption_tool rsa generate -f test

------ 6b89fd023be2d70e begin@2024-04-04_15:48:44.313 ------
generate test_rsa_public.pem/test_rsa_private.pem success
------ 6b89fd023be2d70e took 134.487 milli-seconds to execute ------

指定长度且指定密码

# pem格式密钥,私钥不带密码
❯ easy_encryption_tool rsa generate -f test_no_pwd_pem -s 4096 -e pem

------ 7d68ecefd4536a1c begin@2024-04-04_15:50:00.393 ------
generate test_no_pwd_pem_rsa_public.pem/test_no_pwd_pem_rsa_private.pem success
------ 7d68ecefd4536a1c took 560.056 milli-seconds to execute ------

# pem格式密钥,私钥带密码
❯ easy_encryption_tool rsa generate -f test_pwd_pem -s 4096 -e pem -p 1234567890

------ f036eed08d4188e6 begin@2024-04-04_15:51:20.417 ------
private key password:1234567890
generate test_pwd_pem_rsa_public.pem/test_pwd_pem_rsa_private_cipher.pem success
------ f036eed08d4188e6 took 341.474 milli-seconds to execute ------

# der格式密钥,私钥不带密码
❯ easy_encryption_tool rsa generate -f test_no_pwd_der -s 4096 -e der

------ e152e62cc8ff4080 begin@2024-04-04_15:51:53.004 ------
generate test_no_pwd_der_rsa_public.der/test_no_pwd_der_rsa_private.der success
------ e152e62cc8ff4080 took 620.032 milli-seconds to execute ------

# der格式密钥,私钥带密码
❯ easy_encryption_tool rsa generate -f test_pwd_der -s 4096 -e der -p 1234567890

------ 9b08b9054b7642cd begin@2024-04-04_15:52:04.209 ------
private key password:1234567890
generate test_pwd_der_rsa_public.der/test_pwd_der_rsa_private_cipher.der success
------ 9b08b9054b7642cd took 1108.390 milli-seconds to execute ------

指定长度且随机生成密码

❯ easy_encryption_tool rsa generate -f test -s 4096 -r

------ e3eba04fda53c701 begin@2024-04-04_15:53:14.570 ------
private key password:4)H(iipM9=qnUV!!16LZ3)n&YGQE@v04
generate test_rsa_public.pem/test_rsa_private_cipher.pem success
------ e3eba04fda53c701 took 300.131 milli-seconds to execute ------ 

加密与解密

支持的参数

# 加密
❯ easy_encryption_tool rsa encrypt --help
Usage: main.py rsa encrypt [OPTIONS]

Options:
  -f, --public-key TEXT           公钥文件路径  [required]
  -i, --input-data TEXT           输入数据,可以直接为字符串,也可以为
                                  base64编码的数据,base64编码的数据需要带上标识 -c  [required]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -c, --b64-encoded               输入数据是否被 base64 编码过
  -l, --input-limit INTEGER       输入内容最大长度,单位为 MB,默认为 1MB,非对称不适合直接加密过长的数据
                                  [default: 1]
  -m, --mode [oaep|pkcs1v15]      加密时的填充模式  [default: oaep; required]
  -h, --hash-mode [sha256|sha384|sha512]
                                  此参数仅在-m为 oaep 时生效  [default: sha256]
  --help                          Show this message and exit.

 # 解密
 ❯ easy_encryption_tool rsa decrypt --help
Usage: main.py rsa decrypt [OPTIONS]

Options:
  -f, --private-key TEXT          私钥文件路径  [required]
  -i, --input-data TEXT           输入的密文数据, 必须为base64编码的数据  [required]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -m, --mode [oaep|pkcs1v15]      加密时的填充模式  [default: oaep; required]
  -h, --hash-mode [sha256|sha384|sha512]
                                  此参数仅在-m为 oaep 时生效  [default: sha256]
  -p, --password TEXT             私钥密码,使用私钥时需要输入正确的密码
  --help                          Show this message and exit.

使用 PEM 密钥加解密

私钥不需要密码
# 加密
❯ easy_encryption_tool rsa encrypt -e pem -f ./test_data/test_no_pwd_pem_public.pem -i hello,world

------ 18869a5ba5f11a4f begin@2024-04-04_15:55:10.501 ------
pub key size:4096
padding mode:oaep-sha256
cipher:pQlqgAyKEdrjcdRPe90uWHIJv781VD1X0+wrVyzmf6GE1hMdEwcukflGsgkysN3jbR2btNAEfYwxmvk+b1Om/AUdtGrZNAMuCygY3Y2U6ikVRcOCdd0ZCz3Gp7NTEblifVxMR/UsK2VQ+/4Tysmslv2QFOV7Mz+uE6j/o+hTBYhR42r+tkKsAEQGB8LLfo5GC+Wjk5mU1Yt3d8bz3/55S7Wv3DhAlrD9AuiEhqv4E8JL0MgSIN26rzHnOOlkP5vRlH5lLITzier7W9inoQxpYpKdk3xa7gsRXKXVBNcaNdCn9AH/SkrfEe+bHpZcAWG7It2OyTlaAzSwmia+wYx3CgyVtzMHNU9jQrz8xnMcP1ZntxVNvoVnhn9li0H8XTCAy3p+YfYGybEqiSNeFL7cEsONO8x8y0bkqNQE9KFTba0yZNsME1JfJmQVG9IrLaIn1RAsGmPeVYCuHmwcZQCxFUc14von867Z4HewLNqnN5EzalTnVzIY4whZcwMnmp53tZKeNhh0QemuoEqWmkf4cwJHGR/KZJKi+dhB5vo0+LffXf4LzsJRAwbE9ylwEPEsjFx1BYw7jbVIb7hgZ0AZB0J2OMdov25xMWk2nYBmR6L/QFBCtw/J8t7198ZuHmHI247gl8zJ3tFEAPFw1eFOQOkIAKnSDVfnPBlTZQ8smtM=
------ 18869a5ba5f11a4f took 15.731 milli-seconds to execute ------

# 解密
❯ easy_encryption_tool rsa decrypt -e pem -f ./test_data/test_no_pwd_pem_private.pem -i pQlqgAyKEdrjcdRPe90uWHIJv781VD1X0+wrVyzmf6GE1hMdEwcukflGsgkysN3jbR2btNAEfYwxmvk+b1Om/AUdtGrZNAMuCygY3Y2U6ikVRcOCdd0ZCz3Gp7NTEblifVxMR/UsK2VQ+/4Tysmslv2QFOV7Mz+uE6j/o+hTBYhR42r+tkKsAEQGB8LLfo5GC+Wjk5mU1Yt3d8bz3/55S7Wv3DhAlrD9AuiEhqv4E8JL0MgSIN26rzHnOOlkP5vRlH5lLITzier7W9inoQxpYpKdk3xa7gsRXKXVBNcaNdCn9AH/SkrfEe+bHpZcAWG7It2OyTlaAzSwmia+wYx3CgyVtzMHNU9jQrz8xnMcP1ZntxVNvoVnhn9li0H8XTCAy3p+YfYGybEqiSNeFL7cEsONO8x8y0bkqNQE9KFTba0yZNsME1JfJmQVG9IrLaIn1RAsGmPeVYCuHmwcZQCxFUc14von867Z4HewLNqnN5EzalTnVzIY4whZcwMnmp53tZKeNhh0QemuoEqWmkf4cwJHGR/KZJKi+dhB5vo0+LffXf4LzsJRAwbE9ylwEPEsjFx1BYw7jbVIb7hgZ0AZB0J2OMdov25xMWk2nYBmR6L/QFBCtw/J8t7198ZuHmHI247gl8zJ3tFEAPFw1eFOQOkIAKnSDVfnPBlTZQ8smtM=

------ 197c89cd0b631ce0 begin@2024-04-04_15:55:40.536 ------
private key password:
key size:4096
padding mode:oaep-sha256
origin plain:hello,world
------ 197c89cd0b631ce0 took 338.602 milli-seconds to execute ------
私钥需要密码
# 加密
❯ easy_encryption_tool rsa encrypt -e pem -f ./test_data/test_pwd_pem_public.pem -i hello,world

------ e1cde686b573fb50 begin@2024-04-04_15:56:04.554 ------
pub key size:4096
padding mode:oaep-sha256
cipher:pF06oJgMvzJ8WUphoYqaccLhClQjeSiSQXbQpORXtzkAFKeSqAQwGCKLQlDeJft6bc4wxUe1hS5IM/21hOpx1HZKZyXurfeqHkOXx4ekiakqS+8MgW6x4vozQfTKUZHoDStA8chwibtWlDCAGESYj1drr1UA8cNc5I+ij+hM3voFA3zh8o6JaKLKmxvNedRk5ugJQE6lL3RHMAya5oQS5AYQTtfuLQl52G0loQIPoWWB8KgZD6iZ///I2MI8B4kEHS1O2eg897DNyHGRdf8nRjTJdecWFR7wXY0VQeV8lR2BEsPb7L15qg4lZvonpew9qII6gW5J39yLK73vbAAkpdAmpOGxvOVtztE0Tn4UFkIkOZDkH8nlj1JwhCJ5K9R+TwlkoUinFMasOUZFEvNHzbha69mVErxBQHwv6N6P4kTLOBFVDrqF1Y00ZAQ0ZjIr/s7OdJAyoHlzZkroSfkbvV2eOho3nJD8aoIYdfa1kwttJ7p027VSVMflO1jULRZ0EkT2ncgzOMjqm4fB8Se42/QGjGtKYKOOPp4uBbFuxi8ra4LWY0l0h+FYJ6wXeIcODMLuxHWK4drfJrj5IpaTYNuysmeDEDfMQZQV1WYmyfFsJtIqXFiKrQatgFtGsfYXPCNBTrXa4HVW/Ohm7vE1PKGh+e2K7VpSZ6F4nW+YmQc=
------ e1cde686b573fb50 took 15.492 milli-seconds to execute ------

# 解密 -p 指定密码
❯ easy_encryption_tool rsa decrypt -e pem -f ./test_data/test_pwd_pem_private_cipher.pem -i pF06oJgMvzJ8WUphoYqaccLhClQjeSiSQXbQpORXtzkAFKeSqAQwGCKLQlDeJft6bc4wxUe1hS5IM/21hOpx1HZKZyXurfeqHkOXx4ekiakqS+8MgW6x4vozQfTKUZHoDStA8chwibtWlDCAGESYj1drr1UA8cNc5I+ij+hM3voFA3zh8o6JaKLKmxvNedRk5ugJQE6lL3RHMAya5oQS5AYQTtfuLQl52G0loQIPoWWB8KgZD6iZ///I2MI8B4kEHS1O2eg897DNyHGRdf8nRjTJdecWFR7wXY0VQeV8lR2BEsPb7L15qg4lZvonpew9qII6gW5J39yLK73vbAAkpdAmpOGxvOVtztE0Tn4UFkIkOZDkH8nlj1JwhCJ5K9R+TwlkoUinFMasOUZFEvNHzbha69mVErxBQHwv6N6P4kTLOBFVDrqF1Y00ZAQ0ZjIr/s7OdJAyoHlzZkroSfkbvV2eOho3nJD8aoIYdfa1kwttJ7p027VSVMflO1jULRZ0EkT2ncgzOMjqm4fB8Se42/QGjGtKYKOOPp4uBbFuxi8ra4LWY0l0h+FYJ6wXeIcODMLuxHWK4drfJrj5IpaTYNuysmeDEDfMQZQV1WYmyfFsJtIqXFiKrQatgFtGsfYXPCNBTrXa4HVW/Ohm7vE1PKGh+e2K7VpSZ6F4nW+YmQc= -p 1234567890

------ cb0ebbe7b572b665 begin@2024-04-04_15:56:25.496 ------
private key password:1234567890
key size:4096
padding mode:oaep-sha256
origin plain:hello,world
------ cb0ebbe7b572b665 took 338.788 milli-seconds to execute ------

使用 DER 密钥加解密

私钥不需要密码
# 加密
❯ easy_encryption_tool rsa encrypt -e der -f ./test_data/test_no_pwd_der_public.der -i hello,world

------ 10e4568e22050ecc begin@2024-04-04_15:56:47.705 ------
pub key size:4096
padding mode:oaep-sha256
cipher:V0g9TwUetAKZOl6xwe9SL7ra1P3K2JGwTZ2NMKdZiP4zNaPxxjPPv8Me3g9qMWLNBcfU6dd+7Ia7xGb0c5Ou1/uf7D3xSoV6hU0PV/0i8feJYATgkWFO1NOt1TpIHlcYHtA9NdHEaNXR9qbY8pHyAokVRf83hyQIZMTPgpGo2GH0lJkFAOjxWOiGyPKF7GgdHjz+8rfu4R9VBUg0Wy0O1zyvTKA+b4iE6MS4zJBbzPe0H43w9OLp+TQFykrhLWXsFX+AEhdhxa7N0ebaorlQNtPnY8KuXFx0cqIzWigBcfWNTYgcjbFGLm+mo0Btin0UqDFhbC8EwdpVGnVr6ZBLCvEmyqDAuJN5UCEBQ7Jrakgot/qZ4QHPL5HdU+tNXb8KULH75fyu0A11zzHjpw2E2KRKmg1Fg9aExaim4r15T2VU1eYjZKaPV/YiYMPlqZM9udUQFTmrLRIhCUUp+fc+MJu3zR6chz6d0eSx/RdV8ik8ilKILZl7dAfRS3hC5QG0pPh54Z+MqgAZbHfTxCbjnxqoPJzMOcC+JOPEpjC2PhS6MYE70+Ub8RS1cGZmZ2z32UnanqfT9kLbR626CWUzPzZWsnMheoX5bAABDfp7AkC9BXv+ca3REAyvR8HchVkVMiIRC4dTlY4p4+uFVtOnkhUG5mzSOVGebAWOJ+ftTFY=
------ 10e4568e22050ecc took 14.792 milli-seconds to execute ------


# 解密
❯ easy_encryption_tool rsa decrypt -e der -f ./test_data/test_no_pwd_der_private.der -i V0g9TwUetAKZOl6xwe9SL7ra1P3K2JGwTZ2NMKdZiP4zNaPxxjPPv8Me3g9qMWLNBcfU6dd+7Ia7xGb0c5Ou1/uf7D3xSoV6hU0PV/0i8feJYATgkWFO1NOt1TpIHlcYHtA9NdHEaNXR9qbY8pHyAokVRf83hyQIZMTPgpGo2GH0lJkFAOjxWOiGyPKF7GgdHjz+8rfu4R9VBUg0Wy0O1zyvTKA+b4iE6MS4zJBbzPe0H43w9OLp+TQFykrhLWXsFX+AEhdhxa7N0ebaorlQNtPnY8KuXFx0cqIzWigBcfWNTYgcjbFGLm+mo0Btin0UqDFhbC8EwdpVGnVr6ZBLCvEmyqDAuJN5UCEBQ7Jrakgot/qZ4QHPL5HdU+tNXb8KULH75fyu0A11zzHjpw2E2KRKmg1Fg9aExaim4r15T2VU1eYjZKaPV/YiYMPlqZM9udUQFTmrLRIhCUUp+fc+MJu3zR6chz6d0eSx/RdV8ik8ilKILZl7dAfRS3hC5QG0pPh54Z+MqgAZbHfTxCbjnxqoPJzMOcC+JOPEpjC2PhS6MYE70+Ub8RS1cGZmZ2z32UnanqfT9kLbR626CWUzPzZWsnMheoX5bAABDfp7AkC9BXv+ca3REAyvR8HchVkVMiIRC4dTlY4p4+uFVtOnkhUG5mzSOVGebAWOJ+ftTFY=

------ ff1efcc52f4fc05e begin@2024-04-04_15:57:10.634 ------
private key password:
key size:4096
padding mode:oaep-sha256
origin plain:hello,world
------ ff1efcc52f4fc05e took 348.368 milli-seconds to execute ------
私钥需要密码
# 加密
❯ easy_encryption_tool rsa encrypt -e der -f ./test_data/test_pwd_der_public.der -i hello,world

------ d59dc4bec2be5592 begin@2024-04-04_15:57:28.114 ------
pub key size:4096
padding mode:oaep-sha256
cipher:XNNpZfpu7ZjnI1HnH/KN9BdO+/rxrtt0K4z/KRQjsAZEYZV4uMtT0o45ZHrDfr6mHNrrIlTRrt6wghIeQUojEo0uQA7auwhqJXXl3ghwTqGhKH4Lkf6q+d0X/Pn1MgRoNb3dIvWsZcpTlnqmffphOe2DzWP4By9a3yZe9rb8S/ddml7/+4BIXVqxwWcAMsAg3lpLnNHBQ853XYeDZXxKjvx4J8f2RUbp7c/xsH6eUjxZfDehcoZL7te6OrY2N342UzYKBqTQV4zbqVTm0c6V1Q7XkjFK3esgcxicitIP2UsdQjpQf9xMtOTQzErdSQk/Pd6tLxLNyKQcxDaqXR9TXA84koIfGETx434im+zhOgsUuSwS6zBARI3AlpQi14LVAbr3/6ABIEJG5QvVVVG32aVzOMrPtViRqZzcDgkyIsBOXLAQv7c5UkP+nePtnjs31IXmcO87p5zW6rweW/6Y5z1emI6RIHgLjqGKFKkaWXua0N+ZqHTEuqks2y27mFFT/g2DJN3zp5corIcjgSEqyuQbQg/hFaurrqzu+djQ1Pevjzy8rUOM7k97UYUHwjv0ITeIB/m2Rknbwsu3WH3jW6TV8Ta+Bw05ZKYT6hoFPttfno+iDVRmzRlY2QuBxHzEALtdsANzxKnpUr/vr5mEmU8Wmi87QSjp1ULMJ5lTU64=
------ d59dc4bec2be5592 took 14.696 milli-seconds to execute ------

# 解密 -p 指定密码
❯ easy_encryption_tool rsa decrypt -e der -f ./test_data/test_pwd_der_private_cipher.der -i XNNpZfpu7ZjnI1HnH/KN9BdO+/rxrtt0K4z/KRQjsAZEYZV4uMtT0o45ZHrDfr6mHNrrIlTRrt6wghIeQUojEo0uQA7auwhqJXXl3ghwTqGhKH4Lkf6q+d0X/Pn1MgRoNb3dIvWsZcpTlnqmffphOe2DzWP4By9a3yZe9rb8S/ddml7/+4BIXVqxwWcAMsAg3lpLnNHBQ853XYeDZXxKjvx4J8f2RUbp7c/xsH6eUjxZfDehcoZL7te6OrY2N342UzYKBqTQV4zbqVTm0c6V1Q7XkjFK3esgcxicitIP2UsdQjpQf9xMtOTQzErdSQk/Pd6tLxLNyKQcxDaqXR9TXA84koIfGETx434im+zhOgsUuSwS6zBARI3AlpQi14LVAbr3/6ABIEJG5QvVVVG32aVzOMrPtViRqZzcDgkyIsBOXLAQv7c5UkP+nePtnjs31IXmcO87p5zW6rweW/6Y5z1emI6RIHgLjqGKFKkaWXua0N+ZqHTEuqks2y27mFFT/g2DJN3zp5corIcjgSEqyuQbQg/hFaurrqzu+djQ1Pevjzy8rUOM7k97UYUHwjv0ITeIB/m2Rknbwsu3WH3jW6TV8Ta+Bw05ZKYT6hoFPttfno+iDVRmzRlY2QuBxHzEALtdsANzxKnpUr/vr5mEmU8Wmi87QSjp1ULMJ5lTU64= -p 1234567890

------ 806b307f230908a4 begin@2024-04-04_15:57:47.873 ------
private key password:1234567890
key size:4096
padding mode:oaep-sha256
origin plain:hello,world
------ 806b307f230908a4 took 343.988 milli-seconds to execute ------

对明文为 base64 编码的字节流做加解密

# 加密
❯ easy_encryption_tool rsa encrypt -e pem -f ./test_data/test_pwd_pem_public.pem -i krJchuyaDRYHnu5tsy8UzA== -c

------ 29fa5af7e9f84f15 begin@2024-04-04_15:58:07.029 ------
pub key size:4096
padding mode:oaep-sha256
cipher:QiztiJ21bVsNf4DyPhzDAR/E24Xqe94P398JLDakFl3LDhOA3I/XHY3v3R0GBNRrrMPtUorGHxCVmJNqc06kLCtQ4ljd015rYFRgbAtNLsaNgjsdv1Q7kHQSVa7L1BHdhNDK47svEWMQTS4jKLiKVYbCnz4ARYqe3n+vf5UtVDlrpmMNjowbdfnhnEFibCICBwnGUpssFs9X546/BzCTlqgEGdy1SpFhfX2LaqXkTQwsd3YxU9ynHZ7oVe78z/xJlEDQbPGJSfGbUtoCgQAn975hzCceC+CeDK9E7N8vu6HTv9K3vMNRHTOweRWuGxJKKjzVLSXRcDjkXynJPPe6yuyJdFnsoSHWuOsyqPrjJJC+2RvrkW24RlIEMnVEqLReD8/OnZEEw4CZF9xqplS7yRN/khaYM4MxD9qcxAIYgpg2wq6QngtabU+nGtQSfjKIkXlXnbvqMcLI1pS0TtG5vUeNSzc3Ll8g9CxvMrA/T/vUjz9d60fsGpHbjZezpsQdI8Us60BMxUWgFZ6x/ME5HkMmtXYfvi0/aNKWXymgHtVxqeM9hJaQ6MX1zNZRPe4MMHu3xJgATAbVc7GldgV+d2gZm2cLzZaTTB4ARcAARSKPgbskmIQ2buNRs2/ogjvtG72jilOCmSPKZom0VPHkrLzL4csxgxSd2M5N4cu6+Po=
------ 29fa5af7e9f84f15 took 15.584 milli-seconds to execute ------

# 解密 -p 指定密码
❯ easy_encryption_tool rsa decrypt -e pem -f ./test_data/test_pwd_pem_private_cipher.pem -i QiztiJ21bVsNf4DyPhzDAR/E24Xqe94P398JLDakFl3LDhOA3I/XHY3v3R0GBNRrrMPtUorGHxCVmJNqc06kLCtQ4ljd015rYFRgbAtNLsaNgjsdv1Q7kHQSVa7L1BHdhNDK47svEWMQTS4jKLiKVYbCnz4ARYqe3n+vf5UtVDlrpmMNjowbdfnhnEFibCICBwnGUpssFs9X546/BzCTlqgEGdy1SpFhfX2LaqXkTQwsd3YxU9ynHZ7oVe78z/xJlEDQbPGJSfGbUtoCgQAn975hzCceC+CeDK9E7N8vu6HTv9K3vMNRHTOweRWuGxJKKjzVLSXRcDjkXynJPPe6yuyJdFnsoSHWuOsyqPrjJJC+2RvrkW24RlIEMnVEqLReD8/OnZEEw4CZF9xqplS7yRN/khaYM4MxD9qcxAIYgpg2wq6QngtabU+nGtQSfjKIkXlXnbvqMcLI1pS0TtG5vUeNSzc3Ll8g9CxvMrA/T/vUjz9d60fsGpHbjZezpsQdI8Us60BMxUWgFZ6x/ME5HkMmtXYfvi0/aNKWXymgHtVxqeM9hJaQ6MX1zNZRPe4MMHu3xJgATAbVc7GldgV+d2gZm2cLzZaTTB4ARcAARSKPgbskmIQ2buNRs2/ogjvtG72jilOCmSPKZom0VPHkrLzL4csxgxSd2M5N4cu6+Po= -p 1234567890

------ d1f6350d34acf14e begin@2024-04-04_15:58:25.431 ------
private key password:1234567890
key size:4096
padding mode:oaep-sha256
b64 encoded plain:krJchuyaDRYHnu5tsy8UzA==
------ d1f6350d34acf14e took 344.681 milli-seconds to execute ------

加密模式设置

OAEP模式
# 加密
❯ easy_encryption_tool rsa encrypt -e pem -f ./test_data/test_no_pwd_pem_public.pem -i hello,world -m oaep

------ 5d4c86b12cac7641 begin@2024-04-04_15:58:41.153 ------
pub key size:4096
padding mode:oaep-sha256
cipher:LmYOuAO+zP1qCjivWUH7/EM81/2pDNK5t7JmRXW1GvhElRCa0uKTvEYa/Ncsoqv+zpbxo3O6j9K3YkGbO6rbi2DasYSKCX6DGvMNd348onbEiLZEpRMCGG03PpTpoargFZJhsnUQ6MvFPEpML9Om8EbjAwMG+xukuKV2Vak/6GmO8XQfsr6C+1hzhXqBggorJPyjpGZfypQO3Cx38puIpGC+TAewXZNMcBiVU3MTFvVfPk/vqlzYU68TXHGIIsKFKQG35iOSJA3bXr/FLwor3yAGdk7VS2e1kAYnuceUW9WN4FKb+ThRGRiDepJmFPM3TN9ZEEbdDH+wIZO7MkmKD4RBUgBO0RSDMIP8x8LxKN05xKqRxcrFbx5UKfurf1vAi4Hu+AP+e3kL/2UlvmHfLwmVYMT4Quzy414T/R43cNe9eH8KCypNjV5bFqdUyxJ4u7mC0f+S7PD1oTB6vhwsMOXH6tadhd7LpzpUrEyH6DLhukRIuo72IIdGnXNlB9d4yklxCPfvg9lj/irmdJKaq0MSbm1mZCp3J6R+sd0iKXakZnkPU7YLjwz92S7a1gSwfEpzBfsQZcuqs2BSN/iOEWMEB1XVGZrsbv5Tpp8APo/scGLBHmyk7Q/mDgsaNXrrGiQw0NfU4ZPzaFlvL2AC6HVE0YK4Nm4CIAXy+m2hItM=
------ 5d4c86b12cac7641 took 14.201 milli-seconds to execute ------

# 解密
❯ easy_encryption_tool rsa decrypt -e pem -f test_data/test_no_pwd_pem_private.pem -m oaep -i LmYOuAO+zP1qCjivWUH7/EM81/2pDNK5t7JmRXW1GvhElRCa0uKTvEYa/Ncsoqv+zpbxo3O6j9K3YkGbO6rbi2DasYSKCX6DGvMNd348onbEiLZEpRMCGG03PpTpoargFZJhsnUQ6MvFPEpML9Om8EbjAwMG+xukuKV2Vak/6GmO8XQfsr6C+1hzhXqBggorJPyjpGZfypQO3Cx38puIpGC+TAewXZNMcBiVU3MTFvVfPk/vqlzYU68TXHGIIsKFKQG35iOSJA3bXr/FLwor3yAGdk7VS2e1kAYnuceUW9WN4FKb+ThRGRiDepJmFPM3TN9ZEEbdDH+wIZO7MkmKD4RBUgBO0RSDMIP8x8LxKN05xKqRxcrFbx5UKfurf1vAi4Hu+AP+e3kL/2UlvmHfLwmVYMT4Quzy414T/R43cNe9eH8KCypNjV5bFqdUyxJ4u7mC0f+S7PD1oTB6vhwsMOXH6tadhd7LpzpUrEyH6DLhukRIuo72IIdGnXNlB9d4yklxCPfvg9lj/irmdJKaq0MSbm1mZCp3J6R+sd0iKXakZnkPU7YLjwz92S7a1gSwfEpzBfsQZcuqs2BSN/iOEWMEB1XVGZrsbv5Tpp8APo/scGLBHmyk7Q/mDgsaNXrrGiQw0NfU4ZPzaFlvL2AC6HVE0YK4Nm4CIAXy+m2hItM=

------ 9f151c4c9f56af86 begin@2024-04-04_15:59:05.700 ------
private key password:
key size:4096
padding mode:oaep-sha256
origin plain:hello,world
------ 9f151c4c9f56af86 took 346.121 milli-seconds to execute ------
PKCS1v15 模式
# 加密
❯ easy_encryption_tool rsa encrypt -e pem -f ./test_data/test_no_pwd_pem_public.pem -i hello,world -m pkcs1v15

------ 875086be5059242c begin@2024-04-04_15:59:19.282 ------
pub key size:4096
padding mode:pkcs1v15
cipher:i1hVnoQsWAQK4sftuvg08Fq1dzm3o5BRNb78K6gBGVwsu1a/gSFGwIqSOa22ONlZ0cnPu7v/mZAVOi8/tXa1++JrmpnyoZTQ3vATkXK8WG6Q6Dw/dLKUFvsRv04hxMI2ttSMNqFsiRRnCy1qx2m4PFPPuZFniuT4i9hutGn4br+d5e1DtyLxsSmefKk4BJn0Rzgzv3ImeBmT0znTJ5VN2SI/WRHlvc6KmtnQ1xD2/2kkMycPzLguL+XXc+ie/sNg3Y0CelQcXOxonAnkQcXKpzQL7+pONVDHIJvRRXjv0nUWhTay+KWPApfB+BZ0MkI03oW0divZXohI5pWa7n4Gvw1qN+Kvt3BAmBK64LvlKFzZF553re5fMKodhrK/yhIsCtWYjsrgEz+5UAmavwH6dgTrIpssfSQDaUlWwVQRG/pG+jbxkKZ1Y7SX1SAznS4Jb3xKFeWN7ulPLJIe3Zro4VxihW0KgChDFrnVtpZLuXq98mVR+v/L2HaCzNRCY39soYZZywt3IhP2ZDVoCGpVQWQ8y69pbCKfCfiOheRf1j7VYtIOATT2kNGJrVnBwZvXBfQ2Mp3y9UPIud+WAkS2s6bha1QBF/YX72xtZoiICLZZmrmXN3DdGWy1y8SM3mI75s2GsqjF6JeN2iNoLtDy2tpREH78MujjnSjMSCP78wY=
------ 875086be5059242c took 14.024 milli-seconds to execute ------

# 解密
❯ easy_encryption_tool rsa decrypt -e pem -f test_data/test_no_pwd_pem_private.pem -m pkcs1v15 -i i1hVnoQsWAQK4sftuvg08Fq1dzm3o5BRNb78K6gBGVwsu1a/gSFGwIqSOa22ONlZ0cnPu7v/mZAVOi8/tXa1++JrmpnyoZTQ3vATkXK8WG6Q6Dw/dLKUFvsRv04hxMI2ttSMNqFsiRRnCy1qx2m4PFPPuZFniuT4i9hutGn4br+d5e1DtyLxsSmefKk4BJn0Rzgzv3ImeBmT0znTJ5VN2SI/WRHlvc6KmtnQ1xD2/2kkMycPzLguL+XXc+ie/sNg3Y0CelQcXOxonAnkQcXKpzQL7+pONVDHIJvRRXjv0nUWhTay+KWPApfB+BZ0MkI03oW0divZXohI5pWa7n4Gvw1qN+Kvt3BAmBK64LvlKFzZF553re5fMKodhrK/yhIsCtWYjsrgEz+5UAmavwH6dgTrIpssfSQDaUlWwVQRG/pG+jbxkKZ1Y7SX1SAznS4Jb3xKFeWN7ulPLJIe3Zro4VxihW0KgChDFrnVtpZLuXq98mVR+v/L2HaCzNRCY39soYZZywt3IhP2ZDVoCGpVQWQ8y69pbCKfCfiOheRf1j7VYtIOATT2kNGJrVnBwZvXBfQ2Mp3y9UPIud+WAkS2s6bha1QBF/YX72xtZoiICLZZmrmXN3DdGWy1y8SM3mI75s2GsqjF6JeN2iNoLtDy2tpREH78MujjnSjMSCP78wY=

------ d5096f43a1dd5d65 begin@2024-04-04_15:59:37.216 ------
private key password:
key size:4096
padding mode:pkcs1v15
origin plain:hello,world
------ d5096f43a1dd5d65 took 348.221 milli-seconds to execute ------

签名与验签

支持的参数

# 签名
❯ easy_encryption_tool rsa sign --help
Usage: main.py rsa sign [OPTIONS]

Options:
  -f, --private-key TEXT          私钥文件路径  [required]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -m, --mode [pss|pkcs1v15]       签名时的填充模式  [default: pss; required]
  -h, --hash-mode [sha256|sha384|sha512]
                                  签名时的哈希算法  [default: sha256]
  -p, --password TEXT             私钥密码,使用私钥时需要输入正确的密码
  -i, --input-data TEXT           需要被签名的数据  [required]
  -c, --b64-encoded               输入数据是否被 base64 编码过
  --help                          Show this message and exit.

# 验签
❯ easy_encryption_tool rsa verify --help
Usage: main.py rsa verify [OPTIONS]

Options:
  -f, --public-key TEXT           公钥文件路径  [required]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -m, --mode [pss|pkcs1v15]       签名时的填充模式  [default: pss; required]
  -h, --hash-mode [sha256|sha384|sha512]
                                  签名时的哈希算法  [default: sha256]
  -i, --input-data TEXT           需要被签名的数据  [required]
  -c, --b64-encoded               输入数据是否被 base64 编码过
  -s, --signature TEXT            base64 编码过的签名值
  --help                          Show this message and exit.

PSS模式

# 签名 -p 指定密码
❯ easy_encryption_tool rsa sign -e der -f ./test_data/test_pwd_der_private_cipher.der -m pss -i hello,world -p 1234567890

------ 9238d47e0e2636f1 begin@2024-04-04_16:01:35.674 ------
key size:4096
signature:74bd0807319b4b7c58dc40eaf58efee853eb5d506079ebe8aa3e76350d42ea88c4560c4e732911cca4cd101da6b5b712fae4005bd207d88fcc87761c5c0942f932b9f5773814b91c68c91b23fd623681a069fd29d86c1c89b080b35cf1f45024bf92fdfade2b9536603f5ae40ee0d1350eae686ba1b02954efd8f2b43226228247ce8d5d9c1bbebb97aa77eb52c5a62fbf8bd46e531abf3683487ce5f18cb48f2f175398861f579ea3f38281fc74c7d26942a890fbf3f7c089c553fb632058e7d553c9fc3f4126433cd126067df935008227eaa96b4b7fcb01621d1d553d58070b656aaf2e6d28eb062e5643c639261d908bfd57542ed06e18bfd1419f300582d571c8f461422f684ffd9a68584fd164667f94e9775024cfe635a207297c8a3f1e078652c45c92c7d5ac2a10b6541b2aaaa30e926496caae06effe280bc275ea6b34cf83f3f2ce141acfbce1e03d11071cd9e177be28855fe108ef25ae0ba42db67e9992e3fa0072f92dd8843c666707685f49a10fba0f5719b752025893b272f8171951e007f1527b0320c62e1e9d6814e8de43084e51f917d52047a856576e6cc608576f4d99f4a8e9b237be7c576cf30cb8f97b69e85be2a6e5911f1105555778d122351691d434d40e3742278c54e71c8eac4bbb59918e3ffd3c162d25f0d1dff36e17c3ced4af449f5d06195f9a3328f1c24bd7b52aa49d8727e1894ad2
----------------
base64 encoded:dL0IBzGbS3xY3EDq9Y7+6FPrXVBgeevoqj52NQ1C6ojEVgxOcykRzKTNEB2mtbcS+uQAW9IH2I/Mh3YcXAlC+TK59Xc4FLkcaMkbI/1iNoGgaf0p2GwcibCAs1zx9FAkv5L9+t4rlTZgP1rkDuDRNQ6uaGuhsClU79jytDImIoJHzo1dnBu+u5eqd+tSxaYvv4vUblMavzaDSHzl8Yy0jy8XU5iGH1eeo/OCgfx0x9JpQqiQ+/P3wInFU/tjIFjn1VPJ/D9BJkM80SYGffk1AIIn6qlrS3/LAWIdHVU9WAcLZWqvLm0o6wYuVkPGOSYdkIv9V1Qu0G4Yv9FBnzAFgtVxyPRhQi9oT/2aaFhP0WRmf5Tpd1Akz+Y1ogcpfIo/HgeGUsRcksfVrCoQtlQbKqqjDpJklsquBu/+KAvCdeprNM+D8/LOFBrPvOHgPREHHNnhd74ohV/hCO8lrgukLbZ+mZLj+gBy+S3YhDxmZwdoX0mhD7oPVxm3UgJYk7Jy+BcZUeAH8VJ7AyDGLh6daBTo3kMITlH5F9UgR6hWV25sxghXb02Z9Kjpsje+fFds8wy4+Xtp6FvipuWRHxEFVVd40SI1FpHUNNQON0InjFTnHI6sS7tZkY4//TwWLSXw0d/zbhfDztSvRJ9dBhlfmjMo8cJL17UqpJ2HJ+GJStI=
mode:pss-sha256
------ 9238d47e0e2636f1 took 348.185 milli-seconds to execute ------

# 验签
❯ easy_encryption_tool rsa verify -e der -f ./test_data/test_pwd_der_public.der -m pss -s dL0IBzGbS3xY3EDq9Y7+6FPrXVBgeevoqj52NQ1C6ojEVgxOcykRzKTNEB2mtbcS+uQAW9IH2I/Mh3YcXAlC+TK59Xc4FLkcaMkbI/1iNoGgaf0p2GwcibCAs1zx9FAkv5L9+t4rlTZgP1rkDuDRNQ6uaGuhsClU79jytDImIoJHzo1dnBu+u5eqd+tSxaYvv4vUblMavzaDSHzl8Yy0jy8XU5iGH1eeo/OCgfx0x9JpQqiQ+/P3wInFU/tjIFjn1VPJ/D9BJkM80SYGffk1AIIn6qlrS3/LAWIdHVU9WAcLZWqvLm0o6wYuVkPGOSYdkIv9V1Qu0G4Yv9FBnzAFgtVxyPRhQi9oT/2aaFhP0WRmf5Tpd1Akz+Y1ogcpfIo/HgeGUsRcksfVrCoQtlQbKqqjDpJklsquBu/+KAvCdeprNM+D8/LOFBrPvOHgPREHHNnhd74ohV/hCO8lrgukLbZ+mZLj+gBy+S3YhDxmZwdoX0mhD7oPVxm3UgJYk7Jy+BcZUeAH8VJ7AyDGLh6daBTo3kMITlH5F9UgR6hWV25sxghXb02Z9Kjpsje+fFds8wy4+Xtp6FvipuWRHxEFVVd40SI1FpHUNNQON0InjFTnHI6sS7tZkY4//TwWLSXw0d/zbhfDztSvRJ9dBhlfmjMo8cJL17UqpJ2HJ+GJStI= -i hello,world

------ 8e8b995bbc527e67 begin@2024-04-04_16:02:01.136 ------
verify success
key size:4096
mode:pss-sha256
------ 8e8b995bbc527e67 took 14.193 milli-seconds to execute ------

PKCS1v15模式

# 签名 -p 指定密码
❯ easy_encryption_tool rsa sign -e pem -f ./test_data/test_pwd_pem_private_cipher.pem -i hello,world -p 1234567890

------ c12c59d278e72bb6 begin@2024-04-04_16:02:15.070 ------
key size:4096
signature:8590c16fd7349f7da4b845ab56c0fd786cd0f5bd4c60b8508d571f9c1da8a6f647c6b283a593ce3a8d77bf052f8eef2752058cb653faf434b7e04e4b49248d2d55815616c0e9e4e4196186bc749831616ab66a815f82bc6414d9469790aabb987cdf76b2594e586c65512042aa70f04c6c5ddf9d2038cd01971d36829e3342710e3221eb83f0299baa876df8fa43f76b6bad7ec0a28e30d77f5bdbae132f880ee2234bd5de82ae1e7c00fcb20d04f5c65e5d79a9b64f3776868139581b1ba3cf8167ca2e893330b4a49f2a5c0cd9bd5f331d270dbd3aacc6fba492ab7cce3fe78ec2f7b82d339b9ab90b89bbed8fe5f123f26709a4777dee8df500bf6d4d7178c25889c90b4d0826a47a85556958041aeb5e3609abe315d286d2804eacda85af2bbdfab943206150bd651fd0cb5106ff9b03636dcd2b5ab4d2186fe48241802ad0c8a4313d8bc29ff5c36fa0cffad5e566f3b47b3564b2739685e5ca881c3729fc300911f62b95c36eced3ebb6260997ba16b614599d809df71010a94ada31fa1db0342b632826b57599a8227ce18a44565de61e23e96b5d413702648173ada70f7c3d46599357edb4b2926f5824eef4a5960eae06c236c7cf1a8890ff67365b1aaf778423b99e641ffd56553d8196b4ed40b11ae6e804f8623fc9e3842f248394b61d1886c550d5e20c4e9d3c8b071da6f55569740f3b633cfd99167442a9f5
----------------
base64 encoded:hZDBb9c0n32kuEWrVsD9eGzQ9b1MYLhQjVcfnB2opvZHxrKDpZPOOo13vwUvju8nUgWMtlP69DS34E5LSSSNLVWBVhbA6eTkGWGGvHSYMWFqtmqBX4K8ZBTZRpeQqruYfN92sllOWGxlUSBCqnDwTGxd350gOM0Blx02gp4zQnEOMiHrg/Apm6qHbfj6Q/dra61+wKKOMNd/W9uuEy+IDuIjS9Xegq4efAD8sg0E9cZeXXmptk83doaBOVgbG6PPgWfKLokzMLSknypcDNm9XzMdJw29OqzG+6SSq3zOP+eOwve4LTObmrkLibvtj+XxI/JnCaR3fe6N9QC/bU1xeMJYickLTQgmpHqFVWlYBBrrXjYJq+MV0obSgE6s2oWvK736uUMgYVC9ZR/Qy1EG/5sDY23NK1q00hhv5IJBgCrQyKQxPYvCn/XDb6DP+tXlZvO0ezVksnOWheXKiBw3KfwwCRH2K5XDbs7T67YmCZe6FrYUWZ2AnfcQEKlK2jH6HbA0K2MoJrV1magifOGKRFZd5h4j6WtdQTcCZIFzracPfD1GWZNX7bSykm9YJO70pZYOrgbCNsfPGoiQ/2c2Wxqvd4QjuZ5kH/1WVT2BlrTtQLEa5ugE+GI/yeOELySDlLYdGIbFUNXiDE6dPIsHHab1VWl0DztjPP2ZFnRCqfU=
mode:pss-sha256
------ c12c59d278e72bb6 took 343.034 milli-seconds to execute ------

# 验签
❯ easy_encryption_tool rsa verify -e pem -f ./test_data/test_pwd_pem_public.pem -i hello,world -s hZDBb9c0n32kuEWrVsD9eGzQ9b1MYLhQjVcfnB2opvZHxrKDpZPOOo13vwUvju8nUgWMtlP69DS34E5LSSSNLVWBVhbA6eTkGWGGvHSYMWFqtmqBX4K8ZBTZRpeQqruYfN92sllOWGxlUSBCqnDwTGxd350gOM0Blx02gp4zQnEOMiHrg/Apm6qHbfj6Q/dra61+wKKOMNd/W9uuEy+IDuIjS9Xegq4efAD8sg0E9cZeXXmptk83doaBOVgbG6PPgWfKLokzMLSknypcDNm9XzMdJw29OqzG+6SSq3zOP+eOwve4LTObmrkLibvtj+XxI/JnCaR3fe6N9QC/bU1xeMJYickLTQgmpHqFVWlYBBrrXjYJq+MV0obSgE6s2oWvK736uUMgYVC9ZR/Qy1EG/5sDY23NK1q00hhv5IJBgCrQyKQxPYvCn/XDb6DP+tXlZvO0ezVksnOWheXKiBw3KfwwCRH2K5XDbs7T67YmCZe6FrYUWZ2AnfcQEKlK2jH6HbA0K2MoJrV1magifOGKRFZd5h4j6WtdQTcCZIFzracPfD1GWZNX7bSykm9YJO70pZYOrgbCNsfPGoiQ/2c2Wxqvd4QjuZ5kH/1WVT2BlrTtQLEa5ugE+GI/yeOELySDlLYdGIbFUNXiDE6dPIsHHab1VWl0DztjPP2ZFnRCqfU=

------ 8151e7568131a1c6 begin@2024-04-04_16:02:36.431 ------
verify success
key size:4096
mode:pss-sha256
------ 8151e7568131a1c6 took 13.708 milli-seconds to execute ------

ECC椭圆曲线

支持的命令

❯ easy_encryption_tool ecc --help
Usage: main.py ecc [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  ecdh
  generate
  sign
  verify

生成密钥对

❯ easy_encryption_tool ecc generate --help
Usage: main.py ecc generate [OPTIONS]

Options:
  -c, --curve [secp256r1|secp384r1|secp521r1|secp256k1]
                                  ecc 椭圆曲线类型  [default: secp256k1]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -f, --file-name TEXT            输出密钥对的文件名前缀,最终写入数据时会创建文件并加上文件名后缀  [default:
                                  demo; required]
  -p, --password TEXT             私钥密码,使用私钥时需要输入正确的密码
  -r, --random-password           是否生成私钥的随机密码,如果带上 -r 标识,则随机生成32字节的密码
  --help                          Show this message and exit.

默认生成

❯ easy_encryption_tool ecc generate

------ d6b0cebd74d64b57 begin@2024-04-04_16:07:59.720 ------
generate demo_ecc_public.pem/demo_ecc_private.pem success
------ d6b0cebd74d64b57 took 17.039 milli-seconds to execute ------

指定椭圆曲线且指定密码

❯ easy_encryption_tool ecc generate -c secp384r1 -p 1234567890

------ e852fd0a2d84d39f begin@2024-04-04_16:08:46.706 ------
private key password:1234567890
generate demo_ecc_public.pem/demo_ecc_private_cipher.pem success
------ e852fd0a2d84d39f took 16.710 milli-seconds to execute ------

指定椭圆曲线且随机生成密码

❯ easy_encryption_tool ecc generate -c secp384r1 -r

------ 073bd5585937e6fd begin@2024-04-04_16:09:28.102 ------
private key password:)N)y&4dq=ODg`339uE`7*@A9Gl0eVs3Z
generate demo_ecc_public.pem/demo_ecc_private_cipher.pem success
------ 073bd5585937e6fd took 16.721 milli-seconds to execute ------

ECDH密钥交换

支持的参数

❯ easy_encryption_tool ecc ecdh --help
Usage: main.py ecc ecdh [OPTIONS]

Options:
  -a, --alice-pub-key TEXT    你自己的公钥文件的路径如: ./alice_public.pem  [required]
  -k, --alice-pri-key TEXT    你自己的私钥文件的路径如: ./alice_private.pem  [required]
  -p, --password TEXT         你自己的私钥的密码,如果创建时设置了密码,那么在使用私钥时需要输入正确的密码
  -b, --bob-pub-key TEXT      对方的公钥文件的路径如: ./bob_public.pem  [required]
  -e, --encoding [pem|der]    密钥格式  [default: pem]
  -l, --length INTEGER RANGE  派生密钥的长度,默认 32 字节,长度范围[16 -- 64]  [default: 32;
                              16<=x<=64]
  -s, --salt TEXT             用于增加派生密钥安全性的盐值,两边必须提供一样的盐值  [default:
                              hello,world1234567890!@#$%^&*()_+{}:";<>?/;
                              required]
  -c, --context TEXT          用于增加派生密钥安全性的上下文信息,两边必须提供一样的上下文数据  [default: ecc
                              handshake context data; required]
  --help                      Show this message and exit.

生成 alice 与 bob 的密钥对

❯ easy_encryption_tool ecc generate -f alice -p 1234567890

------ f4815ee66aa727b2 begin@2024-04-04_16:11:03.966 ------
private key password:1234567890
generate alice_ecc_public.pem/alice_ecc_private_cipher.pem success
------ f4815ee66aa727b2 took 17.763 milli-seconds to execute ------

❯ easy_encryption_tool ecc generate -f bob -p 1234567890

------ 76e72cdd07cb5c32 begin@2024-04-04_16:11:26.201 ------
private key password:1234567890
generate bob_ecc_public.pem/bob_ecc_private_cipher.pem success
------ 76e72cdd07cb5c32 took 16.373 milli-seconds to execute ------

alice派生和 bob 共享的对称密钥

❯ easy_encryption_tool ecc ecdh -a ./alice_ecc_public.pem -k ./alice_ecc_private_cipher.pem -p 1234567890 -b ./bob_ecc_public.pem -l 64 -s alice-bob -c key-alice-bob

------ 8235537a02e647d4 begin@2024-04-04_16:14:48.686 ------
curve name:secp256k1
derived key:u+UNGIzrPbLRVlTSixl8fgd3SgLuGeQrwSI4Irs1tpSVivmTxYLTOUm/o1pvqPLuOGVA8D3iLdUGLEE72Wo1QQ==
length:64
------ 8235537a02e647d4 took 18.166 milli-seconds to execute ------

bob派生和alice共享的对称密钥

❯ easy_encryption_tool ecc ecdh -a ./bob_ecc_public.pem -k ./bob_ecc_private_cipher.pem -p 1234567890 -b ./alice_ecc_public.pem -l 64 -s alice-bob -c key-alice-bob

------ d50d7d254d02104c begin@2024-04-04_16:15:39.570 ------
curve name:secp256k1
derived key:u+UNGIzrPbLRVlTSixl8fgd3SgLuGeQrwSI4Irs1tpSVivmTxYLTOUm/o1pvqPLuOGVA8D3iLdUGLEE72Wo1QQ==
length:64
------ d50d7d254d02104c took 16.998 milli-seconds to execute ------

签名与验签

支持的参数

# 签名
❯ easy_encryption_tool ecc sign --help
Usage: main.py ecc sign [OPTIONS]

Options:
  -f, --private-key TEXT          私钥文件路径  [required]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -h, --hash-mode [sha256|sha384|sha512|sha3-224|sha3-256|sha3-384|sha3-512]
                                  签名时的哈希算法  [default: sha256]
  -p, --password TEXT             私钥密码,如果生成时设置了密码那么在使用私钥时需要输入正确的密码
  -i, --input-data TEXT           需要被签名的数据  [required]
  -c, --b64-encoded               输入数据是否被 base64 编码过
  --help                          Show this message and exit.

# 验签
❯ easy_encryption_tool ecc verify --help
Usage: main.py ecc verify [OPTIONS]

Options:
  -f, --public-key TEXT           公钥文件路径  [required]
  -e, --encoding [pem|der]        密钥格式  [default: pem]
  -h, --hash-mode [sha256|sha384|sha512|sha3-224|sha3-256|sha3-384|sha3-512]
                                  签名时的哈希算法  [default: sha256]
  -i, --input-data TEXT           需要被签名的数据  [required]
  -c, --b64-encoded               输入数据是否被 base64 编码过
  -s, --signature TEXT            base64 编码过的签名值
  --help                          Show this message and exit.

生成密钥对

❯ easy_encryption_tool ecc generate -c secp384r1 -p 1234567890 -e der

------ 3a40beeed28cffa4 begin@2024-04-04_16:17:49.172 ------
private key password:1234567890
generate demo_ecc_public.der/demo_ecc_private_cipher.der success
------ 3a40beeed28cffa4 took 16.821 milli-seconds to execute ------

签名

❯ easy_encryption_tool ecc sign -f ./demo_ecc_private_cipher.der -e der -h sha3-512 -p 1234567890 -i aGVsbG8sd29ybGQK -c

------ dbc12fab8422ba0f begin@2024-04-04_16:18:57.578 ------
curve name:secp384r1
key size:384
signature:30640230243bba7ec0a95f7aef4868673282b70217285a667ae52ce5e43c6af5b33e8adbda86bbe2a7d9f995b934d038eae5624c02306c47daed069e51bb12c274c13219c173ed4b59c6f76caab04f50b4359f3f25c0fa4dab4c17cb88888767f37e4c8cf993
base64 encoded:MGQCMCQ7un7AqV9670hoZzKCtwIXKFpmeuUs5eQ8avWzPorb2oa74qfZ+ZW5NNA46uViTAIwbEfa7QaeUbsSwnTBMhnBc+1LWcb3bKqwT1C0NZ8/JcD6TatMF8uIiIdn835MjPmT
mode:ECDSA
------ dbc12fab8422ba0f took 17.265 milli-seconds to execute ------

验签

❯ easy_encryption_tool ecc verify -f ./demo_ecc_public.der -e der -h sha3-512 -i aGVsbG8sd29ybGQK -c -s MGQCMCQ7un7AqV9670hoZzKCtwIXKFpmeuUs5eQ8avWzPorb2oa74qfZ+ZW5NNA46uViTAIwbEfa7QaeUbsSwnTBMhnBc+1LWcb3bKqwT1C0NZ8/JcD6TatMF8uIiIdn835MjPmT

------ d1c74d3acc46413b begin@2024-04-04_16:20:09.177 ------
curve name:secp384r1
verify success
key size:384
mode:ECDSA
------ d1c74d3acc46413b took 15.220 milli-seconds to execute ------

SM9 标识密码(IBC)

SM9 是国密标识密码(Identity-Based Cryptography):身份字符串(如邮箱)本身就是公钥,无需事先交换证书或公钥。密钥体系分两层——KGC 持有主密钥(master key),按身份为用户派生用户私钥;加密者只需主公钥 + 接收方身份即可加密,签名者持自己的用户签名私钥签名,验签者用主公钥 + 签名者身份验签。命令组为 sm9,需要 GmSSL 原生库。

❯ easy_encryption_tool sm9 --help

Commands:
  master-generate  生成 SM9 主密钥对(加密型或签名型)
  extract          从主私钥为指定身份派生用户私钥
  encrypt          用主公钥为指定身份加密(标识加密)
  decrypt          用用户私钥解密
  sign             用用户签名私钥签名
  verify           用主公钥为指定身份验签

生成主密钥并派生用户私钥

-k 选主密钥类型:enc(加密型)或 sign(签名型)。主私钥文件以口令加密落盘(GmSSL 原生加密 PEM),password 与 sm2/rsa/pqc 相同约定:仅 -r 随机口令时在 result 回显(随机口令不回显则无人能再用这把主密钥),-p 自给口令不回显,均不进 metadata:

❯ easy_encryption_tool sm9 master-generate -k enc -f demo -p 1234567890 --json

{"metadata": {"operation": "master-generate", "algorithm": "sm9-enc", "parameters": {"encoding": "pem", "kind": "enc"}}, "result": {"public_file": "demo_sm9encmaster_public.pem", "private_file": "demo_sm9encmaster_private_cipher.pem"}, "runtime": {...}, "messages": [{"status": "hint", "message": {"code": "EET_HINT", "text": "next: eet sm9 extract -k enc -f demo_sm9encmaster_private_cipher.pem -p <password> --id <identity>"}}]}

# 为 bob@example.com 派生加密用户私钥(解密方持有,身份即公钥)
❯ easy_encryption_tool sm9 extract -k enc -f demo_sm9encmaster_private_cipher.pem -p 1234567890 --id bob@example.com -o demo_bob_user.pem --json

{"metadata": {"operation": "extract", "algorithm": "sm9-enc", "parameters": {"kind": "enc", "id": "bob@example.com"}}, "result": {"key_file": "demo_bob_user.pem", "id": "bob@example.com"}, "runtime": {...}}

用户私钥同样以口令加密存储。身份串最长 63 字节(SM9_MAX_ID_SIZE)。

标识加密与解密

加密只需主公钥 + 接收方身份(--to),接收方用自己的用户私钥解密:

❯ easy_encryption_tool sm9 encrypt -f demo_sm9encmaster_public.pem --to bob@example.com -i "hello bob, this is sm9 encrypted 中文" --json

{"metadata": {"operation": "encrypt", "algorithm": "sm9-enc", "input": {"type": "text", "size": 39}, "parameters": {"to": "bob@example.com", "cipher_size": 149}}, "result": {"cipher": "MIGSAgEAA0IABJXfGqJuTtFMLMdtmutukXmnPsBN9nDdrd/T13EOsTeaQbvr4c0ggomnav72wSGmO9wTnirjpW2354hmqhSO3WIEIMeXQd3g0kskZgUx0qNQ+xqH7T3URlDms0cvKChLwVluBCcwvhKLi9sCKzrl3JQKLEysASQTgs52PyWvpACxOwHE6R5nKdjAX44=", "cipher_in_hex": "3081920201000342000495df1aa26e4ed14c2cc76d9aeb6e9179a73ec04df670ddaddfd3d7710eb1379a41bbebe1cd208289a76afef6c121a63bdc139e2ae3a56db7e78866aa148edd620420c79741dde0d24b24660531d2a350fb1a87ed3dd44650e6b3472f28284bc1596e042730be128b8bdb022b3ae5dc940a2c4cac01241382ce763f25afa400b13b01c4e91e6729d8c05f8e", "cipher_bytes": 149}, "runtime": {...}}

# 解密:-e 表明 -i 是 base64 密文(取上一步输出的 cipher 字段)
❯ easy_encryption_tool sm9 decrypt -f demo_bob_user.pem -p 1234567890 --id bob@example.com -i "<cipher>" -e --json

{"metadata": {"operation": "decrypt", "algorithm": "sm9-enc", "input": {"type": "binary", "size": 149}, "parameters": {"id": "bob@example.com"}}, "result": {"plain": "hello bob, this is sm9 encrypted 中文"}, "runtime": {...}}

身份不匹配(用 alice 的用户私钥解给 bob 的密文)解密失败并输出错误文档。

标识签名与验签

签名者持签名型用户私钥,验签方用签名主公钥 + 签名者身份(--id):

❯ easy_encryption_tool sm9 sign -f demo_alice_sign_user.pem -p 1234567890 -i "sm9 signed message from alice" --json

{"metadata": {"operation": "sign", "algorithm": "sm9-sign", "input": {"type": "text", "size": 29}}, "result": {"signature": "MGYEIFVPXeRmEhbqQ/gUUUlhnn6bmsXO/BTHLignsjNW3s2mA0IABCyjMZQa5yXSm/D4piAJv6PcAUCh8WXqzStsAT020nALL8lYGukcLL53SgwSwKeTXO+cKDvchuG7kit9l1LIsOE=", "signature_in_hex": "30660420554f5de4661216ea43f8145149619e7e9b9ac5cefc14c72e2827b23356decda6034200042ca331941ae725d29bf0f8a62009bfa3dc0140a1f165eacd2b6c013d36d2700b2fc9581ae91c2cbe774a0c12c0a7935cef9c283bdc86e1bb922b7d9752c8b0e1", "signature_bytes": 104}, "runtime": {...}}

# 验签:-s 传入签名输出的 signature(base64),--id 必须与签名者身份一致
❯ easy_encryption_tool sm9 verify -f demo_sm9signmaster_public.pem --id alice@example.com -i "sm9 signed message from alice" -s "<signature>" --json

{"metadata": {"operation": "verify", "algorithm": "sm9-sign", "input": {"type": "text", "size": 29}, "parameters": {"id": "alice@example.com"}}, "result": {"valid": true}, "runtime": {...}}

身份不符或消息被篡改时 valid 为 false 或输出错误文档。SM9 签名随机化:同一私钥对同一消息多次签名结果不同,属正常现象。

密钥派生(HKDF / SM3-KDF / PBKDF2-HMAC-SM3)

kdf 命令提供三种派生构造:hkdf(RFC 5869,走 cryptography,无需原生库,3.2.0 起为默认)与两种基于 SM3 的派生方式(需 GmSSL 原生库):

# HKDF:默认算法(sha256、盐未提供按 RFC 5869 补零),二进制 IKM 用 -i <base64> -e
❯ easy_encryption_tool kdf -i ikm-material -l 32 --json

{"metadata": {"operation": "kdf", "algorithm": "hkdf", "input": {"type": "text", "size": 12}, "parameters": {"algorithm": "hkdf", "key_len": 32, "hash": "sha256", "salt_source": "none", "salt_bytes": 0, "info_bytes": 0}}, "result": {"key": "vBmgrK8IqUxy+NSYQ7JrLhVEJtNsL0zKKHlmEFCtUlg=", "key_in_hex": "bc19a0acaf08a94c72f8d49843b26b2e154426d36c2f4cca2879661050ad5258", "key_bytes": 32, "formats": {"key": "base64", "key_in_hex": "hex"}}, "runtime": {...}}

# HKDF:指定哈希与盐/上下文(--info/--info-b64 提供上下文信息)
❯ easy_encryption_tool kdf -a hkdf -H sha512 -i ikm-material --salt eet-salt-01 --info derive-ctx -l 64 --json

{"metadata": {"operation": "kdf", "algorithm": "hkdf", "input": {"type": "text", "size": 12}, "parameters": {"algorithm": "hkdf", "key_len": 64, "hash": "sha512", "salt_source": "cli", "salt_bytes": 11, "info_bytes": 10}}, "result": {"key": "8R5n8jXyB5rRnwrJvTTiGb1Sg9SivldQ/X2GqKhA8fMmABhzV+dQFGvP7wwVU0ZzgxKj+Ihmta+5V2/XFflzEA==", "key_in_hex": "f11e67f235f2079ad19f0ac9bd34e219bd5283d4a2be5750fd7d86a8a840f1f32600187357e750146bcfef0c155346738312a3f88866b5afb9576fd715f97310", "key_bytes": 64, "formats": {"key": "base64", "key_in_hex": "hex"}}, "runtime": {...}}

# SM3-KDF:从共享秘密派生密钥材料(ECDH 共享点后派生对称密钥的典型用法)
❯ easy_encryption_tool kdf -a sm3 -i kat-secret -l 32 --json

{"metadata": {"operation": "kdf", "algorithm": "sm3-kdf", "input": {"type": "text", "size": 10}, "parameters": {"algorithm": "sm3", "key_len": 32}}, "result": {"key": "rfR8C/wIpbbg2PPzkHuCYho96xmf7po4EY5zzdb0OQs=", "key_in_hex": "adf47c0bfc08a5b6e0d8f3f3907b82621a3deb199fee9a38118e73cdd6f4390b", "key_bytes": 32, "formats": {"key": "base64", "key_in_hex": "hex"}}, "runtime": {...}}

# PBKDF2-HMAC-SM3:从口令派生,--salt/--salt-b64/--iter 可选
❯ easy_encryption_tool kdf -a pbkdf2-sm3 -i kat-password --salt eet-salt-01 --iter 10000 -l 32 --json

{"metadata": {"operation": "kdf", "algorithm": "sm3-pbkdf2", "input": {"type": "text", "size": 12}, "parameters": {"algorithm": "pbkdf2-sm3", "key_len": 32, "iterations": 10000, "salt_bytes": 11, "salt_source": "cli"}}, "result": {"key": "Mqm1kNfz58iWtbKMx4mUw6CayE2qituhTNZJztcq/GM=", "key_in_hex": "32a9b590d7f3e7c896b5b28cc78994c3a09ac84daa8adba14cd649ced72afc63", "key_bytes": 32, "formats": {"key": "base64", "key_in_hex": "hex"}}, "runtime": {...}}

要点:

  • -a hkdf(默认,3.2.0 起;原默认 sm3,隐式依赖默认值的脚本需显式写 -a sm3):-H 选 sha1/224/256/384/512,长度 1–1024 字节。盐是可选的上下文绑定值,缺省不随机生成(未提供按 RFC 补 HashLen 零),--salt(文本)/--salt-b64(字节)显式给;--info/--info-b64 提供上下文信息。RFC 5869 A.1–A.4 官方向量在 CLI 上逐位复现。
  • -a sm3(SM3-KDF)不接受盐参数,派生是确定性的;长度范围 1–1024 字节。
  • -a pbkdf2-sm3 缺省生成 16 字节随机盐,随机盐会以 base64 回显在 result 的 salt 字段(否则派生不可复现);用 --salt(文本)或 --salt-b64(字节)显式给盐时 result 不再回显。迭代次数范围 [10000, 16777216],长度范围 1–256 字节。
  • 二进制秘密用 -i <base64> -e 传入(hkdf 与 sm3 均支持)。

SM4 对称加解密(CBC / GCM / CTR)

sm4 命令用法与 aes 一致(密钥/IV 规范化、-r 随机密钥、文件输入输出),模式经 -m 选择。3.0 起新增 CTR 计数器模式:

❯ easy_encryption_tool sm4 -A encrypt -m ctr -k 0123456789abcdef -v fedcba9876543210 -i "ctr mode payload" --json

{"metadata": {"operation": "encrypt", "algorithm": "sm4-ctr", "input": {"type": "text", "size": 16}, "parameters": {"mode": "ctr"}}, "result": {"cipher": "9wc1NPqEZ8jTrkvEQmXQ+g==", "formats": {"cipher": "base64"}}, "runtime": {...}}

❯ easy_encryption_tool sm4 -A decrypt -m ctr -k 0123456789abcdef -v fedcba9876543210 -i "<cipher>" -e --json

{"metadata": {"operation": "decrypt", "algorithm": "sm4-ctr", "input": {"type": "binary", "size": 16}, "parameters": {"mode": "ctr"}}, "result": {"plain": "ctr mode payload", "formats": {"plain": "utf-8"}}, "runtime": {...}}

CTR 是流模式:不做填充,密文长度恒等于明文长度(上例 16 字节进 16 字节出),因此 --gcm-pad 类填充选项与 ctr 互斥。CBC(PKCS#7 填充)与 GCM(12 字节 nonce + 16 字节 tag)行为不变。

PQC 后量子(ML-KEM / ML-DSA)

后量子命令组 pqc,提供 ML-KEM(FIPS 203 密钥封装)与 ML-DSA(FIPS 204 签名)能力,需要 cryptography >= 47(ExternalMu 模式需 >= 49)。参数集可用性取决于所装 cryptography 版本(easy_encryption_tool version 的 Dependencies 行会列出当前可用参数集)。

与 CipherHUB 工具站 的互通关系:公钥可互换(双方均为 NIST 标准 OID 的 SPKI/PKCS#8,工具站后端 liboqs 生成的公钥可直接喂给本工具 encap/verify);私钥不可互换(本工具私钥为 PKCS#8 种子形态加密存储,工具站为展开形态,二者格式不同)。

生成 ML-KEM 密钥对

# 私钥强制密码保护:-p 指定密码,或 -r 随机生成(两者都不传默认随机)
# -r 随机口令回显在 result.password;-p 自给口令不回显
❯ easy_encryption_tool pqc mlkem generate -f demo -p 1234567890 --json

{"metadata": {"operation": "generate", "algorithm": "ML-KEM-768", "parameters": {"encoding": "pem", "seed_derived": false}}, "result": {"public_file": "demo_mlkem768_public.pem", "private_file": "demo_mlkem768_private_cipher.pem"}, "runtime": {"request_id": "a2bac659-2d54-47f2-be3f-aab0fa28174c", "timestamp": "2026-08-28T15:07:32.353623+08:00", "duration_ms": 9.809, "host": "MacM2Max-2.local", "version": "v2.7.0"}}

-a/--algorithm 可选 ML-KEM-512、ML-KEM-768(默认)、ML-KEM-1024;--seed-in-hex 接受 64 字节 hex(128 个十六进制字符)做确定性派生,仅供教学与向量复现,生产环境留空即随机生成。

ML-KEM 封装与解封装

发送方持有公钥做封装,得到密文与共享秘密;接收方持私钥解封装还原同一个共享秘密(典型用法:共享秘密作为对称加密的密钥材料)。

# 封装:输出 ciphertext(交给孩子信道传输)与 shared_secret(发送方本地留存)
❯ easy_encryption_tool pqc mlkem encap -f demo_mlkem768_public.pem --json

{"metadata": {"operation": "encap", "algorithm": "ML-KEM-768", "input": {"type": "key"}, "parameters": {"ciphertext_bytes": 1088}}, "result": {"ciphertext_in_hex": "cbf390d5c3a98de7ece00606...(共 2176 个 hex 字符)", "ciphertext_in_base64": "y/OQ1cOpjefs4AYGeHQe/Cf2knCg...(共 1452 个字符)", "ciphertext_bytes": 1088, "shared_secret_in_hex": "ca4954152db0dd42d6e50ff35ecc51a7590bc487cf7339ee352610cc4b7a56c3", "shared_secret_in_base64": "yklUFS2w3ULW5Q/zXsxRp1kLxIfPcznuNSYQzEt6VsM=", "shared_secret_sha256": "b71c5ae5a9132597df7a96250af8b029b24ec1e91ce92cc18de699dd8f35b8cc", "shared_secret_bytes": 32}, "runtime": {...}}

# 解封装:-i 传入封装输出的 ciphertext_in_base64
❯ easy_encryption_tool pqc mlkem decap -f demo_mlkem768_private_cipher.pem -p 1234567890 -i "<ciphertext_in_base64>" --json

{"metadata": {"operation": "decap", "algorithm": "ML-KEM-768", "input": {"type": "binary", "size": 1088}}, "result": {"shared_secret_in_hex": "9b907dd7844ce9dd906e645ecaaa95936b18b43d7f66b21ae2ef265496ef1f7a", "shared_secret_in_base64": "m5B914RM6d2QbmReyqqVk2sYtD1/ZrIa4u8mVJbvH3o=", "shared_secret_sha256": "c8f5e74ba6ca40c5cef8d72de727c67183b256359c2639fb489e54abcc167697", "shared_secret_bytes": 32}, "runtime": {...}}

注意两次 shared_secret 不同是正常的:ML-KEM 封装本身随机化,同一条 ciphertext 的 encap/decap 结果必然一致(上例两段输出来自两次独立的封装)。按 FIPS 203 的隐式拒绝语义,篡改后的 ciphertext 解封装不报错,但得到的共享秘密必然不同——比对 shared_secret_sha256 即可发现。

生成 ML-DSA 密钥对

❯ easy_encryption_tool pqc mldsa generate -f demo -p 1234567890 --json

{"metadata": {"operation": "generate", "algorithm": "ML-DSA-65", "parameters": {"encoding": "pem", "seed_derived": false}}, "result": {"public_file": "demo_mldsa65_public.pem", "private_file": "demo_mldsa65_private_cipher.pem"}, "runtime": {...}}

-a/--algorithm 可选 ML-DSA-44、ML-DSA-65(默认)、ML-DSA-87;--seed-in-hex 接受 32 字节 hex(64 个十六进制字符)做确定性派生,仅供教学与向量复现。

ML-DSA 签名与验签

# 签名:--context 为可选域分隔字符串(最长 255 字节),验签时必须传同一个值
❯ easy_encryption_tool pqc mldsa sign -f demo_mldsa65_private_cipher.pem -p 1234567890 -i "hello,post-quantum" --context eet-demo --json

{"metadata": {"operation": "sign", "algorithm": "ML-DSA-65", "input": {"type": "text", "size": 18}, "parameters": {"context": "eet-demo"}}, "result": {"signature_in_hex": "b2de9bf26b6685e2b64d8c348ccf726f...(共 6618 个 hex 字符)", "signature_in_base64": "st6b8mtmheK2TYw0jM9ybwQwSnPvYWp2M+Yk...(共 4412 个字符)", "signature_bytes": 3309}, "runtime": {...}}

# 验签:-s 传入签名输出的 signature_in_base64,--context 必须与签名时一致
❯ easy_encryption_tool pqc mldsa verify -f demo_mldsa65_public.pem -i "hello,post-quantum" --context eet-demo -s "<signature_in_base64>" --json

{"metadata": {"operation": "verify", "algorithm": "ML-DSA-65", "input": {"type": "text", "size": 18}, "parameters": {"context": "eet-demo"}}, "result": {"valid": true}, "runtime": {...}}

ML-DSA 签名是随机化的:同一私钥对同一消息多次签名结果不同,属正常现象。验签失败(密钥、消息、context 不匹配或签名被篡改)时输出错误文档并以退出码 1 结束。

ML-DSA ExternalMu 模式(cryptography >= 49)

FIPS 204 的签名输入实际是 64 字节中间值 mu(mu = SHAKE-256(tr‖M', 64),tr 是公钥的哈希、M' 是 context 前缀化的消息)。ExternalMu 模式把「算 mu」与「对 mu 签名」拆开,与 AWS KMS ML-DSA EXTERNAL_MU 语义对齐——密钥留在 KMS/本机,消息摘要可在别处计算。3.1 起此模式走 cryptography 原生 sign_mu/verify_mu(>= 49),不再依赖系统 OpenSSL(cryptography wheel 静态自带),可用性在 doctor 的 external-mu 行与 version --json 的 external_mu 段展示。

三个命令形态:

# 1) compute-mu:从公钥(或私钥,会派生公钥)计算 mu,纯 hashlib 实现,零额外依赖
❯ easy_encryption_tool pqc mldsa compute-mu -f demo_mldsa65_public.pem -i "external mu demo message" --json

{"metadata": {"operation": "compute-mu", "algorithm": "ML-DSA-65", "input": {"type": "text", "size": 24}}, "result": {"mu_in_hex": "4960e833ab4cd4835874423b0dc78880fc76e2b04e0cef784c1320359e81e885ec99e84ed2970d34839c17fa2003e8b9751499c6fd831524f37650efb49833e4", "mu_in_base64": "SWDoM6tM1INYdEI7DceIgPx24rBODO94TBMgNZ6B6IXsmehO0pcNNIOcF/ogA+i5dRSZxv2DFSTzdlDvtJgz5A==", "mu_bytes": 64, "tr_in_hex": "0da3bf875d68bf5e2ec526af9065e24bf6d279c18b8e6907dd09e349267ab154373d0dd5584dd1e8904f6bc06f590f9a30c1f64368f3bd362b28b1d5232eb24e"}, "runtime": {...}, "messages": [{"status": "hint", "message": {"code": "EET_HINT", "text": "next: eet pqc mldsa sign --external-mu --raw-mu -f <private_key> -i <mu_in_hex>"}}]}

# 2) sign --external-mu --raw-mu:-i 直接是 64 字节 mu(hex),不再内部哈希
❯ easy_encryption_tool pqc mldsa sign --external-mu --raw-mu -f demo_mldsa65_private_cipher.pem -p 1234567890 -i "<mu_in_hex>" --json

{"metadata": {"operation": "sign", "algorithm": "ML-DSA-65", "input": {"type": "text", "size": 64}, "parameters": {"mode": "external-mu-raw"}}, "result": {"signature_in_hex": "f9b53026...(共 6618 个 hex 字符)", "signature_in_base64": "+bUwJpwhBPJ1...(共 4412 个字符)", "signature_bytes": 3309}, "runtime": {...}}

# 3) verify --external-mu --raw-mu:对称验签,-s 传 base64 签名
❯ easy_encryption_tool pqc mldsa verify --external-mu --raw-mu -f demo_mldsa65_public.pem -i "<mu_in_hex>" -s "<signature_in_base64>" --json

{"metadata": {"operation": "verify", "algorithm": "ML-DSA-65", "input": {"type": "text", "size": 64}, "parameters": {"mode": "external-mu-raw"}}, "result": {"valid": true}, "runtime": {...}}

说明:

  • sign --external-mu(不带 --raw-mu):消息照常传 -i,eet 内部算 mu 后走 cryptography 原生 mu 签名——产物与标准模式签名互通,pqc mldsa verify(标准模式)可直接验。
  • --raw-mu:-i 必须恰为 64 字节(hex 128 字符或 base64),且与 --context 互斥(context 已在算 mu 时消费)。长度不符报「raw mu must be 64 bytes」。
  • compute-mu 与 --raw-mu 串联即完整 ExternalMu 流程:摘要计算与密钥使用可以发生在不同机器。

证书解析与验证

解析证书并验证签名

 ❯ easy_encryption_tool cert-parse -f test_certs/baidu.com.cer

------ 27f6aa95a2461345 begin@2024-04-06_15:02:26.887 ------
------- verify signature: -------
verify cert signature success
ca issuer:http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt

------- basic info: -------
version: v3-2
serial_number: 26585094245224241434632730821
signature_algorithm: PKCS #1 RSA Encryption
signature_hash_algorithm: sha256
issuer: GlobalSign nv-sa|GlobalSign RSA OV SSL CA 2018|BE
valid_before: 20230706015106Z
valid_after: 20240806015105Z
subject: Beijing Baidu Netcom Science Technology Co., Ltd|CN|baidu.com
public_key_bits: 2048
public_key_type: 6(6:RSA|116:DSA|408:EC|28:DH)
------ 27f6aa95a2461345 took 83.634 milli-seconds to execute ------

解析完整证书内容

❯ easy_encryption_tool cert-parse -f baidu.com.cer -v

------ 247b96f11927fe0f begin@2024-04-06_15:04:26.023 ------
------- verify signature: -------
verify cert signature success
ca issuer:http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt

------- basic info: -------
version: v3-2
serial_number: 26585094245224241434632730821
signature_algorithm: PKCS #1 RSA Encryption
signature_hash_algorithm: sha256
issuer: GlobalSign nv-sa|GlobalSign RSA OV SSL CA 2018|BE
valid_before: 20230706015106Z
valid_after: 20240806015105Z
subject: Beijing Baidu Netcom Science Technology Co., Ltd|CN|baidu.com
public_key_bits: 2048
public_key_type: 6(6:RSA|116:DSA|408:EC|28:DH)

------- verbose info: -------
public_key_exponent: ('10001',)
public_key_modules: ('BB04BB84765807B45A8854E06A56BCE5D48D3E1EB928E0D7018F382B41B2597DF0AC27B426241438FE4CEA3B4951F7E95B40F73FA6C8DA0F026E258B4791B82E9E0021191D1800FCDE04FD2679395DF290BC809DA87CB2918989D8402FE5D2A7F35E6D482BC51F0AB1E08E8C76FFBCD1670AD249D609EE260302F3CCCDEA8AD531A82D8F03FD5EFCE43AC68967994CCE986DFA840D0E538BE66352C59B4AA9ABA32235990DEE19FF9B2DF5A477F2EC1080F4AB82B9D17E361F0E9F9B19A0F5C357DD88BBCEE1909C3F4BBADD3AA941B3DD864DC2C2B7E8FF3713C0048943443811E6A396F70922212F2C4E0E7EE5D85CBB00445BAFDEE4B3B0F03CB63845495D',)
public_key_fingerprints: 43A4C24005AA3F8B7E7AAE35C6729A52025DACF5AAC86E4BF8D8B6633321A9D6
signature: 0X195A675043B1AC7A93A86818728B407EA675DEAC21FCC94116204BF38C0BB94745AEF85D79F64335260198F0B9863E2901F1DFB072B5AE78D2DF61B678678AC9779ADEE0E4412F9C1EE53B7C973F422FADE3497F9D2B0288906925030114B9B5CB0F593D2D973D02D55190690C811022DAC651EF480CD24FDE61F26A8715A56D718E3702A2850F1E1975A3802E6A1AA2028C2FECBD3D81033F8AC0A0E6B40E0857CB001C8AB71B8F38719A8DC0710C3FBCD4BE569DF718C1AABEE4DF1A86E2626F23863054782D471FB4AD052973249814A019C002FD90904E625CE84D3189C3E88B9E73593B9891CA47A5055BC51E8F85390ECEB5260A804E9F084A11491363
certificate_fingerprints: D8:AA:2D:80:6C:57:1F:B6:2E:D4:87:48:41:90:92:3F:93:24:F0:31:9C:FF:FE:DF:7B:62:1F:13:4E:6B:C1:00
extension_count: 10
extensions_detail: {
    "x509.AuthorityInformationAccess": {
        "oid": "1.3.6.1.5.5.7.1.1",
        "critical": false,
        "value": {
            "caIssuers": "http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt",
            "OCSP": "http://ocsp.globalsign.com/gsrsaovsslca2018"
        }
    },
    "x509.BasicConstraints": {
        "oid": "2.5.29.19",
        "critical": false,
        "value": "<BasicConstraints(ca=False, path_length=None)>"
    },
    "x509.KeyUsage": {
        "oid": "2.5.29.15",
        "critical": true,
        "value": "<KeyUsage(digital_signature=True, content_commitment=False, key_encipherment=True, data_encipherment=False, key_agreement=False, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False)>"
    },
    "x509.SubjectKeyIdentifier": {
        "oid": "2.5.29.14",
        "critical": false,
        "value": "<SubjectKeyIdentifier(digest=b'\\xeds\\xab\\xf9 \\xbez\\x19\\x9fY\\x1f\\xb2\\x9f\\xf2?/?\\x91\\x84\\x12')>"
    },
    "x509.SubjectAlternativeName": {
        "oid": "2.5.29.17",
        "critical": false,
        "value": "<SubjectAlternativeName(<GeneralNames([<DNSName(value='baidu.com')>, <DNSName(value='baifubao.com')>, <DNSName(value='www.baidu.cn')>, <DNSName(value='www.baidu.com.cn')>, <DNSName(value='mct.y.nuomi.com')>, <DNSName(value='apollo.auto')>, <DNSName(value='dwz.cn')>, <DNSName(value='*.baidu.com')>, <DNSName(value='*.baifubao.com')>, <DNSName(value='*.baidustatic.com')>, <DNSName(value='*.bdstatic.com')>, <DNSName(value='*.bdimg.com')>, <DNSName(value='*.hao123.com')>, <DNSName(value='*.nuomi.com')>, <DNSName(value='*.chuanke.com')>, <DNSName(value='*.trustgo.com')>, <DNSName(value='*.bce.baidu.com')>, <DNSName(value='*.eyun.baidu.com')>, <DNSName(value='*.map.baidu.com')>, <DNSName(value='*.mbd.baidu.com')>, <DNSName(value='*.fanyi.baidu.com')>, <DNSName(value='*.baidubce.com')>, <DNSName(value='*.mipcdn.com')>, <DNSName(value='*.news.baidu.com')>, <DNSName(value='*.baidupcs.com')>, <DNSName(value='*.aipage.com')>, <DNSName(value='*.aipage.cn')>, <DNSName(value='*.bcehost.com')>, <DNSName(value='*.safe.baidu.com')>, <DNSName(value='*.im.baidu.com')>, <DNSName(value='*.baiducontent.com')>, <DNSName(value='*.dlnel.com')>, <DNSName(value='*.dlnel.org')>, <DNSName(value='*.dueros.baidu.com')>, <DNSName(value='*.su.baidu.com')>, <DNSName(value='*.91.com')>, <DNSName(value='*.hao123.baidu.com')>, <DNSName(value='*.apollo.auto')>, <DNSName(value='*.xueshu.baidu.com')>, <DNSName(value='*.bj.baidubce.com')>, <DNSName(value='*.gz.baidubce.com')>, <DNSName(value='*.smartapps.cn')>, <DNSName(value='*.bdtjrcv.com')>, <DNSName(value='*.hao222.com')>, <DNSName(value='*.haokan.com')>, <DNSName(value='*.pae.baidu.com')>, <DNSName(value='*.vd.bdstatic.com')>, <DNSName(value='*.cloud.baidu.com')>, <DNSName(value='click.hm.baidu.com')>, <DNSName(value='log.hm.baidu.com')>, <DNSName(value='cm.pos.baidu.com')>, <DNSName(value='wn.pos.baidu.com')>, <DNSName(value='update.pan.baidu.com')>])>)>"
    },
    "x509.CRLDistributionPoints": {
        "oid": "2.5.29.31",
        "critical": false,
        "value": "<CRLDistributionPoints([<DistributionPoint(full_name=[<UniformResourceIdentifier(value='http://crl.globalsign.com/gsrsaovsslca2018.crl')>], relative_name=None, reasons=None, crl_issuer=None)>])>"
    },
    "x509.ExtendedKeyUsage": {
        "oid": "2.5.29.37",
        "critical": false,
        "value": "<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name=serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clientAuth)>])>"
    },
    "x509.FreshestCRL": {
        "ERROR": "x509.ExtensionNotFound",
        "oid": "",
        "value": {},
        "critical": false
    },
    "x509.NameConstraints": {
        "ERROR": "x509.ExtensionNotFound",
        "oid": "",
        "value": {},
        "critical": false
    },
    "x509.PolicyConstraints": {
        "ERROR": "x509.ExtensionNotFound",
        "oid": "",
        "value": {},
        "critical": false
    }
}
------ 247b96f11927fe0f took 76.036 milli-seconds to execute ------

解析非法证书内容

# pem格式
❯ easy_encryption_tool cert-parse -f ./test.crt

------ 34ce7a7ed108f599 begin@2024-04-06_15:05:43.194 ------
loading cert file:./upload.sh as format:pem failed:[('PEM routines', '', 'no start line')]
------ 34ce7a7ed108f599 took 0.140 milli-seconds to execute ------

# der格式
❯ easy_encryption_tool cert-parse -f ./test.crt -e der

------ 041f017f1492c8ce begin@2024-04-06_15:06:04.418 ------
loading cert file:./upload.sh as format:der failed:[('asn1 encoding routines', '', 'wrong tag'), ('asn1 encoding routines', '', 'nested asn1 error')]
------ 041f017f1492c8ce took 0.170 milli-seconds to execute ------

Server 模式(HTTP 服务,实验性)

server 命令把整棵 CLI 命令树以 HTTP 服务暴露:请求体里的 args 数组就是命令行参数,服务在进程内调用与 CLI 完全相同的实现,响应体是与 --json 输出完全一致的标准输出文档。需要 [server] extra(pip install "easy-encryption-tool[server]")。3.0.x 入口已注释停用(见上文实验性声明),下文用法为将来重新启用后的参考。

# 启动:端口必填;--token 开启 Bearer 鉴权;默认只绑定 127.0.0.1
❯ easy_encryption_tool server --port 8000 --token my-secret-token

INFO:     Uvicorn running on http://127.0.0.1:8000

两个端点:

  • GET /api/v1/health —— 探活,不做鉴权,返回 {"status": "ok", "service": "eet-server", "version": "..."};
  • POST /api/v1/cli —— 通用 argv 端点,body {"args": ["hash", "-i", "hello", "-a", "sm3"]}。
# 像用命令行一样发请求:args 就是 CLI 参数(--json 由服务自动补上)
❯ curl -s http://127.0.0.1:8000/api/v1/health
{"status":"ok","service":"eet-server","version":"3.0.0"}

❯ curl -s -H "Authorization: Bearer my-secret-token" \
       -H "Content-Type: application/json" \
       -d '{"args":["hash","-i","hello from server","-a","sm3"]}' \
       http://127.0.0.1:8000/api/v1/cli

{"metadata":{"operation":"hash","algorithm":"sm3","input":{"type":"text","size":17},"parameters":{"digest_size":32}},"result":{"digest":"0404a15d0ceee521bec8b0f8c91cac471c2213628c258cac2e0a8ab5d5988cd2","formats":{"digest":"hex"}},"runtime":{"request_id":"ae044e1d-764a-485c-a223-57ab533318a5","timestamp":"2026-08-31T16:23:46.676712+08:00","duration_ms":0.07,"host":"MacM2Max-2.local","version":"v3.0.0"}}

行为约定:

方面 行为
状态码映射 CLI 退出码 0 → 200;2(参数错误)→ 400;1(运行错误)→ 422;真实退出码另附 X-EET-Exit-Code 响应头
错误响应体 与 CLI 相同的结构化错误文档(status: "error"),非 FastAPI 默认格式
鉴权 --token 给出后要求 Authorization: Bearer <token> 或 X-EET-Token: <token>,缺失/不符返回 401(body 同样是结构化错误文档,code EET_UNAUTHORIZED);不给 --token 则不鉴权
stdout 回退 命令不支持 --json 时(如 --version)回退捕获 stdout,包成 {"output": "...", "exit_code": 0}
绑定地址 默认 127.0.0.1,--host 显式放开(对外开放务必配合 --token,并置于反向代理/TLS 之后)

FastAPI 未安装时 server 命令输出结构化错误与安装指引(pip install "easy-encryption-tool[server]"),其余命令不受影响。

Release files for easy-encryption-tool 3.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for easy-encryption-tool 3.2.1
File Size Uploaded
easy_encryption_tool-3.2.1.tar.gz 308.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for easy-encryption-tool 3.2.1
File Interpreter ABI Platform
easy_encryption_tool-3.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 633.8 kB

Release files / easy_encryption_tool-3.2.1.tar.gz

Download URL easy_encryption_tool-3.2.1.tar.gz
Size 308.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9775fb9451385d192b48c16336aa42adc5305d23acef495be94dbd5943820bda
BLAKE2b-256 checksum
How to use checksums
c7830d38115f907bd962a596fb42c05aecf6ae2c0d62d25ab8196f5e077f8510
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.7

Release files / easy_encryption_tool-3.2.1-py3-none-any.whl

Download URL easy_encryption_tool-3.2.1-py3-none-any.whl
Size 325.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cde6ad657e85ee05b295a15ca3a8af17ccbbc87b3237183243e574dac1c28493
BLAKE2b-256 checksum
How to use checksums
76fd46fca403bbb18883292894db41e57b00ae3699f9b73f16fc454b5e454d2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.7

Release history Release notifications | RSS feed

3.3.1

2 release files

3.3.0

1 release file

3.2.2

2 release files

This release

3.2.1 This release

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.2

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.8.2

2 release files

2.8.0

2 release files

2.6.0

2 release files

2.5.0

1 release file

2.4.9

1 release file

2.4.8

1 release file

2.4.7

1 release file

2.4.6

1 release file

2.4.4

1 release file

2.4.3

1 release file

2.4.2

1 release file

2.4.1

1 release file

2.4.0

1 release file

2.3.9

1 release file

2.3.8

1 release file

2.3.7

1 release file

2.3.6

1 release file

2.3.5

1 release file

2.3.4

1 release file

2.3.3

1 release file

2.3.2

1 release file

2.3.1

1 release file

2.3.0

1 release file

2.2.5

1 release file

2.2.4

1 release file

2.2.3

1 release file

2.2.2

1 release file

2.2.1

1 release file

2.2.0

1 release file

2.1.9

1 release file

2.1.8

1 release file

2.1.7

1 release file

2.1.6

1 release file

2.1.5

1 release file

2.1.4

1 release file

2.1.3

1 release file

2.1.2

1 release file

2.1.1

1 release file

2.1.0

1 release file

2.0.9

1 release file

2.0.8

1 release file

2.0.7

1 release file

2.0.6

1 release file

2.0.5

1 release file

2.0.4

1 release file

2.0.3

1 release file

2.0.2

1 release file

2.0.1

1 release file

2.0.0

1 release file

1.2.1

1 release file

1.2.0

1 release file

1.1.6

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page