diff --git a/Sources/Packages/Package.swift b/Sources/Packages/Package.swift index 5d48a5e..3a8c855 100644 --- a/Sources/Packages/Package.swift +++ b/Sources/Packages/Package.swift @@ -46,7 +46,7 @@ let package = Package( ), .testTarget( name: "SecretKitTests", - dependencies: ["SecretKit", "SecureEnclaveSecretKit", "SmartCardSecretKit"], + dependencies: ["SecretKit", "SecretAgentKit", "SecureEnclaveSecretKit", "SmartCardSecretKit"], swiftSettings: swiftSettings, ), .target( diff --git a/Sources/Packages/Sources/SSHProtocolKit/OpenSSHSignatureWriter.swift b/Sources/Packages/Sources/SSHProtocolKit/OpenSSHSignatureWriter.swift index e5c618d..25397db 100644 --- a/Sources/Packages/Sources/SSHProtocolKit/OpenSSHSignatureWriter.swift +++ b/Sources/Packages/Sources/SSHProtocolKit/OpenSSHSignatureWriter.swift @@ -30,19 +30,28 @@ public struct OpenSSHSignatureWriter: Sendable { extension OpenSSHSignatureWriter { + /// Converts a fixed-width big-endian integer (e.g. r/s from CryptoKit rawRepresentation) into an SSH mpint. + /// Strips unnecessary leading zeros and prefixes `0x00` if needed to keep the value positive. + private func mpint(fromFixedWidthPositiveBytes bytes: Data) -> Data { + // mpint zero is encoded as a string with zero bytes of data. + guard let firstNonZeroIndex = bytes.firstIndex(where: { $0 != 0x00 }) else { + return Data() + } + + let trimmed = Data(bytes[firstNonZeroIndex...]) + + if let first = trimmed.first, first >= 0x80 { + var prefixed = Data([0x00]) + prefixed.append(trimmed) + return prefixed + } + return trimmed + } + func ecdsaSignature(_ rawRepresentation: Data, keyType: KeyType) -> Data { let rawLength = rawRepresentation.count/2 - // Check if we need to pad with 0x00 to prevent certain - // ssh servers from thinking r or s is negative - let paddingRange: ClosedRange = 0x80...0xFF - var r = Data(rawRepresentation[0.. (r: Data, s: Data) { + let reader = OpenSSHReader(data: openSSHSignedData) + + // Prefix + _ = try reader.readNextBytes(as: UInt32.self) + + let algorithm = try reader.readNextChunkAsString() + guard algorithm == "ecdsa-sha2-nistp256" else { + throw ParseError.invalidAlgorithm + } + + let sigReader = try reader.readNextChunkAsSubReader() + let r = try sigReader.readNextChunk() + let s = try sigReader.readNextChunk() + return (r, s) + } + +} +