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