104 lines
3.7 KiB
Swift
104 lines
3.7 KiB
Swift
//
|
|||
|
|
// 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))
|
||
|
|
}
|
||
|
|
}
|