// // BigUIntPaddingTests.swift // PortalKitTests // // Verification of BigUInt 256-byte padding, truncation, and hex conversion edge cases. // import XCTest @testable import PortalKit final class BigUIntPaddingTests: XCTestCase { func testZeroPaddingTo256Bytes() { let zero = BigUInt(0) let padded = zero.toPadded256Data() XCTAssertEqual(padded.count, 256, "Zero must produce exactly 256 bytes") XCTAssertEqual(padded, Data(repeating: 0, count: 256)) } func testSmallNumberPadding() { let one = BigUInt(1) let padded = one.toPadded256Data() XCTAssertEqual(padded.count, 256) XCTAssertEqual(padded.prefix(255), Data(repeating: 0, count: 255)) XCTAssertEqual(padded.last, 1) let value = BigUInt(0x12345678) let paddedValue = value.toPadded256Data() XCTAssertEqual(paddedValue.count, 256) XCTAssertEqual(paddedValue.suffix(4), Data([0x12, 0x34, 0x56, 0x78])) } func testExact256ByteValue() { // Portal TV 2048-bit prime N is exactly 256 bytes let N = PortalSrpClient.N let paddedN = N.toPadded256Data() XCTAssertEqual(paddedN.count, 256) XCTAssertEqual(paddedN.first, 0xFF) XCTAssertEqual(paddedN.last, 0xFF) // Raw serialize count for 2048-bit N starting with 0xFF is 256 bytes XCTAssertEqual(N.serialize().count, 256) XCTAssertEqual(paddedN, N.serialize()) } func testVariableLengthPadding() { let val = BigUInt(0xAABB) // Pad to 4 bytes: 00 00 AA BB let p4 = val.toPaddedData(byteCount: 4) XCTAssertEqual(p4, Data([0x00, 0x00, 0xAA, 0xBB])) // Pad to 2 bytes: AA BB let p2 = val.toPaddedData(byteCount: 2) XCTAssertEqual(p2, Data([0xAA, 0xBB])) // Truncate to 1 byte: BB (suffix) let p1 = val.toPaddedData(byteCount: 1) XCTAssertEqual(p1, Data([0xBB])) } func testHexConversionEdgeCases() { // Empty data XCTAssertEqual(SrpFormat.bytesToHex(Data()), "") XCTAssertEqual(SrpFormat.hexToBytes(""), Data()) // Leading zero single byte XCTAssertEqual(SrpFormat.bytesToHex(Data([0x05])), "05") XCTAssertEqual(SrpFormat.hexToBytes("05"), Data([0x05])) // High nybble / low nybble XCTAssertEqual(SrpFormat.bytesToHex(Data([0xF0, 0x0F])), "f00f") XCTAssertEqual(SrpFormat.hexToBytes("f00f"), Data([0xF0, 0x0F])) XCTAssertEqual(SrpFormat.hexToBytes("F00F"), Data([0xF0, 0x0F])) // case insensitive // Whitespace and newline tolerance let spacedHex = " f0 0f \n 12\t 34 \r\n" XCTAssertEqual(SrpFormat.hexToBytes(spacedHex), Data([0xF0, 0x0F, 0x12, 0x34])) // Invalid: odd length XCTAssertNil(SrpFormat.hexToBytes("123")) XCTAssertNil(SrpFormat.hexToBytes("f")) // Invalid: non-hex characters XCTAssertNil(SrpFormat.hexToBytes("123g")) XCTAssertNil(SrpFormat.hexToBytes("zz")) XCTAssertNil(SrpFormat.hexToBytes("!!")) } func testConstantTimeEqualsEdgeCases() { let a = Data([0x01, 0x02, 0x03, 0x04]) let b = Data([0x01, 0x02, 0x03, 0x04]) let diffStart = Data([0xFF, 0x02, 0x03, 0x04]) let diffMid = Data([0x01, 0xFF, 0x03, 0x04]) let diffEnd = Data([0x01, 0x02, 0x03, 0xFF]) let diffLength = Data([0x01, 0x02, 0x03]) XCTAssertTrue(SrpFormat.constantTimeEquals(a, b)) XCTAssertTrue(SrpFormat.constantTimeEquals(Data(), Data())) XCTAssertFalse(SrpFormat.constantTimeEquals(a, diffStart)) XCTAssertFalse(SrpFormat.constantTimeEquals(a, diffMid)) XCTAssertFalse(SrpFormat.constantTimeEquals(a, diffEnd)) XCTAssertFalse(SrpFormat.constantTimeEquals(a, diffLength)) } }