// The Swift Programming Language // https://docs.swift.org/swift-book import Crypto import Foundation public func serializeV1(msg: MessageP) -> Data { let MESSAGE_CAPACITY: Int = countBytes(msg: msg) var serializedData: Data = Data(count: MESSAGE_CAPACITY) // Serialize Header // UGLY: extrapolate in functions serializedData[0] = msg.version serializedData[1] = msg.messageType.rawValue serializedData[2] = msg.devType.rawValue serializedData[3] = msg.RESERVED serializedData[4...7] = msg.signType.rawValue.data // First 8 bytes serializedData[8...15] = msg.timestamp.timeIntervalSince1970.data // 8 Bytes serializedData[16...31] = msg.devID.data // 16 bytes serializedData[32...39] = msg.location.x.data // 8 Bytes serializedData[40...47] = msg.location.y.data // 8 Bytes serializedData[48...55] = msg.location.z.data // 8 Bytes var index = 56 for field in msg.fields { serializedData[index..<(index + 4)] = UInt32(field.key.count).data serializedData[(index + 4)..<(index + 8)] = UInt32(field.value.count).data index += 8 serializedData[index..<(index + field.key.count)] = Data(field.key) index += field.key.count serializedData[index..<(index + field.value.count)] = Data(field.value) index += field.value.count } let paddingBytes = (8 - (index % 8)) % 8 serializedData[index..<(index + paddingBytes)] = Data(count: paddingBytes) index += paddingBytes // Add STOP FIELDS serializedData[index..<(index + 8)] = UInt64(0).data return serializedData } public func signMessage(msgData: Data, signType: SignType, key: P256.Signing.PrivateKey) throws -> [UInt8] { // UGLY We are hypothesisying that signType is P521 switch signType { /* case .P521: return try signP521(object: msgData, key: key).map { value in return value } */ case .P256: return try signP256(object: msgData, key: key).map { value in return value } default: throw CommonError.SIGNATURE_NOT_SUPPORTED } } public func verifyMessageSignature(message: SignedMessage, key: P256.Signing.PublicKey) throws -> Bool { // UGLY Assuming P521 Signature let msgData = serializeV1(msg: message) return try verifySignatureP256(signature: Data(message.signature), object: msgData, key: key) } public func deserializeV1(serializedData: Data) throws -> SignedMessage { // Serialize Header // UGLY: extrapolate in functions let version: UInt8 = serializedData[0] let messageType: MessageType = MessageType(rawValue: serializedData[1])! let devType: DeviceType = DeviceType(rawValue: serializedData[2])! let RESERVED: UInt8 = serializedData[3] let signType: SignType = SignType(rawValue: serializedData[4...7].uint32)! // First 8 bytes let timestamp = serializedData[8...15].double // 8 Bytes let devID = serializedData[16...31].uint128 // 16 bytes let locationX = serializedData[32...39].uint64 // 8 Bytes let locationY = serializedData[40...47].uint64 // 8 Bytes let locationZ = serializedData[48...55].uint64 // 8 Bytes var index = 56 // Deserializing Fields var MORE_FIELDS = true var fields: [Field] = [] while MORE_FIELDS { let nextChunk = serializedData[index..<(index + 8)] let a = nextChunk.map { value in return value } if nextChunk.uint64 == 0 { MORE_FIELDS = false continue } let fieldKeyCount = serializedData[index..<(index + 4)].uint32 let fieldValueCount = serializedData[(index + 4)..<(index + 8)].uint32 index += 8 let key = serializedData[index..<(index + Int(fieldKeyCount))].map { value in return value } index += Int(fieldKeyCount) let value = serializedData[index..<(index + Int(fieldValueCount))].map { value in return value } index += Int(fieldValueCount) fields.append(Field(key: key, value: value)) } let paddingBytes = (8 - (index % 8)) % 8 // Skip padding bytes index += paddingBytes + 8 let signature = serializedData[index.. Int { /// /// Author: Christian Risi /// /// This is computed as all the bits for the fixed fields /// let INITIAL_CAPACITY_BYTES: Int = 56 let FIELD_HEADER_CAPACITY_BYTES: Int = 8 var fieldReveservedCapacity: Int = 0 for field in msg.fields { fieldReveservedCapacity += FIELD_HEADER_CAPACITY_BYTES + field.key.count + field.value.count } fieldReveservedCapacity += (8 - (fieldReveservedCapacity % 8)) % 8 + 8 return INITIAL_CAPACITY_BYTES + fieldReveservedCapacity }