diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift index f9ed8f8..7202afb 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift @@ -195,88 +195,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: "auth_context_request_encrypt_description_\(secret.name)") - context.localizedCancelTitle = String(localized: "auth_context_request_deny_button") - 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: "auth_context_request_decrypt_description_\(secret.name)") - context.localizedCancelTitle = String(localized: "auth_context_request_deny_button") - 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 { /// All available tokens, excluding the Secure Enclave. diff --git a/Sources/Secretive/Localizable.xcstrings b/Sources/Secretive/Localizable.xcstrings index 063d2fc..5a4281d 100644 --- a/Sources/Secretive/Localizable.xcstrings +++ b/Sources/Secretive/Localizable.xcstrings @@ -917,84 +917,6 @@ } } }, - "auth_context_request_decrypt_description_%@" : { - "comment" : "When the user performs a decryption action using a secret, they are shown a prompt to approve the action. This is the description, showing which secret will be used. The placeholder is the name of the secret. NOTE: This is currently not exposed in UI.", - "extractionState" : "manual", - "localizations" : { - "ca" : { - "stringUnit" : { - "state" : "translated", - "value" : "desencripta dades usant el secret \"%1$@\" " - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Daten mit dem Secret \"%1$@\" entschlüsseln" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "decrypt data using secret \"%1$@\"" - } - }, - "fi" : { - "stringUnit" : { - "state" : "translated", - "value" : "pura salaus käyttäen salaisuutta \"%1$@\"" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "déchiffrer les données en utilisant le secret \"%1$@\"." - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "decifra i dati usando il Segreto \"%1$@\"" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "シークレット“%1$@”を使って復号化します" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "비밀 \"%1$@\"를 사용해서 데이터 복호화" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "odszyfruj dane używając sekretu “%1$@”" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "decriptar o dado utilizando segredo \"%1$@\"" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "расшифровать данные используя секрет \"%1$@\"" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "使用密钥串 \"%1$@\" 解密数据" - } - } - } - }, "auth_context_request_deny_button" : { "comment" : "When the user chooses to perform an action that requires Touch ID/password authentication, they are shown a prompt to approve the action. This is the deny button for that prompt.", "extractionState" : "manual", @@ -1073,84 +995,6 @@ } } }, - "auth_context_request_encrypt_description_%@" : { - "comment" : "When the user performs an encryption action using a secret, they are shown a prompt to approve the action. This is the description, showing which secret will be used. The placeholder is the name of the secret. NOTE: This is currently not exposed in UI.", - "extractionState" : "manual", - "localizations" : { - "ca" : { - "stringUnit" : { - "state" : "translated", - "value" : "encripta dades usant el secret \"%1$@\"" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Daten mit dem Secret \"%1$@\" verschlüsseln" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "encrypt data using secret \"%1$@\"" - } - }, - "fi" : { - "stringUnit" : { - "state" : "translated", - "value" : "salaa käyttäen salaisuutta \"%1$@\"" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "chiffrer les données en utilisant le secret \"%1$@\"" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "cifra i dati usando il Segreto \"%1$@\"" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "シークレット“%1$@”を使って暗号化します" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "비밀 \"%1$@\"를 사용해서 데이터 암호화" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "zaszyfruj dane używając sekretu “%1$@”" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "encriptar dado utilizando o segredo \"%1$@\"" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "зашифровать данные используя секрет \"%1$@\"" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "使用密钥串 \"%1$@\" 加密数据" - } - } - } - }, "auth_context_request_signature_description_%@_%@" : { "comment" : "When the user performs a signature action using a secret, they are shown a prompt to approve the action. This is the description, showing which secret will be used, and where the request is coming from. The first placeholder is the name of the app requesting the operation. The second placeholder is the name of the secret.", "extractionState" : "manual",