Init
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Srp6aExchangeTests.swift
|
||||
// PortalKitTests
|
||||
//
|
||||
// Verification of 2048-bit SRP-6a end-to-end key exchange with mock server parameters.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import PortalKit
|
||||
|
||||
final class Srp6aExchangeTests: XCTestCase {
|
||||
func testEndToEndExchangeSuccess() throws {
|
||||
let pin = "654321"
|
||||
let mockCertHash = SrpGroup.rfc5054_2048.hashAlgorithm.hash("MOCK_CERT_LEAF_DER".data(using: .utf8)!)
|
||||
|
||||
let server = SrpServerMock(pin: pin)
|
||||
let client = PortalSrpClient()
|
||||
|
||||
// Client computes M1 bound to mock TLS cert hash
|
||||
let clientM1Hex = try client.computeM1(
|
||||
saltHex: server.saltHex,
|
||||
pubBHex: server.pubBHex,
|
||||
pin: pin,
|
||||
tlsCertSha256: mockCertHash
|
||||
)
|
||||
|
||||
XCTAssertFalse(clientM1Hex.isEmpty)
|
||||
XCTAssertNotNil(client.sessionKey)
|
||||
|
||||
// Server verifies client's A and M1
|
||||
let verifyResult = server.verifyClient(
|
||||
pubAHex: client.pubAHex,
|
||||
clientM1Hex: clientM1Hex,
|
||||
serverTlsCertSha256: mockCertHash
|
||||
)
|
||||
|
||||
XCTAssertTrue(verifyResult.success, "Server rejected valid client proof")
|
||||
XCTAssertNotNil(verifyResult.M2Hex)
|
||||
XCTAssertNotNil(verifyResult.token)
|
||||
|
||||
// Client verifies server M2
|
||||
XCTAssertNoThrow(
|
||||
try client.verifyServerM2(serverM2Hex: verifyResult.M2Hex!),
|
||||
"Client failed to verify genuine server M2"
|
||||
)
|
||||
}
|
||||
|
||||
func testWrongPinFailsExchange() throws {
|
||||
let actualPin = "123456"
|
||||
let wrongPin = "999999"
|
||||
let mockCertHash = Data(repeating: 0x42, count: 32)
|
||||
|
||||
let server = SrpServerMock(pin: actualPin)
|
||||
let client = PortalSrpClient()
|
||||
|
||||
// Client computes M1 with wrong PIN
|
||||
let clientM1Hex = try client.computeM1(
|
||||
saltHex: server.saltHex,
|
||||
pubBHex: server.pubBHex,
|
||||
pin: wrongPin,
|
||||
tlsCertSha256: mockCertHash
|
||||
)
|
||||
|
||||
// Server verification MUST fail
|
||||
let verifyResult = server.verifyClient(
|
||||
pubAHex: client.pubAHex,
|
||||
clientM1Hex: clientM1Hex,
|
||||
serverTlsCertSha256: mockCertHash
|
||||
)
|
||||
|
||||
XCTAssertFalse(verifyResult.success)
|
||||
XCTAssertNil(verifyResult.token)
|
||||
XCTAssertNil(verifyResult.M2Hex)
|
||||
XCTAssertTrue(verifyResult.errorMessage?.contains("M1 verification failed") ?? false)
|
||||
}
|
||||
|
||||
func testMultipleRandomExchanges() throws {
|
||||
// Run 5 randomized rounds to verify no modular arithmetic edge cases
|
||||
for round in 1...5 {
|
||||
let pin = String(format: "%06d", round * 111111 % 1000000)
|
||||
let mockCertHash = SrpGroup.rfc5054_2048.hashAlgorithm.hash("CERT_ROUND_\(round)".data(using: .utf8)!)
|
||||
|
||||
let server = SrpServerMock(pin: pin)
|
||||
let client = PortalSrpClient()
|
||||
|
||||
let m1Hex = try client.computeM1(
|
||||
saltHex: server.saltHex,
|
||||
pubBHex: server.pubBHex,
|
||||
pin: pin,
|
||||
tlsCertSha256: mockCertHash
|
||||
)
|
||||
|
||||
let serverRes = server.verifyClient(
|
||||
pubAHex: client.pubAHex,
|
||||
clientM1Hex: m1Hex,
|
||||
serverTlsCertSha256: mockCertHash
|
||||
)
|
||||
|
||||
XCTAssertTrue(serverRes.success, "Round \(round) failed server verification")
|
||||
guard let m2 = serverRes.M2Hex else {
|
||||
XCTFail("Round \(round) missing M2")
|
||||
continue
|
||||
}
|
||||
|
||||
XCTAssertNoThrow(try client.verifyServerM2(serverM2Hex: m2), "Round \(round) failed client M2 verification")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user