131 行
5.7 KiB
Swift
131 行
5.7 KiB
Swift
import XCTest
|
||
@testable import KyberSDK
|
||
|
||
/**
|
||
* KyberSDK 单元测试套件
|
||
*
|
||
* 测试覆盖:
|
||
* - 三种变体(512 / 768 / 1024)密钥尺寸验证
|
||
* - 三种变体完整 KEM 全流程(密钥生成 → 封装 → 解封装 → 比对)
|
||
* - 错误密钥解封装(验证 IND-CCA2 安全属性)
|
||
* - 输入参数校验(非法公钥 / 私钥 / 密文长度)
|
||
* - Kyber768 性能基线
|
||
*/
|
||
final class KyberSDKTests: XCTestCase {
|
||
|
||
// MARK: - Kyber512 测试
|
||
|
||
/// 验证 Kyber512 密钥尺寸符合规范
|
||
func testKyber512KeySizes() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber512)
|
||
XCTAssertEqual(kp.publicKey.count, 800, "Kyber512 公钥应为 800 字节")
|
||
XCTAssertEqual(kp.secretKey.count, 1632, "Kyber512 私钥应为 1632 字节")
|
||
}
|
||
|
||
/// Kyber512 完整 KEM 流程:密钥生成 → 封装 → 解封装 → 共享密钥必须一致
|
||
func testKyber512RoundTrip() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber512)
|
||
let enc = try KyberKEM.encapsulate(variant: .kyber512, publicKey: kp.publicKey)
|
||
let dec = try KyberKEM.decapsulate(variant: .kyber512, ciphertext: enc.ciphertext, secretKey: kp.secretKey)
|
||
|
||
XCTAssertEqual(enc.ciphertext.count, 768, "Kyber512 密文应为 768 字节")
|
||
XCTAssertEqual(enc.sharedSecret.count, 32, "共享密钥应为 32 字节")
|
||
XCTAssertEqual(dec.count, 32, "解封装共享密钥应为 32 字节")
|
||
XCTAssertEqual(enc.sharedSecret, dec, "封装和解封装的共享密钥必须完全一致")
|
||
}
|
||
|
||
/// Kyber512 错误密钥测试:使用错误私钥解封装,共享密钥应与封装方不同(IND-CCA2)
|
||
func testKyber512WrongKey() throws {
|
||
let alice = try KyberKEM.generateKeyPair(variant: .kyber512)
|
||
let bob = try KyberKEM.generateKeyPair(variant: .kyber512)
|
||
// 发送方使用 Alice 的公钥封装
|
||
let enc = try KyberKEM.encapsulate(variant: .kyber512, publicKey: alice.publicKey)
|
||
// Bob 用自己的私钥解封装 —— 应得到不同的(伪随机)共享密钥
|
||
let dec = try KyberKEM.decapsulate(variant: .kyber512, ciphertext: enc.ciphertext, secretKey: bob.secretKey)
|
||
XCTAssertNotEqual(enc.sharedSecret, dec, "使用错误私钥不应恢复正确的共享密钥(IND-CCA2)")
|
||
}
|
||
|
||
// MARK: - Kyber768 测试
|
||
|
||
/// 验证 Kyber768 密钥尺寸符合规范
|
||
func testKyber768KeySizes() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber768)
|
||
XCTAssertEqual(kp.publicKey.count, 1184, "Kyber768 公钥应为 1184 字节")
|
||
XCTAssertEqual(kp.secretKey.count, 2400, "Kyber768 私钥应为 2400 字节")
|
||
}
|
||
|
||
/// Kyber768 完整 KEM 流程
|
||
func testKyber768RoundTrip() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber768)
|
||
let enc = try KyberKEM.encapsulate(variant: .kyber768, publicKey: kp.publicKey)
|
||
let dec = try KyberKEM.decapsulate(variant: .kyber768, ciphertext: enc.ciphertext, secretKey: kp.secretKey)
|
||
|
||
XCTAssertEqual(enc.ciphertext.count, 1088, "Kyber768 密文应为 1088 字节")
|
||
XCTAssertEqual(enc.sharedSecret, dec, "封装和解封装的共享密钥必须完全一致")
|
||
}
|
||
|
||
// MARK: - Kyber1024 测试
|
||
|
||
/// 验证 Kyber1024 密钥尺寸符合规范
|
||
func testKyber1024KeySizes() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber1024)
|
||
XCTAssertEqual(kp.publicKey.count, 1568, "Kyber1024 公钥应为 1568 字节")
|
||
XCTAssertEqual(kp.secretKey.count, 3168, "Kyber1024 私钥应为 3168 字节")
|
||
}
|
||
|
||
/// Kyber1024 完整 KEM 流程
|
||
func testKyber1024RoundTrip() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber1024)
|
||
let enc = try KyberKEM.encapsulate(variant: .kyber1024, publicKey: kp.publicKey)
|
||
let dec = try KyberKEM.decapsulate(variant: .kyber1024, ciphertext: enc.ciphertext, secretKey: kp.secretKey)
|
||
|
||
XCTAssertEqual(enc.ciphertext.count, 1568, "Kyber1024 密文应为 1568 字节")
|
||
XCTAssertEqual(enc.sharedSecret, dec, "封装和解封装的共享密钥必须完全一致")
|
||
}
|
||
|
||
// MARK: - 输入参数校验测试
|
||
|
||
/// 公钥长度不符时应抛出 KyberError.invalidPublicKeySize
|
||
func testInvalidPublicKeySize() {
|
||
XCTAssertThrowsError(
|
||
try KyberKEM.encapsulate(variant: .kyber768, publicKey: Data(repeating: 0, count: 100)),
|
||
"公钥长度不匹配时应抛出错误"
|
||
)
|
||
}
|
||
|
||
/// 私钥长度不符时应抛出 KyberError.invalidSecretKeySize
|
||
func testInvalidSecretKeySize() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber768)
|
||
let enc = try KyberKEM.encapsulate(variant: .kyber768, publicKey: kp.publicKey)
|
||
XCTAssertThrowsError(
|
||
try KyberKEM.decapsulate(
|
||
variant: .kyber768,
|
||
ciphertext: enc.ciphertext,
|
||
secretKey: Data(repeating: 0, count: 10)
|
||
),
|
||
"私钥长度不匹配时应抛出错误"
|
||
)
|
||
}
|
||
|
||
/// 密文长度不符时应抛出 KyberError.invalidCiphertextSize
|
||
func testInvalidCiphertextSize() throws {
|
||
let kp = try KyberKEM.generateKeyPair(variant: .kyber768)
|
||
XCTAssertThrowsError(
|
||
try KyberKEM.decapsulate(
|
||
variant: .kyber768,
|
||
ciphertext: Data(repeating: 0, count: 10),
|
||
secretKey: kp.secretKey
|
||
),
|
||
"密文长度不匹配时应抛出错误"
|
||
)
|
||
}
|
||
|
||
// MARK: - 性能测试
|
||
|
||
/// Kyber768 密钥生成性能基线(10 次迭代平均值)
|
||
func testKyber768Performance() throws {
|
||
measure {
|
||
_ = try? KyberKEM.generateKeyPair(variant: .kyber768)
|
||
}
|
||
}
|
||
} |