Skip to content

Commit

Permalink
Refactor KASWebSocket.swift for managing connection state (#7)
Browse files Browse the repository at this point in the history
* Refactor KASWebSocket.swift for managing connection state

The code changes involve refactoring the KASWebSocket.swift class to manage the WebSocket connection state with Combine. This reorganization includes the creation of a connectionStateSubject and the introduction of connection and disconnection states, as well as a publisher for these states. The code now also performs periodic "pinging" to check the connection status.

* Add token authentication to KASWebSocket connection

The KASWebSocket class has been updated to include a token for authentication during connection. The token is passed in upon initialization and is added to the header of the WebSocket request. The token is also sent as a WebSocket message on connection. The changes also affect KASWebSocket tests to accommodate the new parameter.

* Make `toData` function public

Changed the accessibility of the `toData` function in `NanoTDF` class from internal to public to allow external modules to access this function. This update is crucial for modules relying on this method to convert NanoTDF objects to raw data.

* Add custom message handling to KASWebSocket

Introduced a new callback for handling custom messages and a method for sending custom messages. Updated the logic to call this callback when an unknown message type is received, enhancing flexibility in message processing.

* Mark SymmetricKeyTests as comments and refactor Header handling

Temporarily commented out SymmetricKeyTests due to dependency on nanoTDF.storedKey. Refactored Header struct by removing magicNumber validation and ensuring consistent public init and access for members. Simplified parsing and initialization logic in BinaryParser and other affected files.

* Make ParsingError enum public

Updated the accessibility of the ParsingError enum to public. This change allows other modules to handle parsing errors more effectively by being able to reference and utilize the ParsingError enum.

* Refactor version handling from Data to UInt8

Replaced the version field type in the Header struct from Data to UInt8. Updated related parsing logic and test cases accordingly for improved type safety and consistency.

* Simplify header version handling

Remove explicit `version` parameter from the `Header` struct and use a static version constant instead. This reduces redundancy and simplifies the initialization process. Adjust initialization and test cases to reflect this change.

* Fix boundary checks and remove debug print statements

Added boundary checks for cursor and empty data to prevent crashes during read operations. All debug print statements have been commented out to clean up the output and improve readability.
  • Loading branch information
arkavo-com authored Aug 4, 2024
1 parent 85f4734 commit 88b8f0d
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 266 deletions.
80 changes: 51 additions & 29 deletions OpenTDFKit/BinaryParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class BinaryParser {
}

func read(length: Int) -> Data? {
guard cursor >= 0 else { return nil }
guard !data.isEmpty else { return nil }
guard cursor + length <= data.count else { return nil }
let range = cursor ..< (cursor + length)
cursor += length
Expand All @@ -26,11 +28,11 @@ public class BinaryParser {
else {
return nil
}
let bodyLengthlHex = String(format: "%02x", bodyLength)
print("Body Length Hex:", bodyLengthlHex)
let bodyHexString = body.map { String(format: "%02x", $0) }.joined(separator: " ")
print("Body Hex:", bodyHexString)
print("bodyString: \(bodyString)")
// let bodyLengthlHex = String(format: "%02x", bodyLength)
// print("Body Length Hex:", bodyLengthlHex)
// let bodyHexString = body.map { String(format: "%02x", $0) }.joined(separator: " ")
// print("Body Hex:", bodyHexString)
// print("bodyString: \(bodyString)")
return ResourceLocator(protocolEnum: protocolEnumValue, body: bodyString)
}

Expand Down Expand Up @@ -100,8 +102,8 @@ public class BinaryParser {
print("Failed to read BindingMode")
return nil
}
let eccModeHex = String(format: "%02x", eccAndBindingMode)
print("ECC Mode Hex:", eccModeHex)
// let eccModeHex = String(format: "%02x", eccAndBindingMode)
// print("ECC Mode Hex:", eccModeHex)
let ecdsaBinding = (eccAndBindingMode & (1 << 7)) != 0
let ephemeralECCParamsEnumValue = Curve(rawValue: eccAndBindingMode & 0x7)

Expand All @@ -110,8 +112,8 @@ public class BinaryParser {
return nil
}

print("ecdsaBinding: \(ecdsaBinding)")
print("ephemeralECCParamsEnum: \(ephemeralECCParamsEnum)")
// print("ecdsaBinding: \(ecdsaBinding)")
// print("ephemeralECCParamsEnum: \(ephemeralECCParamsEnum)")

return PolicyBindingConfig(ecdsaBinding: ecdsaBinding, curve: ephemeralECCParamsEnum)
}
Expand All @@ -137,7 +139,7 @@ public class BinaryParser {

func readPolicyBinding(bindingMode: PolicyBindingConfig) -> Data? {
var bindingSize: Int
print("bindingMode", bindingMode)
// print("bindingMode", bindingMode)
if bindingMode.ecdsaBinding {
switch bindingMode.curve {
case .secp256r1, .xsecp256k1:
Expand All @@ -151,7 +153,7 @@ public class BinaryParser {
// GMAC Tag Binding
bindingSize = 16
}
print("bindingSize", bindingSize)
// print("bindingSize", bindingSize)
return read(length: bindingSize)
}

Expand All @@ -177,17 +179,34 @@ public class BinaryParser {
}

public func parseHeader() throws -> Header {
guard let magicNumber = read(length: FieldSize.magicNumberSize),
let version = read(length: FieldSize.versionSize),
let kas = readResourceLocator(),
let eccMode = readEccAndBindingMode(),
let payloadSigMode = readSymmetricAndPayloadConfig(),
let policy = readPolicyField(bindingMode: eccMode)
// print("Starting to parse header")

guard let magicNumber = read(length: FieldSize.magicNumberSize) else {
throw ParsingError.invalidFormat
}
// print("Read Magic Number: \(magicNumber), Expected: \(Header.magicNumber)")
guard magicNumber == Header.magicNumber else {
throw ParsingError.invalidMagicNumber
}

guard let versionData = read(length: FieldSize.versionSize) else {
throw ParsingError.invalidFormat
}
let versionDataInt = Int(versionData[0])
guard versionDataInt == Header.version else {
throw ParsingError.invalidVersion
}
// let version = versionData[0]
// print("Version: \(String(format: "%02X", version))")
guard let kas = readResourceLocator(),
let policyBindingConfig = readEccAndBindingMode(),
let payloadSignatureConfig = readSymmetricAndPayloadConfig(),
let policy = readPolicyField(bindingMode: policyBindingConfig)
else {
throw ParsingError.invalidFormat
}

let ephemeralKeySize = switch eccMode.curve {
let ephemeralPublicKeySize = switch policyBindingConfig.curve {
case .secp256r1:
33
case .secp384r1:
Expand All @@ -197,14 +216,17 @@ public class BinaryParser {
case .xsecp256k1:
33
}
guard let ephemeralKey = read(length: ephemeralKeySize) else {
guard let ephemeralPublicKey = read(length: ephemeralPublicKeySize) else {
throw ParsingError.invalidFormat
}

guard let header = Header(magicNumber: magicNumber, version: version, kas: kas, eccMode: eccMode, payloadSigMode: payloadSigMode, policy: policy, ephemeralKey: ephemeralKey) else {
throw ParsingError.invalidMagicNumber
}
return header
return Header(
kas: kas,
policyBindingConfig: policyBindingConfig,
payloadSignatureConfig: payloadSignatureConfig,
policy: policy,
ephemeralPublicKey: ephemeralPublicKey
)
}

public func parsePayload(config: SignatureAndPayloadConfig) throws -> Payload {
Expand All @@ -216,7 +238,7 @@ public class BinaryParser {
let byte2 = UInt32(lengthData[1]) << 8
let byte3 = UInt32(lengthData[2])
let length: UInt32 = byte1 | byte2 | byte3
print("parsePayload length", length)
// print("parsePayload length", length)
// IV nonce
guard let iv = read(length: FieldSize.payloadIvSize)
else {
Expand All @@ -242,7 +264,7 @@ public class BinaryParser {
}
// cipherText
let cipherTextLength = Int(length) - payloadMACSize - FieldSize.payloadIvSize
print("cipherTextLength", cipherTextLength)
// print("cipherTextLength", cipherTextLength)
guard let ciphertext = read(length: cipherTextLength),
let payloadMAC = read(length: payloadMACSize)
else {
Expand All @@ -258,7 +280,7 @@ public class BinaryParser {
}
let publicKeyLength: Int
let signatureLength: Int
print("config.signatureECCMode", config)
// print("config.signatureECCMode", config)
switch config.signatureCurve {
case .secp256r1, .xsecp256k1:
publicKeyLength = 33
Expand All @@ -273,8 +295,8 @@ public class BinaryParser {
print("signatureECCMode not found")
throw ParsingError.invalidFormat
}
print("publicKeyLength", publicKeyLength)
print("signatureLength", signatureLength)
// print("publicKeyLength", publicKeyLength)
// print("signatureLength", signatureLength)
guard let publicKey = read(length: publicKeyLength),
let signature = read(length: signatureLength)
else {
Expand Down Expand Up @@ -303,7 +325,7 @@ enum FieldSize {
static let maxPayloadMacSize = 32
}

enum ParsingError: Error {
public enum ParsingError: Error {
case invalidFormat
case invalidMagicNumber
case invalidVersion
Expand Down
Loading

0 comments on commit 88b8f0d

Please sign in to comment.