Files
Vespass/Backend/Storage/GenericPasswordConvertible.swift
Nalin Bhardwaj 83781c6fa1 secrets refactor
working demo
2023-01-18 03:06:16 -08:00

64 lines
2.1 KiB
Swift

//
// GenericPasswordConvertible.swift
// Vespass
//
// Created by Nalin Bhardwaj on 22/12/22.
// Copyright © 2022 Vespass. All rights reserved.
//
// The interface required for conversion to a generic password keychain item.
import Foundation
import CryptoKit
/// The interface needed for SecKey conversion.
protocol GenericPasswordConvertible: CustomStringConvertible {
/// Creates a key from a raw representation.
init<D>(rawRepresentation data: D) throws where D: ContiguousBytes
/// A raw representation of the key.
var rawRepresentation: Data { get }
}
extension GenericPasswordConvertible {
/// A string version of the key for visual inspection.
/// IMPORTANT: Never log the actual key data.
public var description: String {
return self.rawRepresentation.withUnsafeBytes { bytes in
return "Key representation contains \(bytes.count) bytes."
}
}
}
// Ensure that Secure Enclave keys are generic password convertible.
extension SecureEnclave.P256.KeyAgreement.PrivateKey: GenericPasswordConvertible {
init<D>(rawRepresentation data: D) throws where D: ContiguousBytes {
try self.init(dataRepresentation: data.dataRepresentation)
}
var rawRepresentation: Data {
return dataRepresentation // Contiguous bytes repackaged as a Data instance.
}
}
extension SecureEnclave.P256.Signing.PrivateKey: GenericPasswordConvertible {
init<D>(rawRepresentation data: D) throws where D: ContiguousBytes {
try self.init(dataRepresentation: data.dataRepresentation)
}
var rawRepresentation: Data {
return dataRepresentation // Contiguous bytes repackaged as a Data instance.
}
}
extension ContiguousBytes {
/// A Data instance created safely from the contiguous bytes without making any copies.
var dataRepresentation: Data {
return self.withUnsafeBytes { bytes in
let cfdata = CFDataCreateWithBytesNoCopy(nil, bytes.baseAddress?.assumingMemoryBound(to: UInt8.self), bytes.count, kCFAllocatorNull)
return ((cfdata as NSData?) as Data?) ?? Data()
}
}
}