mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-09-15 08:50:57 +00:00
WIP
This commit is contained in:
parent
a94c9fd1b5
commit
2994861f45
@ -92,16 +92,8 @@ extension Agent {
|
|||||||
/// - provenance: A ``SecretKit.SigningRequestProvenance`` object describing the origin of the request.
|
/// - provenance: A ``SecretKit.SigningRequestProvenance`` object describing the origin of the request.
|
||||||
/// - 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, keyBlob: Data, provenance: SigningRequestProvenance) async throws -> Data {
|
func sign(data: Data, keyBlob: Data, provenance: SigningRequestProvenance) async throws -> Data {
|
||||||
// Check if hash is actually an openssh certificate and reconstruct the public key if it is
|
guard let (secret, store) = await secret(matching: keyBlob) else {
|
||||||
let resolvedBlob: Data
|
logger.debug("Agent did not have a key matching \(keyBlob as NSData)")
|
||||||
if let certificatePublicKey = await certificateHandler.publicKeyHash(from: keyBlob) {
|
|
||||||
resolvedBlob = certificatePublicKey
|
|
||||||
} else {
|
|
||||||
resolvedBlob = keyBlob
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let (secret, store) = await secret(matching: resolvedBlob) else {
|
|
||||||
logger.debug("Agent did not have a key matching \(resolvedBlob as NSData)")
|
|
||||||
throw NoMatchingKeyError()
|
throw NoMatchingKeyError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import OSLog
|
import OSLog
|
||||||
|
import SecretKit
|
||||||
|
|
||||||
/// Manages storage and lookup for OpenSSH certificates.
|
/// Manages storage and lookup for OpenSSH certificates.
|
||||||
public actor OpenSSHCertificateHandler: Sendable {
|
public actor OpenSSHCertificateHandler: Sendable {
|
||||||
@ -25,33 +26,6 @@ public actor OpenSSHCertificateHandler: Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconstructs a public key from a ``Data``, if that ``Data`` contains an OpenSSH certificate hash. Currently only ecdsa certificates are supported
|
|
||||||
/// - Parameter certBlock: The openssh certificate to extract the public key from
|
|
||||||
/// - Returns: A ``Data`` object containing the public key in OpenSSH wire format if the ``Data`` is an OpenSSH certificate hash, otherwise nil.
|
|
||||||
public func publicKeyHash(from hash: Data) -> Data? {
|
|
||||||
let reader = OpenSSHReader(data: hash)
|
|
||||||
do {
|
|
||||||
let certType = String(decoding: try reader.readNextChunk(), as: UTF8.self)
|
|
||||||
switch certType {
|
|
||||||
case "ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
|
||||||
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
|
||||||
"ecdsa-sha2-nistp521-cert-v01@openssh.com":
|
|
||||||
_ = try reader.readNextChunk() // nonce
|
|
||||||
let curveIdentifier = try reader.readNextChunk()
|
|
||||||
let publicKey = try reader.readNextChunk()
|
|
||||||
|
|
||||||
let openSSHIdentifier = certType.replacingOccurrences(of: "-cert-v01@openssh.com", with: "")
|
|
||||||
return openSSHIdentifier.lengthAndData +
|
|
||||||
curveIdentifier.lengthAndData +
|
|
||||||
publicKey.lengthAndData
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to find an OpenSSH Certificate that corresponds to a ``Secret``
|
/// Attempts to find an OpenSSH Certificate that corresponds to a ``Secret``
|
||||||
/// - Parameter secret: The secret to search for a certificate with
|
/// - Parameter secret: The secret to search for a certificate with
|
||||||
/// - Returns: A (``Data``, ``Data``) tuple containing the certificate and certificate name, respectively.
|
/// - Returns: A (``Data``, ``Data``) tuple containing the certificate and certificate name, respectively.
|
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// Reads OpenSSH protocol data.
|
/// Reads OpenSSH protocol data.
|
||||||
public final class OpenSSHReader {
|
final class OpenSSHReader {
|
||||||
|
|
||||||
var remaining: Data
|
var remaining: Data
|
||||||
|
|
@ -59,11 +59,35 @@ extension SSHAgentInputParser {
|
|||||||
|
|
||||||
func signatureRequestContext(from data: Data) throws -> SSHAgent.Request.SignatureRequestContext {
|
func signatureRequestContext(from data: Data) throws -> SSHAgent.Request.SignatureRequestContext {
|
||||||
let reader = OpenSSHReader(data: data)
|
let reader = OpenSSHReader(data: data)
|
||||||
let keyBlob = try reader.readNextChunk()
|
let rawKeyBlob = try reader.readNextChunk()
|
||||||
|
let keyBlob = certificatePublicKeyBlob(from: rawKeyBlob) ?? rawKeyBlob
|
||||||
let dataToSign = try reader.readNextChunk()
|
let dataToSign = try reader.readNextChunk()
|
||||||
return SSHAgent.Request.SignatureRequestContext(keyBlob: keyBlob, dataToSign: dataToSign)
|
return SSHAgent.Request.SignatureRequestContext(keyBlob: keyBlob, dataToSign: dataToSign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func certificatePublicKeyBlob(from hash: Data) -> Data? {
|
||||||
|
let reader = OpenSSHReader(data: hash)
|
||||||
|
do {
|
||||||
|
let certType = String(decoding: try reader.readNextChunk(), as: UTF8.self)
|
||||||
|
switch certType {
|
||||||
|
case "ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
||||||
|
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
||||||
|
"ecdsa-sha2-nistp521-cert-v01@openssh.com":
|
||||||
|
_ = try reader.readNextChunk() // nonce
|
||||||
|
let curveIdentifier = try reader.readNextChunk()
|
||||||
|
let publicKey = try reader.readNextChunk()
|
||||||
|
let openSSHIdentifier = certType.replacingOccurrences(of: "-cert-v01@openssh.com", with: "")
|
||||||
|
return openSSHIdentifier.lengthAndData +
|
||||||
|
curveIdentifier.lengthAndData +
|
||||||
|
publicKey.lengthAndData
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user