mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-08-27 15:40:57 +00:00
Expose tokenID.
This commit is contained in:
parent
822f61f1f8
commit
16b9b3816a
@ -23,6 +23,9 @@ extension SmartCard {
|
|||||||
public var isAvailable: Bool {
|
public var isAvailable: Bool {
|
||||||
state.isAvailable
|
state.isAvailable
|
||||||
}
|
}
|
||||||
|
@MainActor public var smartcardTokenID: String? {
|
||||||
|
state.tokenID
|
||||||
|
}
|
||||||
|
|
||||||
public let id = UUID()
|
public let id = UUID()
|
||||||
@MainActor public var name: String {
|
@MainActor public var name: String {
|
||||||
@ -35,7 +38,7 @@ extension SmartCard {
|
|||||||
/// Initializes a Store.
|
/// Initializes a Store.
|
||||||
public init() {
|
public init() {
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
if let tokenID = state.tokenID {
|
if let tokenID = smartcardTokenID{
|
||||||
state.isAvailable = true
|
state.isAvailable = true
|
||||||
state.watcher.addRemovalHandler(self.smartcardRemoved, forTokenID: tokenID)
|
state.watcher.addRemovalHandler(self.smartcardRemoved, forTokenID: tokenID)
|
||||||
}
|
}
|
||||||
@ -172,88 +175,6 @@ extension SmartCard.Store {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: Smart Card specific encryption/decryption/verification
|
|
||||||
extension SmartCard.Store {
|
|
||||||
|
|
||||||
/// Encrypts a payload with a specified key.
|
|
||||||
/// - Parameters:
|
|
||||||
/// - data: The payload to encrypt.
|
|
||||||
/// - secret: The secret to encrypt with.
|
|
||||||
/// - Returns: The encrypted data.
|
|
||||||
/// - Warning: Encryption functions are deliberately only exposed on a library level, and are not exposed in Secretive itself to prevent users from data loss. Any pull requests which expose this functionality in the app will not be merged.
|
|
||||||
public func encrypt(data: Data, with secret: SecretType) throws -> Data {
|
|
||||||
let context = LAContext()
|
|
||||||
context.localizedReason = String(localized: .authContextRequestEncryptDescription(secretName: secret.name))
|
|
||||||
context.localizedCancelTitle = String(localized: .authContextRequestDenyButton)
|
|
||||||
let attributes = KeychainDictionary([
|
|
||||||
kSecAttrKeyType: secret.algorithm.secAttrKeyType,
|
|
||||||
kSecAttrKeySizeInBits: secret.keySize,
|
|
||||||
kSecAttrKeyClass: kSecAttrKeyClassPublic,
|
|
||||||
kSecUseAuthenticationContext: context
|
|
||||||
])
|
|
||||||
var encryptError: SecurityError?
|
|
||||||
let untyped: CFTypeRef? = SecKeyCreateWithData(secret.publicKey as CFData, attributes, &encryptError)
|
|
||||||
guard let untypedSafe = untyped else {
|
|
||||||
throw KeychainError(statusCode: errSecSuccess)
|
|
||||||
}
|
|
||||||
let key = untypedSafe as! SecKey
|
|
||||||
guard let signature = SecKeyCreateEncryptedData(key, encryptionAlgorithm(for: secret), data as CFData, &encryptError) else {
|
|
||||||
throw SigningError(error: encryptError)
|
|
||||||
}
|
|
||||||
return signature as Data
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypts a payload with a specified key.
|
|
||||||
/// - Parameters:
|
|
||||||
/// - data: The payload to decrypt.
|
|
||||||
/// - secret: The secret to decrypt with.
|
|
||||||
/// - Returns: The decrypted data.
|
|
||||||
/// - Warning: Encryption functions are deliberately only exposed on a library level, and are not exposed in Secretive itself to prevent users from data loss. Any pull requests which expose this functionality in the app will not be merged.
|
|
||||||
public func decrypt(data: Data, with secret: SecretType) async throws -> Data {
|
|
||||||
guard let tokenID = await state.tokenID else { fatalError() }
|
|
||||||
let context = LAContext()
|
|
||||||
context.localizedReason = String(localized: .authContextRequestDecryptDescription(secretName: secret.name))
|
|
||||||
context.localizedCancelTitle = String(localized: .authContextRequestDenyButton)
|
|
||||||
let attributes = KeychainDictionary([
|
|
||||||
kSecClass: kSecClassKey,
|
|
||||||
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
|
|
||||||
kSecAttrApplicationLabel: secret.id as CFData,
|
|
||||||
kSecAttrTokenID: tokenID,
|
|
||||||
kSecUseAuthenticationContext: context,
|
|
||||||
kSecReturnRef: true
|
|
||||||
])
|
|
||||||
var untyped: CFTypeRef?
|
|
||||||
let status = SecItemCopyMatching(attributes, &untyped)
|
|
||||||
if status != errSecSuccess {
|
|
||||||
throw KeychainError(statusCode: status)
|
|
||||||
}
|
|
||||||
guard let untypedSafe = untyped else {
|
|
||||||
throw KeychainError(statusCode: errSecSuccess)
|
|
||||||
}
|
|
||||||
let key = untypedSafe as! SecKey
|
|
||||||
var encryptError: SecurityError?
|
|
||||||
guard let signature = SecKeyCreateDecryptedData(key, encryptionAlgorithm(for: secret), data as CFData, &encryptError) else {
|
|
||||||
throw SigningError(error: encryptError)
|
|
||||||
}
|
|
||||||
return signature as Data
|
|
||||||
}
|
|
||||||
|
|
||||||
private func encryptionAlgorithm(for secret: SecretType) -> SecKeyAlgorithm {
|
|
||||||
switch (secret.algorithm, secret.keySize) {
|
|
||||||
case (.ellipticCurve, 256):
|
|
||||||
return .eciesEncryptionCofactorVariableIVX963SHA256AESGCM
|
|
||||||
case (.ellipticCurve, 384):
|
|
||||||
return .eciesEncryptionCofactorVariableIVX963SHA384AESGCM
|
|
||||||
case (.rsa, 1024), (.rsa, 2048):
|
|
||||||
return .rsaEncryptionOAEPSHA512AESGCM
|
|
||||||
default:
|
|
||||||
fatalError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TKTokenWatcher {
|
extension TKTokenWatcher {
|
||||||
|
|
||||||
/// All available tokens, excluding the Secure Enclave.
|
/// All available tokens, excluding the Secure Enclave.
|
||||||
|
Loading…
Reference in New Issue
Block a user