以下内容均非抄自文档。检查脚本 content/libraries/verify/swift-crypto/run.sh 于2026年10月20日在容器镜像 swift:6.4.1-noble 中运行了 swift-crypto 5.0.3;本页内容必须与它的输出一致,每条事实都列出了对应的输出行。
ECDSA 签名编码
structuredECDSASignature 有 64 字节的 rawRepresentation 和 derRepresentation;它的字节(withUnsafeBytes)就是原始形式。
检查记录
fact ecdsa-signature-encoding = structured
evidence ecdsa-signature-encoding: signature(for:) returns P256.Signing.ECDSASignature: rawRepresentation 64 bytes, derRepresentation starts with 0x30 and converts back: yes, withUnsafeBytes yields the raw form: yes
ECDSA 的 nonce
random同一条消息的两个签名不同;用 RFC 6979 A.2.5 中的密钥和消息签名,也没有得到 RFC 中的 r。
检查记录
fact ecdsa-nonce = random
evidence ecdsa-nonce: two signatures of one message are different; r for the RFC 6979 A.2.5 key and message equals the RFC's r: no
签名时的 low-S
eithers 没有经过规范化:64 个签名中出现了 high-S 值。
检查记录
fact ecdsa-low-s-sign = either
evidence ecdsa-low-s-sign: signatures with s > n/2 among 64: yes
验证时的 high-S
accepts-high-s把 s 替换为 n − s 的签名验证通过。
检查记录
fact ecdsa-low-s-verify = accepts-high-s
evidence ecdsa-low-s-verify: isValidSignature with s replaced by n - s: true
签名调用对哪些内容做哈希
hashes-message-or-digestsignature(for: data) 会先计算哈希;signature(for: SHA256.hash(data: message)) 生成的签名针对原消息验证通过。
检查记录
fact ecdsa-prehash = hashes-message-or-digest
evidence ecdsa-prehash: signature(for: SHA256.hash(data: message)) verifies with isValidSignature(_:for: message): yes
对消息使用的哈希
curve-matched对数据生成的签名可以作为对哈希值的签名验证通过:P-256 对应 SHA-256,P-384 对应 SHA-384,P-521 对应 SHA-512。
检查记录
fact ecdsa-message-hash = curve-matched
evidence ecdsa-message-hash: signature(for: data) verifies as a signature over SHA-256 on P-256: yes, SHA-384 on P-384: yes, SHA-512 on P-521: yes
哈希与曲线绑定
noneP-384 密钥对 SHA-256 摘要签名,签名验证通过。
检查记录
fact ecdsa-hash-curve-binding = none
evidence ecdsa-hash-curve-binding: a P-384 key signed a SHA-256 digest, and the signature verifies: yes
摘要长于曲线的阶
truncatedP-256 密钥对 SHA-512 摘要签名;openssl pkeyutl 把该签名作为对摘要前 32 字节的签名验证通过。
检查记录
fact ecdsa-long-input = truncated
evidence ecdsa-long-input: a P-256 key signed a SHA-512 digest without an error
evidence ecdsa-long-input: openssl pkeyutl verifies that signature over the first 32 digest bytes: yes
格式错误的 ECDSA 签名
throws对于原始 r‖s 签名和 3 个字节的输入,init(derRepresentation:) 抛出 truncatedASN1Field;对于 DER 和 3 个字节的输入,init(rawRepresentation:) 抛出 incorrectParameterSize。
检查记录
fact ecdsa-malformed-signature = throws
evidence ecdsa-malformed-signature: ECDSASignature(derRepresentation:) with the RFC 6979 A.2.5 signature as raw r||s: threw CryptoKitASN1Error.truncatedASN1Field; with 3 bytes: threw CryptoKitASN1Error.truncatedASN1Field
evidence ecdsa-malformed-signature: ECDSASignature(rawRepresentation:) with DER: threw CryptoKitError.incorrectParameterSize; with 3 bytes: threw CryptoKitError.incorrectParameterSize
evidence ecdsa-malformed-signature: isValidSignature for a valid signature over another message: false
ECDSA 曲线
P-256P-384P-521P-256、P-384 和 P-521 的签名与验证均成功;源代码中未声明其他 ECDSA 曲线。
检查记录
fact ecdsa-curves = P-256, P-384, P-521
evidence ecdsa-curves: key types declared in Sources/Crypto and Sources/CryptoExtras: Curve25519 MLDSA65 MLDSA87 MLKEM1024 MLKEM768 P256 P384 P521 XWingMLKEM768X25519
EdDSA
Ed25519Curve25519.Signing(Ed25519);源代码中未声明 Ed448 类型。
检查记录
fact eddsa = Ed25519
确定性 Ed25519 签名
yes同一条消息的两个签名完全相同,且与 RFC 8032 测试 1 的签名一致;OpenSSL 验证通过了 swift-crypto 生成的签名。
检查记录
fact ed25519-deterministic = yes
evidence ed25519-deterministic: RFC 8032 test 1: the derived public key matches: yes, the RFC signature verifies: yes
evidence ed25519-deterministic: swift-crypto's signature with the same key and message equals the RFC signature: yes; two signatures are identical: yes; both verify: yes
evidence ed25519-deterministic: OpenSSL 3.0.13 pkeyutl on a swift-crypto Ed25519 signature: Signature Verified Successfully
S 值非规范的 Ed25519 签名
rejected把 RFC 8032 测试 1 的签名中的 S 替换为 S + L 后,该签名被拒绝。
检查记录
fact ed25519-non-canonical-s = rejected
evidence ed25519-non-canonical-s: the RFC 8032 test 1 signature with S replaced by S + L
Ed25519 小阶公钥
accepted单位元可以作为公钥导入,R 为单位元且 S = 0 的签名验证通过。
检查记录
fact ed25519-small-order-key = accepted
evidence ed25519-small-order-key: the identity point as public key: import accepted; signature R = identity, S = 0 verifies: yes
格式错误的 Ed25519 签名
rejected由 64 个 0xab 字节构成的签名和 63 字节的签名都返回 false。
检查记录
fact ed25519-malformed-signature = rejected
evidence ed25519-malformed-signature: 64 bytes of 0xab: false; 63 bytes of the RFC signature: false
后量子算法
ML-KEMML-DSAX-WingML-KEM 和 X-Wing 封装后都能解封装出相同的密钥,ML-DSA 签名验证通过;X-Wing 经由 HPKE 也能正常工作。
检查记录
fact pqc = ML-KEM, ML-DSA, X-Wing
evidence pqc: ML-KEM-768: public key 1184 bytes, ciphertext 1088 bytes, shared secrets match: yes
evidence pqc: ML-KEM-1024: public key 1568 bytes, ciphertext 1568 bytes, shared secrets match: yes
evidence pqc: ML-DSA-65: public key 1952 bytes, signature 3309 bytes, verifies: yes; ML-DSA-87: signature 4627 bytes, verifies: yes
evidence pqc: X-Wing (XWingMLKEM768X25519): public key 1216 bytes, ciphertext 1120 bytes, shared secrets match: yes
evidence pqc: HPKE with XWingMLKEM768X25519_SHA256_AES_GCM_256 opens its own message: yes
ML-KEM 参数集
ML-KEM-768ML-KEM-1024MLKEM768 和 MLKEM1024 封装后都能解封装出相同的密钥;源代码中未声明 ML-KEM-512 类型。
检查记录
fact ml-kem-parameter-sets = ML-KEM-768, ML-KEM-1024
ML-DSA 参数集
ML-DSA-65ML-DSA-87MLDSA65 和 MLDSA87 的签名与验证均成功;源代码中未声明 ML-DSA-44 类型。
检查记录
fact ml-dsa-parameter-sets = ML-DSA-65, ML-DSA-87
ML-DSA 签名模式
hedged同一条消息的两个 ML-DSA-65 签名不同(对冲签名)。
检查记录
fact ml-dsa-signing = hedged
evidence ml-dsa-signing: two ML-DSA-65 signatures of one message are different
ML-DSA 上下文字符串
supported使用上下文 invoice-v1 生成的签名,用该上下文验证通过,用 invoice-v2 或不带上下文验证则失败。
检查记录
fact ml-dsa-context-string = supported
evidence ml-dsa-context-string: signed with context "invoice-v1": verifies with it yes, with "invoice-v2" no, without a context no
格式错误的 ML-DSA 签名
returns-false截断的签名、3 个字节的输入和错误的消息都返回 false。
检查记录
fact ml-dsa-malformed-signature = returns-false
evidence ml-dsa-malformed-signature: isValidSignature: truncated signature false, 3 bytes false, wrong message false
被修改的 ML-KEM 密文
implicit-rejection翻转密文中的一位后,decapsulate 返回的密钥与发送方的不同。
检查记录
fact ml-kem-modified-ciphertext = implicit-rejection
evidence ml-kem-modified-ciphertext: ML-KEM-768 with one ciphertext bit flipped: decapsulate returned a key that differs from the sender's
后量子私钥
seed-onlyseedRepresentation 对 ML-KEM-768 为 64 字节,对 ML-DSA-65 为 32 字节,由它重建的密钥与原密钥一致。
检查记录
fact pq-private-keys = seed-only
evidence pq-private-keys: ML-KEM-768 seedRepresentation 64 bytes, integrityCheckedRepresentation 96 bytes; ML-DSA-65 seedRepresentation 32 bytes, integrityCheckedRepresentation 64 bytes
evidence pq-private-keys: keys rebuilt from the seed alone have the same public key: ML-KEM-768 yes, ML-DSA-65 yes
公钥格式
spki-pemspki-dersec1-uncompressedsec1-compressedraw-xyraw-32P-256 的 SPKI PEM 与 DER、SEC1 未压缩与压缩形式和原始 x‖y,以及 Ed25519 的 32 个原始字节,均能写出并读回。
检查记录
fact public-key-formats = spki-pem, spki-der, sec1-uncompressed, sec1-compressed, raw-xy, raw-32
evidence public-key-formats: P-256 public key sizes: raw 64, x963 65, compressed 33, DER 91; PEM header -----BEGIN PUBLIC KEY-----; Ed25519 raw 32
evidence public-key-formats: written and read back: spki-pem yes, spki-der yes, sec1-uncompressed yes, sec1-compressed yes, raw-xy yes, raw-32 yes
私钥格式
pkcs8-pempkcs8-dersec1-pemsec1-derraw-scalarseed-32可读取 PEM 或 DER 格式的 PKCS#8 和 SEC1、原始 P-256 标量和 Ed25519 种子;写出 PKCS#8;加密的 PKCS#8 会被拒绝。
检查记录
fact private-key-formats = pkcs8-pem, pkcs8-der, sec1-pem, sec1-der, raw-scalar, seed-32
evidence private-key-formats: P-256 private key written as: derRepresentation PKCS#8 (138 bytes), pemRepresentation -----BEGIN PRIVATE KEY-----, rawRepresentation 32 bytes, x963Representation 97 bytes
evidence private-key-formats: OpenSSL-written P-256 keys read: pkcs8-pem yes, pkcs8-der yes, encrypted-pkcs8 no, sec1-pem yes, sec1-der yes; encrypted PKCS#8: threw CryptoKitASN1Error.invalidPEMDocument