Sesame-Server/Sources/App/KeyManagement.swift
Christoph Hagen 20fa7286ea First version
2022-01-24 17:17:06 +01:00

125 lines
3.4 KiB
Swift

import Foundation
import WebSocketKit
import Vapor
final class KeyManagement {
/// The security parameter for the keys (in bits)
private static let keySecurity = 128
/// The size of the individual keys in bytes
static let keySize = keySecurity / 8
/// The connection to the device
private var connection: WebSocket?
private let deviceKey: String
var deviceIsAuthenticated = false
/// Indicator for device availability
var deviceIsConnected: Bool {
!(connection?.isClosed ?? true) && deviceIsAuthenticated
}
/// The id of the key which was sent to the device
private var keyInTransit: UInt16?
/// The result transmitted by the device for the sent key
var keyResult: KeyResult = .none
init(deviceKey: String) {
self.deviceKey = deviceKey
}
// MARK: API
var deviceResponse: String {
guard let keyId = keyInTransit else {
return "No key"
}
return "\(keyId):\(keyResult.rawValue)"
}
var deviceStatus: String {
deviceIsConnected ? "1" : "0"
}
func clearClientRequest() {
keyInTransit = nil
keyResult = .none
}
func sendKeyToDevice(_ key: Data, keyId: UInt16) -> KeyPostResponse {
guard key.count == KeyManagement.keySize else {
return .invalidKeySize
}
guard let socket = connection, !socket.isClosed else {
connection = nil
return .deviceNotConnected
}
let keyIdData = [UInt8(keyId >> 8), UInt8(keyId & 0xFF)]
keyInTransit = keyId
socket.send(keyIdData + key, promise: nil)
return .success
}
func authenticateDevice(psk: String) {
guard psk == self.deviceKey else {
print("Invalid device key")
_ = connection?.close()
deviceIsAuthenticated = false
return
}
print("Device authenticated")
deviceIsAuthenticated = true
}
func processDeviceResponse(_ data: ByteBuffer) {
guard data.readableBytes == 1 else {
print("Unexpected number of bytes received from device")
keyInTransit = nil
keyResult = .unexpectedSocketEvent
return
}
guard let rawValue = data.getBytes(at: 0, length: 1)?.first else {
print("Unreadable data received from device")
keyInTransit = nil
keyResult = .unexpectedSocketEvent
return
}
guard let response = KeyResult(rawValue: rawValue) else {
print("Unknown response \(rawValue) received from device")
keyInTransit = nil
keyResult = .unexpectedSocketEvent
return
}
guard keyInTransit != nil else {
print("No key in transit for response \(response)")
return
}
keyResult = response
}
func didCloseDeviceSocket() {
deviceIsAuthenticated = false
guard connection != nil else {
return
}
connection = nil
print("Socket closed")
}
func removeDeviceConnection() {
_ = connection?.close()
connection = nil
}
func createNewDeviceConnection(_ socket: WebSocket) {
removeDeviceConnection()
connection = socket
deviceIsAuthenticated = false
print("Socket connected")
}
}