mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-04-10 17:47:19 +00:00
initial openssh certificate support
This commit is contained in:
parent
403709ac83
commit
10fbc0f5b2
@ -11,6 +11,8 @@ public class Agent {
|
|||||||
private let witness: SigningWitness?
|
private let witness: SigningWitness?
|
||||||
private let writer = OpenSSHKeyWriter()
|
private let writer = OpenSSHKeyWriter()
|
||||||
private let requestTracer = SigningRequestTracer()
|
private let requestTracer = SigningRequestTracer()
|
||||||
|
private let certsPath = (NSHomeDirectory() as NSString).appendingPathComponent("PublicKeys") as String
|
||||||
|
private var certsMap: [Data: Data] = [:]
|
||||||
|
|
||||||
/// Initializes an agent with a store list and a witness.
|
/// Initializes an agent with a store list and a witness.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
@ -83,12 +85,44 @@ extension Agent {
|
|||||||
var count = UInt32(secrets.count).bigEndian
|
var count = UInt32(secrets.count).bigEndian
|
||||||
let countData = Data(bytes: &count, count: UInt32.bitWidth/8)
|
let countData = Data(bytes: &count, count: UInt32.bitWidth/8)
|
||||||
var keyData = Data()
|
var keyData = Data()
|
||||||
let writer = OpenSSHKeyWriter()
|
|
||||||
for secret in secrets {
|
for secret in secrets {
|
||||||
let keyBlob = writer.data(secret: secret)
|
let minimalHex = writer.openSSHMD5Fingerprint(secret: secret).replacingOccurrences(of: ":", with: "")
|
||||||
|
let certificatePath = certsPath.appending("/").appending("\(minimalHex)-cert.pub")
|
||||||
|
Logger().debug("Checking for \(certificatePath)")
|
||||||
|
var keyBlob = writer.data(secret: secret)
|
||||||
|
var curveData = writer.curveType(for: secret.algorithm, length: secret.keySize).data(using: .utf8)!
|
||||||
|
|
||||||
|
|
||||||
|
if FileManager.default.fileExists(atPath: certificatePath) {
|
||||||
|
Logger().debug("Found certificate for \(secret.name)")
|
||||||
|
do {
|
||||||
|
let certContent = try String(contentsOfFile:certificatePath, encoding: .utf8)
|
||||||
|
let certElements = certContent.trimmingCharacters(in: .whitespacesAndNewlines).components(separatedBy: " ")
|
||||||
|
|
||||||
|
if certElements.count >= 2 {
|
||||||
|
if let certDecoded = Data(base64Encoded: certElements[1] as String) {
|
||||||
|
certsMap[certDecoded] = keyBlob // Probably a better way to store the certificate/key association than this...
|
||||||
|
keyBlob = certDecoded
|
||||||
|
|
||||||
|
if certElements.count >= 3 {
|
||||||
|
if let certName = certElements[2].data(using: .utf8) {
|
||||||
|
curveData = certName
|
||||||
|
} else {
|
||||||
|
Logger().info("Certificate for \(secret.name) does not have a name tag, using curveData instead")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger().warning("Certificate found for \(secret.name) but failed to decode base64 key, using public key instead")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Logger().warning("Certificate found for \(secret.name) but failed to load, using public key instead")
|
||||||
|
}
|
||||||
|
}
|
||||||
keyData.append(writer.lengthAndData(of: keyBlob))
|
keyData.append(writer.lengthAndData(of: keyBlob))
|
||||||
let curveData = writer.curveType(for: secret.algorithm, length: secret.keySize).data(using: .utf8)!
|
|
||||||
keyData.append(writer.lengthAndData(of: curveData))
|
keyData.append(writer.lengthAndData(of: curveData))
|
||||||
|
|
||||||
}
|
}
|
||||||
Logger().debug("Agent enumerated \(secrets.count) identities")
|
Logger().debug("Agent enumerated \(secrets.count) identities")
|
||||||
return countData + keyData
|
return countData + keyData
|
||||||
@ -101,7 +135,13 @@ extension Agent {
|
|||||||
/// - Returns: An OpenSSH formatted Data payload containing the signed data response.
|
/// - Returns: An OpenSSH formatted Data payload containing the signed data response.
|
||||||
func sign(data: Data, provenance: SigningRequestProvenance) throws -> Data {
|
func sign(data: Data, provenance: SigningRequestProvenance) throws -> Data {
|
||||||
let reader = OpenSSHReader(data: data)
|
let reader = OpenSSHReader(data: data)
|
||||||
let hash = reader.readNextChunk()
|
var hash = reader.readNextChunk()
|
||||||
|
|
||||||
|
// We would have stored the certificate in the hashmap, so if it matches a certificate, use the associated key instead
|
||||||
|
if let publicKeyHash = certsMap[hash] {
|
||||||
|
hash = publicKeyHash
|
||||||
|
}
|
||||||
|
|
||||||
guard let (store, secret) = secret(matching: hash) else {
|
guard let (store, secret) = secret(matching: hash) else {
|
||||||
Logger().debug("Agent did not have a key matching \(hash as NSData)")
|
Logger().debug("Agent did not have a key matching \(hash as NSData)")
|
||||||
throw AgentError.noMatchingKey
|
throw AgentError.noMatchingKey
|
||||||
|
Loading…
Reference in New Issue
Block a user