173 行
6.7 KiB
Markdown
173 行
6.7 KiB
Markdown
|
|
# KyberSDK — iOS / macOS Swift Package
|
|||
|
|
|
|||
|
|
基于 CRYSTALS-Kyber(ML-KEM,NIST FIPS 203)后量子密钥封装机制的 Swift Package,
|
|||
|
|
支持 iOS 14+ / macOS 11+ 及全平台架构(arm64 真机、arm64/x86_64 模拟器)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 环境要求
|
|||
|
|
|
|||
|
|
| 工具 | 最低版本 |
|
|||
|
|
|------|---------|
|
|||
|
|
| Xcode | 15.0 |
|
|||
|
|
| iOS | 14.0 |
|
|||
|
|
| macOS | 11.0 |
|
|||
|
|
| Swift | 5.9 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 支持的平台与架构
|
|||
|
|
|
|||
|
|
| 平台 | 架构 |
|
|||
|
|
|------|-----|
|
|||
|
|
| iOS 真机 | `arm64` |
|
|||
|
|
| iOS 模拟器(Intel Mac) | `x86_64` |
|
|||
|
|
| iOS 模拟器(Apple Silicon Mac) | `arm64` |
|
|||
|
|
| macOS | `arm64`、`x86_64` |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 集成方法
|
|||
|
|
|
|||
|
|
### 方式一:本地 Swift Package(推荐开发阶段)
|
|||
|
|
|
|||
|
|
1. 在 Xcode 中选择 **File → Add Package Dependencies → Add Local…**
|
|||
|
|
2. 选择本仓库中的 `ios/` 目录(包含 `Package.swift`)
|
|||
|
|
3. 在弹出框中勾选 **KyberSDK**,选择目标 Target,点击 Add Package
|
|||
|
|
|
|||
|
|
### 方式二:SPM 依赖声明
|
|||
|
|
|
|||
|
|
```swift
|
|||
|
|
// Package.swift
|
|||
|
|
.package(path: "../ios"), // 本地路径
|
|||
|
|
// 或使用远程 URL:
|
|||
|
|
// .package(url: "https://your-repo/KyberSDK", from: "1.0.0"),
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## API 使用示例
|
|||
|
|
|
|||
|
|
```swift
|
|||
|
|
import KyberSDK
|
|||
|
|
|
|||
|
|
// ── 接收方:生成密钥对 ────────────────────────────────────────────────
|
|||
|
|
let keyPair = try KyberKEM.generateKeyPair(variant: .kyber768)
|
|||
|
|
// keyPair.publicKey → 可公开分发(Data)
|
|||
|
|
// keyPair.secretKey → 安全存储,建议存入 iOS Keychain
|
|||
|
|
|
|||
|
|
// ── 发送方:封装共享密钥 ──────────────────────────────────────────────
|
|||
|
|
let result = try KyberKEM.encapsulate(variant: .kyber768, publicKey: keyPair.publicKey)
|
|||
|
|
// result.ciphertext → 传输给接收方(Data)
|
|||
|
|
// result.sharedSecret → 本地保留,用于对称加密(AES-GCM、ChaCha20-Poly1305)
|
|||
|
|
|
|||
|
|
// ── 接收方:解封装恢复共享密钥 ───────────────────────────────────────
|
|||
|
|
let sharedSecret = try KyberKEM.decapsulate(
|
|||
|
|
variant: .kyber768,
|
|||
|
|
ciphertext: result.ciphertext,
|
|||
|
|
secretKey: keyPair.secretKey
|
|||
|
|
)
|
|||
|
|
// result.sharedSecret == sharedSecret ✓(密文合法时)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **注意**:所有方法均为同步调用,建议在后台队列执行:
|
|||
|
|
> ```swift
|
|||
|
|
> let kp = try await Task.detached(priority: .userInitiated) {
|
|||
|
|
> try KyberKEM.generateKeyPair(variant: .kyber768)
|
|||
|
|
> }.value
|
|||
|
|
> ```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 支持的安全级别
|
|||
|
|
|
|||
|
|
| 枚举值 | KYBER_K | NIST 级别 | 经典安全性 | 公钥 | 私钥 | 密文 |
|
|||
|
|
|--------|---------|----------|----------|-----|-----|-----|
|
|||
|
|
| `.kyber512` | 2 | Level 1 | ~AES-128 | 800 B | 1632 B | 768 B |
|
|||
|
|
| `.kyber768` | 3 | Level 3 | ~AES-192 | 1184 B | 2400 B | 1088 B |
|
|||
|
|
| `.kyber1024` | 4 | Level 5 | ~AES-256 | 1568 B | 3168 B | 1568 B |
|
|||
|
|
|
|||
|
|
共享密钥固定为 **32 字节**(三种变体相同)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 运行测试
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ios
|
|||
|
|
swift test
|
|||
|
|
# 预期输出:11 项测试全部通过
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
测试覆盖:
|
|||
|
|
|
|||
|
|
| 测试名称 | 说明 |
|
|||
|
|
|---------|------|
|
|||
|
|
| `testKyber512/768/1024KeySizes` | 密钥尺寸符合规范 |
|
|||
|
|
| `testKyber512/768/1024RoundTrip` | 完整 KEM 流程,共享密钥必须一致 |
|
|||
|
|
| `testKyber512WrongKey` | 错误私钥不能恢复正确共享密钥(IND-CCA2) |
|
|||
|
|
| `testInvalidPublicKeySize` | 公钥长度不符时抛出错误 |
|
|||
|
|
| `testInvalidSecretKeySize` | 私钥长度不符时抛出错误 |
|
|||
|
|
| `testInvalidCiphertextSize` | 密文长度不符时抛出错误 |
|
|||
|
|
| `testKyber768Performance` | 密钥生成性能基线 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 包结构详解
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
ios/
|
|||
|
|
├── Package.swift # SPM 包描述(iOS 14+ / macOS 11+)
|
|||
|
|
├── Sources/
|
|||
|
|
│ ├── CKyber/ # C 实现层(单 target 包含三种变体)
|
|||
|
|
│ │ ├── include/ # 对外暴露的头文件
|
|||
|
|
│ │ │ ├── kyber_sdk.h # 伞头文件(包含 api.h 及 randombytes 声明)
|
|||
|
|
│ │ │ ├── api.h # 三种变体函数声明
|
|||
|
|
│ │ │ └── ...(其余内部头文件)
|
|||
|
|
│ │ ├── internal/ # .inc 文件(不直接编译,由变体 .c 文件 #include)
|
|||
|
|
│ │ │ ├── kem.inc # kem.c 内容副本
|
|||
|
|
│ │ │ ├── indcpa.inc # indcpa.c 内容副本
|
|||
|
|
│ │ │ └── ...(poly / ntt / cbd / reduce / verify / symmetric_shake)
|
|||
|
|
│ │ ├── kyber512.c # 翻译单元:#define KYBER_K 2
|
|||
|
|
│ │ ├── kyber768.c # 翻译单元:#define KYBER_K 3
|
|||
|
|
│ │ ├── kyber1024.c # 翻译单元:#define KYBER_K 4
|
|||
|
|
│ │ ├── fips202.c # SHA3/SHAKE(与 KYBER_K 无关,编译一次)
|
|||
|
|
│ │ └── randombytes_ios.c # arc4random_buf 包装
|
|||
|
|
│ └── KyberSDK/ # Swift 封装层
|
|||
|
|
│ ├── KyberTypes.swift # KyberVariant / KyberKeyPair / KyberError
|
|||
|
|
│ └── KyberKEM.swift # 主 API:generateKeyPair / encapsulate / decapsulate
|
|||
|
|
├── Tests/
|
|||
|
|
│ └── KyberSDKTests/
|
|||
|
|
│ └── KyberSDKTests.swift # 11 项单元测试
|
|||
|
|
└── KyberDemo/ # SwiftUI 演示 App 源文件
|
|||
|
|
├── KyberDemoApp.swift
|
|||
|
|
├── ContentView.swift
|
|||
|
|
└── README.md # Demo 集成说明
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 多变体编译原理(.inc 翻译单元技巧)
|
|||
|
|
|
|||
|
|
Kyber C 实现通过编译时常量 `KYBER_K` 区分变体,同一源文件在不同 `KYBER_K` 下产生不同符号名。
|
|||
|
|
为在单一 SPM target 中同时支持三种变体:
|
|||
|
|
|
|||
|
|
1. 将所有变体相关的 `.c` 文件重命名为 `.inc`(放在 `internal/`),SPM 不直接编译它们。
|
|||
|
|
2. 创建三个"驱动"翻译单元(`kyber512/768/1024.c`),各自先 `#define KYBER_K`,再 `#include` 所有 `.inc` 文件。
|
|||
|
|
3. `fips202.c` 与 KYBER_K 无关,单独编译一次;链接器对三份对象文件中的相同符号自动去重。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
kyber512.c (#define KYBER_K 2) → pqcrystals_kyber512_ref_keypair 等
|
|||
|
|
kyber768.c (#define KYBER_K 3) → pqcrystals_kyber768_ref_keypair 等
|
|||
|
|
kyber1024.c (#define KYBER_K 4) → pqcrystals_kyber1024_ref_keypair 等
|
|||
|
|
fips202.c → pqcrystals_kyber_fips202_ref_* (共享,去重)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 安全注意事项
|
|||
|
|
|
|||
|
|
1. **私钥存储**:私钥应存入 iOS Keychain(`kSecClassKey`),不应明文持久化。
|
|||
|
|
2. **共享密钥用途**:建议通过 HKDF 从共享密钥派生实际加密/认证密钥。
|
|||
|
|
3. **密文完整性**:解封装不抛出错误不代表密文合法(IND-CCA2 特性),
|
|||
|
|
应通过上层协议(TLS / AEAD)保证完整性。
|