diff --git a/ShhShell/Host/HostsManager.swift b/ShhShell/Host/HostsManager.swift index d1e4398..afe6526 100644 --- a/ShhShell/Host/HostsManager.swift +++ b/ShhShell/Host/HostsManager.swift @@ -187,9 +187,7 @@ class HostsManager: ObservableObject, @unchecked Sendable { for host in hosts { guard let publicKey = host.publicKey else { continue } guard let privateKey = host.privateKey else { continue } - guard let privKeyStr = String(data: privateKey, encoding: .utf8), - let pubKeyStr = String(data: publicKey, encoding: .utf8) else { continue } - let keypair = Keypair(type: .rsa(1), name: UUID().uuidString, publicKey: pubKeyStr, privateKey: privKeyStr) + let keypair = Keypair(type: .rsa, name: UUID().uuidString, publicKey: publicKey, privateKey: privateKey) if !result.contains(keypair) { result.append(keypair) } diff --git a/ShhShell/Keys/KeyManager.swift b/ShhShell/Keys/KeyManager.swift index 90fd2ab..2fd2dd7 100644 --- a/ShhShell/Keys/KeyManager.swift +++ b/ShhShell/Keys/KeyManager.swift @@ -27,17 +27,17 @@ class KeyManager: ObservableObject { let privatekeyData = key.rawRepresentation let publickeyData = key.publicKey.rawRepresentation print(publickeyData.base64EncodedString()) - let pubpem = makeSSHPubkey(pub: publickeyData, comment: "neon443@m") - let privpem = makeSSHPrivkey(pub: publickeyData, priv: privatekeyData, comment: "neon443@m") + let pubpem = KeyManager.makeSSHPubkey(pub: publickeyData, comment: "neon443@m") + let privpem = KeyManager.makeSSHPrivkey(pub: publickeyData, priv: privatekeyData, comment: "neon443@m") print(String(data: pubpem, encoding: .utf8)!) print() print(String(data: privpem, encoding: .utf8)!) print() - print(importSSHPubkey(pub: String(data: pubpem, encoding: .utf8)!).base64EncodedString()) + print(KeyManager.importSSHPubkey(pub: String(data: pubpem, encoding: .utf8)!).base64EncodedString()) print(privatekeyData.base64EncodedString()) - print(importSSHPrivkey(priv: String(data: privpem, encoding: .utf8)!).base64EncodedString()) + print(KeyManager.importSSHPrivkey(priv: String(data: privpem, encoding: .utf8)!).privateKey.base64EncodedString()) fatalError() } @@ -59,14 +59,14 @@ class KeyManager: ObservableObject { //MARK: generate keys func generateKey(type: KeyType, SEPKeyTag: String, comment: String, passphrase: String) -> Keypair? { switch type { - case .ecdsa(let inSEP): + case .ecdsa: fatalError("unimplemented") - case .rsa(let rsaSize): + case .rsa: fatalError("unimplemented") } } - func importSSHPubkey(pub: String) -> Data { + static func importSSHPubkey(pub: String) -> Data { let split = pub.split(separator: " ") guard split.count == 3 else { return Data() } @@ -78,7 +78,7 @@ class KeyManager: ObservableObject { return pubdata } - func makeSSHPubkey(pub: Data, comment: String) -> Data { + static func makeSSHPubkey(pub: Data, comment: String) -> Data { let header = "ssh-ed25519" var keyBlob: Data = Data() //key type bit @@ -91,7 +91,7 @@ class KeyManager: ObservableObject { return Data(pubkeyline.utf8) } - func importSSHPrivkey(priv: String) -> Data { + static func importSSHPrivkey(priv: String) -> Keypair { var split = priv.replacingOccurrences(of: "-----BEGIN OPENSSH PRIVATE KEY-----\n", with: "") split = split.replacingOccurrences(of: "-----BEGIN OPENSSH PRIVATE KEY-----", with: "") split = split.replacingOccurrences(of: "\n-----END OPENSSH PRIVATE KEY-----\n", with: "") @@ -102,17 +102,38 @@ class KeyManager: ObservableObject { var dataBlob = Data(base64Encoded: split.data(using: .utf8)!)! dataBlob.removeFirst(15) //remove magik header + dataBlob.removeFirst(16) //remove none noen + dataBlob.removeFirst(4) //remove lenght header for empty data + dataBlob.removeFirst(8) //remove empty data - for _ in 0..<2 { - removeField(&dataBlob) - } //remove the 2 nones fro encryption and kdf - removeField(&dataBlob) //remove the empty Data() + removeField(&dataBlob) //remove key type for pubkey str - - return Data() + let pubkeyData = Data((dataBlob as NSData)[0.. Data { + static func makeSSHPrivkey(pub: Data, priv: Data, comment: String) -> Data { var content: Data = Data() var blob: Data = Data() @@ -167,27 +188,26 @@ class KeyManager: ObservableObject { return SecKeyCopyPublicKey(privateKey) } - func encode(str: String) -> Data { + static func encode(str: String) -> Data { guard let utf8 = str.data(using: .utf8) else { return Data() } return encode(int: utf8.count) + utf8 } - func encode(data: Data) -> Data { + static func encode(data: Data) -> Data { return encode(int: data.count) + data } - func encode(int: Int) -> Data { + static func encode(int: Int) -> Data { var bigEndian = UInt32(int).bigEndian return Data(bytes: &bigEndian, count: 4) // 32bits / 8 bitsperbyte } - func removeField(_ data: inout Data) { + static func removeField(_ data: inout Data) { guard data.count >= 4 else { return } - let lengthBytes = data.subdata(in: 0..<4) - let length = lengthBytes.withUnsafeBytes { $0.load(as: UInt32.self).bigEndian } + let length = (data as NSData)[3] guard data.count >= 4 + Int(length) else { return } data.removeFirst(4) diff --git a/ShhShell/Keys/KeyType.swift b/ShhShell/Keys/KeyType.swift index ef0b27c..d007f5a 100644 --- a/ShhShell/Keys/KeyType.swift +++ b/ShhShell/Keys/KeyType.swift @@ -10,13 +10,13 @@ import Foundation enum KeyType: Codable, Equatable, Hashable, CustomStringConvertible { var description: String { switch self { - case .ecdsa(let inSEP): - return inSEP ? "ECDSA Secure Enclave" : "ECDSA" - case .rsa(let bits): - return "RSA \(bits)" + case .ecdsa: + return "ECDSA" + case .rsa: + return "RSA" } } - case ecdsa(inSEP: Bool) - case rsa(Int) + case ecdsa + case rsa } diff --git a/ShhShell/Keys/Keypair.swift b/ShhShell/Keys/Keypair.swift index d109a17..ec7a762 100644 --- a/ShhShell/Keys/Keypair.swift +++ b/ShhShell/Keys/Keypair.swift @@ -11,38 +11,49 @@ protocol KeypairProtocol: Identifiable, Equatable, Codable, Hashable { var id: UUID { get } var type: KeyType { get set } var name: String { get set } - var publicKey: Data? { get set } - var privateKey: Data? { get set } + var publicKey: Data { get set } + var privateKey: Data { get set } var passphrase: String { get set } + + var openSshPubkey: String { get } + var openSshPrivkey: String { get } } struct Keypair: KeypairProtocol { var id = UUID() - var type: KeyType = .rsa(4096) + var type: KeyType = .ecdsa var name: String = "" - var publicKey: Data? - var privateKey: Data? + var publicKey: Data + var privateKey: Data var passphrase: String = "" + var openSshPubkey: String { + String(data: KeyManager.makeSSHPubkey(pub: publicKey, comment: name), encoding: .utf8) ?? "OpenSSH key format error" + } + + var openSshPrivkey: String { + String(data: KeyManager.makeSSHPrivkey(pub: publicKey, priv: privateKey, comment: name), encoding: .utf8) ?? "OpenSSH key format error" + } + init( id: UUID = UUID(), type: KeyType, name: String, - publicKey: String, - privateKey: String, + publicKey: Data, + privateKey: Data, passphrase: String = "" ) { self.id = id self.type = type self.name = name - self.publicKey = publicKey.data(using: .utf8) - self.privateKey = privateKey.data(using: .utf8) + self.publicKey = publicKey + self.privateKey = privateKey self.passphrase = passphrase } static func ==(lhs: Keypair, rhs: Keypair) -> Bool { - if lhs.publicKey?.base64EncodedString() == rhs.publicKey?.base64EncodedString() - && lhs.privateKey?.base64EncodedString() == rhs.privateKey?.base64EncodedString() { + if lhs.publicKey.base64EncodedString() == rhs.publicKey.base64EncodedString() + && lhs.privateKey.base64EncodedString() == rhs.privateKey.base64EncodedString() { return true } else { return false diff --git a/ShhShell/Views/Keys/KeyDetailView.swift b/ShhShell/Views/Keys/KeyDetailView.swift index ba46b9c..481c620 100644 --- a/ShhShell/Views/Keys/KeyDetailView.swift +++ b/ShhShell/Views/Keys/KeyDetailView.swift @@ -85,9 +85,9 @@ struct KeyDetailView: View { KeyDetailView( hostsManager: HostsManager(), keypair: Keypair( - type: .rsa(4096), + type: .rsa, name: "previewKey", - publicKey: "ssh-ed25519 dskjhfajkdhfjkdashfgjkhadsjkgfbhalkjhfjkhdask user@mac", + publicKey: "ssh-ed25519 dskjhfajkdhfjkdashfgjkhadsjkgfbhalkjhfjkhdask user@mac".data(using: .utf8)!, privateKey: """ -----BEGIN OPENSSH PRIVATE KEY----- Lorem ipsum dolor sit amet, consectetur adipiscing elit @@ -95,7 +95,7 @@ struct KeyDetailView: View { Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat -----END OPENSSH PRIVATE KEY----- - """ + """.data(using: .utf8)! ) ) } diff --git a/ShhShell/Views/Keys/KeyManagerView.swift b/ShhShell/Views/Keys/KeyManagerView.swift index d305fb0..4728fa8 100644 --- a/ShhShell/Views/Keys/KeyManagerView.swift +++ b/ShhShell/Views/Keys/KeyManagerView.swift @@ -22,9 +22,7 @@ struct KeyManagerView: View { NavigationLink { KeyDetailView(hostsManager: hostsManager, keypair: keypair) } label: { - if let publicKey = keypair.publicKey { - Text(String(data: publicKey, encoding: .utf8) ?? "nil") - } + Text(String(data: keypair.publicKey, encoding: .utf8) ?? "nil") } } }