1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCrypto open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftCrypto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.md for the list of SwiftCrypto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import Foundation
import XCTest
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
// Skip tests that require @testable imports of CryptoKit.
#else
#if !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@testable import CryptoKit
#else
@testable import Crypto
#endif
struct ECDHTestGroup: Codable {
let curve: String
let tests: [ECDHTestVector]
}
struct ECDHTestVector: Codable {
let comment: String
let publicKey: String
let privateKey: String
let shared: String
let result: String
let tcId: Int
let flags: [String]
enum CodingKeys: String, CodingKey {
case publicKey = "public"
case privateKey = "private"
case comment
case shared
case result
case tcId
case flags
}
}
class X25519Tests: XCTestCase {
func testSerialization() throws {
let bobsKey = Curve25519.KeyAgreement.PrivateKey()
let privateKey = Curve25519.KeyAgreement.PrivateKey()
let keyData = privateKey.rawRepresentation
let recoveredKey = try orFail { try Curve25519.KeyAgreement.PrivateKey(rawRepresentation: keyData) }
let ss1 = try orFail { try privateKey.sharedSecretFromKeyAgreement(with: bobsKey.publicKey) }
let ss2 = try orFail { try recoveredKey.sharedSecretFromKeyAgreement(with: bobsKey.publicKey) }
XCTAssertEqual(ss1, ss2)
XCTAssertEqual(recoveredKey.rawRepresentation, keyData)
}
func testCompressedKeys() throws {
let x963Positive = Data(base64Encoded: "A+QHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L")!
let key = try P256.KeyAgreement.PublicKey(compressedRepresentation: x963Positive)
XCTAssertEqual(
key.x963Representation.base64EncodedString(),
"BOQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7LE6xvfFkB4Y3VXoOpB/Kp6ngpf3Lce9hDMl7fqaDUfYE="
)
let x963Negative = Data(base64Encoded: "AuQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L")!
let negativeKey = try P256.KeyAgreement.PublicKey(compressedRepresentation: x963Negative)
XCTAssertEqual(
negativeKey.x963Representation.base64EncodedString(),
"BOQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L7FOQgqb+HnMqoXxW+A1WFYfWgI4jhCe8zaEgVl8rgn4="
)
let p384Positive = Data(base64Encoded: "AyEfGE5ySReJyfSruLRdsjvCB5RNWGLk8JYrzIrans3MprXf5Q4nh69bQ2rI4+DNpw==")!
let p384Key = try P384.KeyAgreement.PublicKey(compressedRepresentation: p384Positive)
XCTAssertEqual(
p384Key.x963Representation.base64EncodedString(),
"BCEfGE5ySReJyfSruLRdsjvCB5RNWGLk8JYrzIrans3MprXf5Q4nh69bQ2rI4+DNp22k0ZcxSL1Ljf19pe25Y6UgedrZf1sOLBVVDZxO36mxwUgPUqFp5/0nNmGMDdQeTQ=="
)
let p384Negative = Data(base64Encoded: "AiEfGE5ySReJyfSruLRdsjvCB5RNWGLk8JYrzIrans3MprXf5Q4nh69bQ2rI4+DNpw==")!
let p384NegativeKey = try P384.KeyAgreement.PublicKey(compressedRepresentation: p384Negative)
XCTAssertEqual(
p384NegativeKey.x963Representation.base64EncodedString(),
"BCEfGE5ySReJyfSruLRdsjvCB5RNWGLk8JYrzIrans3MprXf5Q4nh69bQ2rI4+DNp5JbLmjOt0K0cgKCWhJGnFrfhiUmgKTx0+qq8mOxIFZNPrfwrF6WGALYyZ508ivhsg=="
)
let p521Positive = Data(base64Encoded: "AwGUsatNKbCi6jeO1oFHpvhxesJnRxeZ45/sqCvaEZgwnpyj+/SsXjgBViEjvlJUdqentCaUFCwjuYZJM9HpdVq4Iw==")!
let p521Key = try P521.KeyAgreement.PublicKey(compressedRepresentation: p521Positive)
XCTAssertEqual(
p521Key.x963Representation.base64EncodedString(),
"BAGUsatNKbCi6jeO1oFHpvhxesJnRxeZ45/sqCvaEZgwnpyj+/SsXjgBViEjvlJUdqentCaUFCwjuYZJM9HpdVq4IwE8xEGqskayEkbPkQCGqSKfVYPZTkBdEs1ham1IXcqT4HSfoGGw98UwjQRiDPfIv0+vU6ocPbxURTdvwUSWPm72WQ=="
)
let p521Negative = Data(base64Encoded: "AgGUsatNKbCi6jeO1oFHpvhxesJnRxeZ45/sqCvaEZgwnpyj+/SsXjgBViEjvlJUdqentCaUFCwjuYZJM9HpdVq4Iw==")!
let p521NegativeKey = try P521.KeyAgreement.PublicKey(compressedRepresentation: p521Negative)
XCTAssertEqual(
p521NegativeKey.x963Representation.base64EncodedString(),
"BAGUsatNKbCi6jeO1oFHpvhxesJnRxeZ45/sqCvaEZgwnpyj+/SsXjgBViEjvlJUdqentCaUFCwjuYZJM9HpdVq4IwDDO75VTblN7bkwbv95Vt1gqnwmsb+i7TKelZK3ojVsH4tgX55PCDrPcvud8wg3QLBQrFXjwkOrusiQPrtpwZEJpg=="
)
}
func testCompressedKeysUsingAPI() throws {
let x963Positive = Data(base64Encoded: "A+QHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L")!
let key = try P256.KeyAgreement.PublicKey(compressedRepresentation: x963Positive)
XCTAssertEqual(
key.compressedRepresentation,
x963Positive
)
let x963Negative = Data(base64Encoded: "AuQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L")!
let negativeKey = try P256.KeyAgreement.PublicKey(compressedRepresentation: x963Negative)
XCTAssertEqual(
negativeKey.compressedRepresentation,
x963Negative
)
let p384Positive = Data(base64Encoded: "AyEfGE5ySReJyfSruLRdsjvCB5RNWGLk8JYrzIrans3MprXf5Q4nh69bQ2rI4+DNpw==")!
let p384Key = try P384.KeyAgreement.PublicKey(compressedRepresentation: p384Positive)
XCTAssertEqual(
p384Key.compressedRepresentation,
p384Positive
)
let p384Negative = Data(base64Encoded: "AiEfGE5ySReJyfSruLRdsjvCB5RNWGLk8JYrzIrans3MprXf5Q4nh69bQ2rI4+DNpw==")!
let p384NegativeKey = try P384.KeyAgreement.PublicKey(compressedRepresentation: p384Negative)
XCTAssertEqual(
p384NegativeKey.compressedRepresentation,
p384Negative
)
let p521Positive = Data(base64Encoded: "AwGUsatNKbCi6jeO1oFHpvhxesJnRxeZ45/sqCvaEZgwnpyj+/SsXjgBViEjvlJUdqentCaUFCwjuYZJM9HpdVq4Iw==")!
let p521Key = try P521.KeyAgreement.PublicKey(compressedRepresentation: p521Positive)
XCTAssertEqual(
p521Key.compressedRepresentation,
p521Positive
)
let p521Negative = Data(base64Encoded: "AgGUsatNKbCi6jeO1oFHpvhxesJnRxeZ45/sqCvaEZgwnpyj+/SsXjgBViEjvlJUdqentCaUFCwjuYZJM9HpdVq4Iw==")!
let p521NegativeKey = try P521.KeyAgreement.PublicKey(compressedRepresentation: p521Negative)
XCTAssertEqual(
p521NegativeKey.compressedRepresentation,
p521Negative
)
// Check that the uncompressed key gets rejected
let uncompressedX963 = Data(base64Encoded: "BOQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7LE6xvfFkB4Y3VXoOpB/Kp6ngpf3Lce9hDMl7fqaDUfYE=")!
XCTAssertThrowsError(try P256.KeyAgreement.PublicKey(compressedRepresentation: uncompressedX963))
}
func testUncompressedKeys() throws {
let uncompressedX963 = Data(base64Encoded: "BOQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7LE6xvfFkB4Y3VXoOpB/Kp6ngpf3Lce9hDMl7fqaDUfYE=")!
let key = try P256.KeyAgreement.PublicKey(x963Representation: uncompressedX963)
XCTAssertEqual(
key.x963Representation.base64EncodedString(),
"BOQHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7LE6xvfFkB4Y3VXoOpB/Kp6ngpf3Lce9hDMl7fqaDUfYE="
)
let compressedX963Positive = Data(base64Encoded: "A+QHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L")!
XCTAssertThrowsError(try P256.KeyAgreement.PublicKey(x963Representation: compressedX963Positive))
}
func testWycheproof() throws {
try orFail {
try wycheproofTest(
bundleType: self,
jsonName: "x25519_test",
testFunction: { (group: ECDHTestGroup) in
try orFail { try testGroup(group: group) }
})
}
}
func testGroup(group: ECDHTestGroup) throws {
for testVector in group.tests {
let publicKey = try orFail { try Curve25519.KeyAgreement.PublicKey(rawRepresentation: Array(hexString: testVector.publicKey)) }
let privateKey = try orFail { try Curve25519.KeyAgreement.PrivateKey(rawRepresentation: Array(hexString: testVector.privateKey)) }
do {
let expectedSharedSecret = try Array(hexString: testVector.shared)
let testSharedSecret = try Array(privateKey.sharedSecretFromKeyAgreement(with: publicKey).ss)
XCTAssertEqual(testSharedSecret, expectedSharedSecret)
XCTAssert(testVector.result == "valid" || testVector.result == "acceptable")
} catch {
if testVector.flags.contains("LowOrderPublic") {
XCTAssertEqual(testVector.result, "acceptable")
return
}
XCTAssertEqual(testVector.result, "invalid")
}
}
}
}
#endif // CRYPTO_IN_SWIFTPM
|