almost done rewritign import sshprivkey

made these static funcitons
made keypair have computed openssh format pub/priv variables that are strings
This commit is contained in:
neon443
2025-07-01 12:46:32 +01:00
parent 1f3afc9c93
commit 19c2e8f912
6 changed files with 75 additions and 48 deletions

View File

@@ -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)
}

View File

@@ -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..<Int((dataBlob as NSData)[3])])
removeField(&dataBlob) //remove pubkey field
dataBlob.removeFirst(4) //remove lenght header for the privkey data blob
guard (dataBlob as NSData).subdata(with: NSRange(0...3)) == (dataBlob as NSData).subdata(with: NSRange(4...7)) else {
fatalError("checkints are different")
}
dataBlob.removeFirst(8) //remove checkints
removeField(&dataBlob) // remove pubkey type header
removeField(&dataBlob) // remove pubkey
let privatekeyData = Data((dataBlob as NSData)[0..<32])
dataBlob.removeFirst(4 + 32) //remove privkey
guard (dataBlob as NSData).subdata(with: NSRange(0...31)) == pubkeyData else {
fatalError("pubkeys dont match")
}
dataBlob.removeFirst(32) //remove pubkey
let comment = String(data: Data((dataBlob as NSData)[0..<Int((dataBlob as NSData)[3])]), encoding: .utf8)!
return Keypair(type: .ecdsa, name: comment, publicKey: pubkeyData, privateKey: privatekeyData)
}
func makeSSHPrivkey(pub: Data, priv: Data, comment: String) -> 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)

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)!
)
)
}

View File

@@ -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")
}
}
}