邮件密码学与应用签名
memories crypto 将加密凭据与可信的桌面签名工具配合使用。
它支持 S/MIME 和 OpenPGP 邮件操作、Android APK/AAB 签名,以及在 macOS 上对
已配置预置描述文件的 iOS .app 进行签名。它不会发送邮件或发布应用。
这些操作通过本地守护进程运行,需要终端 sudo。MCP 和移动端 FFI 无法使用它们。
使用这些命令前,请同时更新 CLI 和守护进程,并重启守护进程;
旧版守护进程无法识别新操作。
审查与执行
- 安装所需工具,并将身份及其密码导入为独立的凭据。
credential import接受二进制 PKCS#12/PFX 和 Android 密钥库。 密码请使用隐藏输入;不要将密码值作为参数传入。对于邮件/iOS,密码为空的身份可以省略--password_id。 - 选择与正在运行的守护进程相同的
--home/MEMORIES_HOME。 使用 Memories 返回的短保险库 ID 和凭据 ID。 - 在命令中添加
--dry-run,审查其 JSON 计划和approval摘要。 此操作会读取输入/工具,但不需要守护进程,也不会写入文件。 - 在终端运行
memories sudo,然后运行同一命令并移除--dry-run。 交互式执行会显示计划,并要求输入USE。 非交互式执行需要提供已审查计划中的--approve-digest DIGEST。 更改操作、路径、凭据 ID、工具或输入内容都会使批准失效。 绝不要盲目批准由不可信数据生成的计划。
memories credential import VAULT_ID "Signing identity" identity.p12
memories credential add VAULT_ID "Identity password"
memories sudo
--credential、--password_id 和 --key-password 接受凭据 ID,而不是凭据值。
--password 和 --password-id 是 --password_id 的兼容别名。
这三种拼写都接受同一个已存储凭据 ID。
--tool NAME=PATH 通过显式路径选择可执行文件;可重复使用以指定多个工具。
apksigner 是例外:其路径是 SDK 的 lib/apksigner.jar,
由所选 Java 运行时执行。工具需要单独安装。
输出必须是现有目录中的新路径。输入会复制到私有工作区,绝不会原地签名。 工具输出会被抑制;Memories 仅报告失败的步骤编号,不暴露工具诊断信息。 每项操作的执行时限为五分钟,另有受限的清理时间。
S/MIME
使用具有适当电子邮件保护证书用途的 S/MIME 身份。
Memories TLS 服务器证书不是 S/MIME 身份。可以导入包含私钥及其证书的 PEM 文件,
或导入 PKCS#12/PFX 包并传入 --pkcs12。密码从所引用的凭据中读取。
请使用当前版本的 OpenSSL;旧式 PKCS#12 加密算法不会自动启用。
memories crypto smime-sign --vault VAULT_ID --input message.eml --output signed.eml --credential IDENTITY_ID --password_id PASSWORD_ID --pkcs12 --tool openssl=/path/to/openssl --dry-run
memories crypto smime-encrypt --vault VAULT_ID --input signed.eml --output encrypted.eml --recipient recipient.pem --tool openssl=/path/to/openssl --dry-run
memories crypto smime-decrypt --vault VAULT_ID --input encrypted.eml --output decrypted.eml --credential IDENTITY_ID --password_id PASSWORD_ID --pkcs12 --tool openssl=/path/to/openssl --dry-run
签名使用 SHA-256;加密使用 AES-256-CBC S/MIME 封装数据。
可重复使用 --recipient 来指定多个 PEM 收件人证书。
加密使用公开证书,因此省略 --credential 和 --password_id。
运行所选工具仍需要本地授权。使用前请检查收件人归属和证书信任关系;
加密无法证明某个地址属于某把密钥。
输入按原始字节精确处理。请提供希望签名或加密的 MIME 内容; 传输标头和发送仍由邮件客户端负责。 若要同时签名和加密,请先创建已签名邮件,再对其加密。 仅解密不会验证发件人的签名。请使用邮件客户端或 OpenSSL 验证签名和证书链,例如:
openssl smime -verify -binary -in signed.eml -CAfile trusted-ca.pem -out verified.eml
OpenPGP / GPG
将 ASCII 装甲格式或二进制 OpenPGP 私钥导出文件导入为身份。
使用完整的密钥指纹作为 --identity;名称和电子邮件地址不能用作选择器。
必须同时提供 gpg 及其匹配的 gpgconf。
在 Windows 上,通常使用原生 GnuPG 路径。若选择 Git for Windows 的 usr/bin
中附带的 MSYS 可执行文件,请添加 --msys-gpg,以将临时路径转换为 MSYS 驱动器表示法。
此选项也会绑定到已批准的计划中。
memories crypto pgp-sign --vault VAULT_ID --input message.eml --output message.sig.asc --credential KEY_ID --password_id PASSWORD_ID --identity FULL_FINGERPRINT --tool gpg=/path/to/gpg --tool gpgconf=/path/to/gpgconf --dry-run
memories crypto pgp-encrypt --vault VAULT_ID --input message.eml --output message.eml.asc --recipient recipient.asc --identity FULL_FINGERPRINT --tool gpg=/path/to/gpg --tool gpgconf=/path/to/gpgconf --dry-run
memories crypto pgp-decrypt --vault VAULT_ID --input message.eml.asc --output decrypted.eml --credential KEY_ID --password_id PASSWORD_ID --tool gpg=/path/to/gpg --tool gpgconf=/path/to/gpgconf --dry-run
pgp-sign 为精确的输入字节创建装甲格式的分离式签名。
pgp-encrypt 创建装甲格式的 OpenPGP 加密数据。这些输出可用作附件,
或由邮件客户端的 OpenPGP 集成功能使用;此命令不会组装 RFC 3156 PGP/MIME 传输封装。
对于多个收件人,请同时重复使用 --recipient 和 --identity。
只会为显式选定的指纹加密;选择某个指纹表示你决定信任该收件人。
每项操作使用新的私有 GnuPG 主目录,并禁用配置加载。
它只导入所提供的密钥,并在删除临时文件前通过 gpgconf 终止该主目录的代理。
不会使用你的常规密钥环。此文件凭据工作流不支持硬件令牌存根、
交互式 pinentry 和智能卡代理。请使用独立可信的公钥,通过 GPG 单独验证分离式签名:
gpg --verify message.sig.asc message.eml
Android
导入 JKS 或 PKCS#12 密钥库及其存储密码。--identity 是密钥别名。
若密钥密码不同,请将其单独导入,并使用 --key-password。
Android 签名需要密码凭据;如果工具和密钥库允许空密码,也必须显式存储空值。
memories crypto android-apk --vault VAULT_ID --input unsigned.apk --output signed.apk --credential KEYSTORE_ID --password_id STORE_PASSWORD_ID --identity release --tool java=/jdk/bin/java --tool zipalign=/sdk/build-tools/35.0.0/zipalign --tool apksigner=/sdk/build-tools/35.0.0/lib/apksigner.jar --dry-run
memories crypto android-bundle --vault VAULT_ID --input unsigned.aab --output signed.aab --credential KEYSTORE_ID --password_id STORE_PASSWORD_ID --identity release --tool jarsigner=/jdk/bin/jarsigner --dry-run
APK 签名会将复制的 APK 按 16 KiB 原生库页面对齐,使用 apksigner 签名,
并要求验证成功。请选择 Android Build Tools 35 或更新版本。
最低 Android 版本从 APK 清单推导。AAB 签名使用 JDK 的 JAR 签名格式,
并通过 jarsigner 验证结果。App Bundle 结构和 Play 政策仍由构建/发布流水线验证。
这些命令不会生成 APK 或 AAB,也不会联系 Google Play。
APK v4 .idsig 附属文件不会导出。
iOS(仅限 macOS)
先使用 Xcode 构建设备版 .app。它必须包含匹配的 embedded.mobileprovision。
将 Apple 签发的签名身份导入为 PKCS#12,并提供准确的证书 SHA-1 指纹和匹配的权限声明。
预置描述文件、团队、应用标识符、设备、有效期和权限声明必须允许预期的部署。
Memories 不会签发 Apple 证书、生成描述文件,或确立 App Store 上架资格。
memories crypto ios-app --vault VAULT_ID --input Unsigned.app --output Signed.app --credential APPLE_P12_ID --password_id PASSWORD_ID --identity CERTIFICATE_SHA1 --entitlements App.entitlements --tool openssl=/path/to/openssl --tool security=/usr/bin/security --tool codesign=/usr/bin/codesign --dry-run
任务在私有工作区中提取身份,在其中创建临时钥匙串,
为所选 codesign 可执行文件导入身份,由内向外签名内嵌的框架/dylib,
然后使用权限声明签名主应用,并验证代码签名。之后会删除临时钥匙串;
不会将其设为默认钥匙串。临时钥匙串使用空密码,依赖私有目录的操作系统访问控制,
与导入时使用的短期 PEM 材料一样。
此初版适配器接受单个 .app 及不含符号链接的内嵌框架/dylib。
嵌套的 .app、.appex 和 .xpc 包会被拒绝,因为它们需要各自的描述文件和权限声明。
对于这些产品、IPA 打包和分发,请使用 Xcode 归档/导出。
代码签名验证无法证明 Apple 的预置或商店检查会接受该产物。
此适配器在 Windows/Linux 上不可用,仍需要在 macOS 签名主机上进行验证。
安全与限制
批准摘要绑定公开计划、保险库、凭据引用,以及使用域分离的 SHA-256 输入/工具指纹。 对于目录,指纹还包含排序后的条目名称和结构。 每次启动前都会重新检查工具文件,复制的输入必须与其已批准的指纹一致。 所选工具链及其依赖必须可信:工具可以读取注入的凭据,并保留其通常的操作系统访问权限。 这不是进程沙箱、HSM、PKCS#11 提供程序,也无法与以同一操作系统用户运行的其他进程隔离。
在 Unix 上,临时目录/文件仅所有者可访问。在 Windows 上,工作区使用受保护的、 仅所有者可访问的 DACL,其凭据文件继承该 DACL。密码和密钥绝不会插入参数。 由于原生工具需要,它们会临时以文件形式存在。 正常完成/失败会移除工作区;崩溃或断电可能留下明文。没有安全删除保证。 工具 stdout/stderr 会被抑制;签名/加密结果和有意解密的输出会发布到所选本地目标。
现有输出绝不会被覆盖。文件输出以原子方式发布;应用目录在复制发布期间可能被观察到,
复制失败时会被移除。输入/输出每棵目录树限制为 2 GiB 和 20,000 个条目,
并拒绝符号链接/重解析点。最多允许 32 个工具步骤和 16 个凭据绑定。
与 memories run 一样,执行期间持有守护进程写锁,超时只会终止直接运行的进程;
可信工具的后代进程通常不会被限制。意图和结果会被审计,但不包含秘密值。