From 8cfee095d3480f44eb40f5058d2566fb93871f1d Mon Sep 17 00:00:00 2001 From: Islam <2553451+qalandarov@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:36:49 +0100 Subject: [PATCH] PeerID 6/n: Unifiy validation (#743) --- bitchat/Models/ReadReceipt.swift | 2 +- .../Noise/NoiseSecurityConsiderations.swift | 5 --- bitchat/Services/NoiseEncryptionService.swift | 4 +- bitchat/Utils/InputValidator.swift | 21 ----------- bitchat/Utils/PeerIDResolver.swift | 8 ---- bitchatTests/Utils/InputValidatorTests.swift | 37 ------------------- 6 files changed, 3 insertions(+), 74 deletions(-) delete mode 100644 bitchatTests/Utils/InputValidatorTests.swift diff --git a/bitchat/Models/ReadReceipt.swift b/bitchat/Models/ReadReceipt.swift index 2e261dae..0884605d 100644 --- a/bitchat/Models/ReadReceipt.swift +++ b/bitchat/Models/ReadReceipt.swift @@ -79,7 +79,7 @@ struct ReadReceipt: Codable { guard let readerIDData = dataCopy.readFixedBytes(at: &offset, count: 8) else { return nil } let readerID = readerIDData.hexEncodedString() - guard InputValidator.validatePeerID(readerID) else { return nil } + guard PeerID(str: readerID).isValid else { return nil } guard let timestamp = dataCopy.readDate(at: &offset), InputValidator.validateTimestamp(timestamp), diff --git a/bitchat/Noise/NoiseSecurityConsiderations.swift b/bitchat/Noise/NoiseSecurityConsiderations.swift index 2ae05854..61a863c3 100644 --- a/bitchat/Noise/NoiseSecurityConsiderations.swift +++ b/bitchat/Noise/NoiseSecurityConsiderations.swift @@ -52,11 +52,6 @@ struct NoiseSecurityValidator { static func validateHandshakeMessageSize(_ data: Data) -> Bool { return data.count <= NoiseSecurityConstants.maxHandshakeMessageSize } - - /// Validate peer ID format using unified validator - static func validatePeerID(_ peerID: String) -> Bool { - return InputValidator.validatePeerID(peerID) - } } // MARK: - Enhanced Noise Session with Security diff --git a/bitchat/Services/NoiseEncryptionService.swift b/bitchat/Services/NoiseEncryptionService.swift index 545b1772..fa9f92e5 100644 --- a/bitchat/Services/NoiseEncryptionService.swift +++ b/bitchat/Services/NoiseEncryptionService.swift @@ -407,7 +407,7 @@ final class NoiseEncryptionService { func initiateHandshake(with peerID: String) throws -> Data { // Validate peer ID - guard NoiseSecurityValidator.validatePeerID(peerID) else { + guard PeerID(str: peerID).isValid else { SecureLogger.warning(.authenticationFailed(peerID: peerID)) throw NoiseSecurityError.invalidPeerID } @@ -430,7 +430,7 @@ final class NoiseEncryptionService { func processHandshakeMessage(from peerID: String, message: Data) throws -> Data? { // Validate peer ID - guard NoiseSecurityValidator.validatePeerID(peerID) else { + guard PeerID(str: peerID).isValid else { SecureLogger.warning(.authenticationFailed(peerID: peerID)) throw NoiseSecurityError.invalidPeerID } diff --git a/bitchat/Utils/InputValidator.swift b/bitchat/Utils/InputValidator.swift index dbba5742..a6a981d9 100644 --- a/bitchat/Utils/InputValidator.swift +++ b/bitchat/Utils/InputValidator.swift @@ -11,27 +11,6 @@ struct InputValidator { // BinaryProtocol caps payload length at UInt16.max (65_535). Leave headroom // for headers/padding by limiting user content to 60_000 bytes. static let maxMessageLength = 60_000 - static let maxPeerIDLength = 64 - static let hexPeerIDLength = 16 // 8 bytes = 16 hex chars - } - - // MARK: - Peer ID Validation - - /// Validates a peer ID from any source (short 16-hex, full 64-hex, or internal alnum/-/_ up to 64) - static func validatePeerID(_ peerID: String) -> Bool { - // Accept short routing IDs (exact 16-hex) - if PeerIDResolver.isShortID(peerID) { return true } - // If length equals short-hex length but isn't valid hex, reject - if peerID.count == Limits.hexPeerIDLength { return false } - // Accept full Noise key hex (exact 64-hex) - if PeerIDResolver.isNoiseKeyHex(peerID) { return true } - // If length equals full key length but isn't valid hex, reject - if peerID.count == Limits.maxPeerIDLength { return false } - // Internal format: alphanumeric + dash/underscore up to 63 (not 16 or 64) - let validCharset = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-_")) - return !peerID.isEmpty && - peerID.count < Limits.maxPeerIDLength && - peerID.rangeOfCharacter(from: validCharset.inverted) == nil } // MARK: - String Content Validation diff --git a/bitchat/Utils/PeerIDResolver.swift b/bitchat/Utils/PeerIDResolver.swift index 1411d59e..151b3aba 100644 --- a/bitchat/Utils/PeerIDResolver.swift +++ b/bitchat/Utils/PeerIDResolver.swift @@ -8,13 +8,5 @@ struct PeerIDResolver { } return id } - - static func isShortID(_ id: String) -> Bool { - return id.count == 16 && Data(hexString: id) != nil - } - - static func isNoiseKeyHex(_ id: String) -> Bool { - return id.count == 64 && Data(hexString: id) != nil - } } diff --git a/bitchatTests/Utils/InputValidatorTests.swift b/bitchatTests/Utils/InputValidatorTests.swift deleted file mode 100644 index f6b2617f..00000000 --- a/bitchatTests/Utils/InputValidatorTests.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// InputValidatorTests.swift -// bitchatTests -// -// This is free and unencumbered software released into the public domain. -// - -import XCTest -@testable import bitchat - -final class InputValidatorTests: XCTestCase { - func test_accepts_short_hex_peer_id() { - XCTAssertTrue(InputValidator.validatePeerID("0011223344556677")) - XCTAssertTrue(InputValidator.validatePeerID("aabbccddeeff0011")) - } - - func test_accepts_full_noise_key_hex() { - let hex64 = String(repeating: "ab", count: 32) // 64 hex chars - XCTAssertTrue(InputValidator.validatePeerID(hex64)) - } - - func test_accepts_internal_alnum_dash_underscore() { - XCTAssertTrue(InputValidator.validatePeerID("peer_123-ABC")) - XCTAssertTrue(InputValidator.validatePeerID("nostr_user_01")) - } - - func test_rejects_invalid_characters() { - XCTAssertFalse(InputValidator.validatePeerID("peer!@#")) - XCTAssertFalse(InputValidator.validatePeerID("gggggggggggggggg")) // not hex for short form - } - - func test_rejects_too_long() { - let tooLong = String(repeating: "a", count: 65) - XCTAssertFalse(InputValidator.validatePeerID(tooLong)) - } -} -