mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-03-24 01:57:23 +01:00
WIP SPM
This commit is contained in:
59
Sources/SecretKit/Common/OpenSSH/OpenSSHKeyWriter.swift
Normal file
59
Sources/SecretKit/Common/OpenSSH/OpenSSHKeyWriter.swift
Normal file
@@ -0,0 +1,59 @@
|
||||
import Foundation
|
||||
import CryptoKit
|
||||
|
||||
// For the moment, only supports ecdsa-sha2-nistp256 and ecdsa-sha2-nistp386 keys
|
||||
public struct OpenSSHKeyWriter {
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func data<SecretType: Secret>(secret: SecretType) -> Data {
|
||||
lengthAndData(of: curveType(for: secret.algorithm, length: secret.keySize).data(using: .utf8)!) +
|
||||
lengthAndData(of: curveIdentifier(for: secret.algorithm, length: secret.keySize).data(using: .utf8)!) +
|
||||
lengthAndData(of: secret.publicKey)
|
||||
}
|
||||
|
||||
public func openSSHString<SecretType: Secret>(secret: SecretType, comment: String? = nil) -> String {
|
||||
[curveType(for: secret.algorithm, length: secret.keySize), data(secret: secret).base64EncodedString(), comment]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: " ")
|
||||
}
|
||||
|
||||
public func openSSHSHA256Fingerprint<SecretType: Secret>(secret: SecretType) -> String {
|
||||
// OpenSSL format seems to strip the padding at the end.
|
||||
let base64 = Data(SHA256.hash(data: data(secret: secret))).base64EncodedString()
|
||||
let paddingRange = base64.index(base64.endIndex, offsetBy: -2)..<base64.endIndex
|
||||
let cleaned = base64.replacingOccurrences(of: "=", with: "", range: paddingRange)
|
||||
return "SHA256:\(cleaned)"
|
||||
}
|
||||
|
||||
public func openSSHMD5Fingerprint<SecretType: Secret>(secret: SecretType) -> String {
|
||||
Insecure.MD5.hash(data: data(secret: secret))
|
||||
.compactMap { ("0" + String($0, radix: 16, uppercase: false)).suffix(2) }
|
||||
.joined(separator: ":")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension OpenSSHKeyWriter {
|
||||
|
||||
public func lengthAndData(of data: Data) -> Data {
|
||||
let rawLength = UInt32(data.count)
|
||||
var endian = rawLength.bigEndian
|
||||
return Data(bytes: &endian, count: UInt32.bitWidth/8) + data
|
||||
}
|
||||
|
||||
public func curveIdentifier(for algorithm: Algorithm, length: Int) -> String {
|
||||
switch algorithm {
|
||||
case .ellipticCurve:
|
||||
return "nistp" + String(describing: length)
|
||||
}
|
||||
}
|
||||
|
||||
public func curveType(for algorithm: Algorithm, length: Int) -> String {
|
||||
switch algorithm {
|
||||
case .ellipticCurve:
|
||||
return "ecdsa-sha2-nistp" + String(describing: length)
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Sources/SecretKit/Common/OpenSSH/OpenSSHReader.swift
Normal file
25
Sources/SecretKit/Common/OpenSSH/OpenSSHReader.swift
Normal file
@@ -0,0 +1,25 @@
|
||||
import Foundation
|
||||
|
||||
public class OpenSSHReader {
|
||||
|
||||
var remaining: Data
|
||||
|
||||
public init(data: Data) {
|
||||
remaining = Data(data)
|
||||
}
|
||||
|
||||
public func readNextChunk() -> Data {
|
||||
let lengthRange = 0..<(UInt32.bitWidth/8)
|
||||
let lengthChunk = remaining[lengthRange]
|
||||
remaining.removeSubrange(lengthRange)
|
||||
let littleEndianLength = lengthChunk.withUnsafeBytes { pointer in
|
||||
return pointer.load(as: UInt32.self)
|
||||
}
|
||||
let length = Int(littleEndianLength.bigEndian)
|
||||
let dataRange = 0..<length
|
||||
let ret = Data(remaining[dataRange])
|
||||
remaining.removeSubrange(dataRange)
|
||||
return ret
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user