109 lines
4.2 KiB
Swift
109 lines
4.2 KiB
Swift
//
|
|
// AESCipher.swift
|
|
// native_crypto_ios
|
|
//
|
|
// Created by Hugo Pointcheval on 25/05/2022.
|
|
//
|
|
|
|
import Foundation
|
|
import CryptoKit
|
|
|
|
class AESCipher : Cipher {
|
|
/// Encrypts plaintext with key using AES GCM
|
|
@available(iOS 13.0, *)
|
|
func encrypt(data: Data, key: Data, predefinedIV: Data?) throws -> Data {
|
|
let symmetricKey : SymmetricKey = SymmetricKey.init(data: key)
|
|
|
|
// Encryption
|
|
var encrypted : AES.GCM.SealedBox
|
|
do {
|
|
// If predefinedIV is not null use it
|
|
if (predefinedIV != nil) {
|
|
let nonce = try AES.GCM.Nonce(data: predefinedIV!)
|
|
encrypted = try AES.GCM.seal(data, using: symmetricKey, nonce: nonce)
|
|
} else {
|
|
encrypted = try AES.GCM.seal(data, using: symmetricKey)
|
|
}
|
|
} catch CryptoKitError.incorrectKeySize {
|
|
throw NativeCryptoError.invalidKeySize()
|
|
} catch CryptoKitError.invalidParameter, CryptoKitError.incorrectParameterSize {
|
|
throw NativeCryptoError.invalidParameter()
|
|
} catch {
|
|
throw NativeCryptoError.unknownError(reason: "An error occured during encryption.")
|
|
}
|
|
|
|
// NONCE[12] || CIPHERTEXT[n] || TAG[16]
|
|
let encryptedData : Data? = encrypted.combined
|
|
if (encryptedData == nil) {
|
|
throw NativeCryptoError.unknownError(reason: "An error occured during ciphertext combination.")
|
|
}
|
|
return encryptedData!
|
|
}
|
|
|
|
/// Decrypts ciphertext with key using AES GCM
|
|
@available(iOS 13.0, *)
|
|
func decrypt(data: Data, key: Data) throws -> Data {
|
|
let symmetricKey = SymmetricKey.init(data: key)
|
|
|
|
// SealedBox initialization
|
|
var encrypted : AES.GCM.SealedBox
|
|
do {
|
|
encrypted = try AES.GCM.SealedBox(combined: data)
|
|
} catch {
|
|
throw NativeCryptoError.unknownError(reason: "An error occured during sealedbox initialization.")
|
|
}
|
|
|
|
// Decryption
|
|
var decryptedData : Data
|
|
do {
|
|
decryptedData = try AES.GCM.open(encrypted, using: symmetricKey)
|
|
} catch CryptoKitError.incorrectKeySize {
|
|
throw NativeCryptoError.invalidKeySize()
|
|
} catch CryptoKitError.invalidParameter, CryptoKitError.incorrectParameterSize {
|
|
throw NativeCryptoError.invalidParameter()
|
|
} catch CryptoKitError.authenticationFailure {
|
|
throw NativeCryptoError.authenticationError()
|
|
} catch {
|
|
throw NativeCryptoError.unknownError(reason: "An error occured during decryption.")
|
|
}
|
|
|
|
return decryptedData
|
|
}
|
|
|
|
/// Encrypts plaintext file with key using AES GCM
|
|
func encryptFile(fileParameters: FileParameters, key: Data, predefinedIV: Data?) throws -> Bool {
|
|
let fileManager = FileManager.default
|
|
let inputFile = URL(fileURLWithPath: fileParameters.inputPath)
|
|
|
|
guard let data = fileManager.contents(atPath: inputFile.path) else {
|
|
throw NativeCryptoError.ioError(reason: "Error while reading input file.")
|
|
}
|
|
|
|
let encryptedData = try encrypt(data: data, key: key, predefinedIV: predefinedIV)
|
|
|
|
guard fileManager.createFile(atPath: fileParameters.outputPath, contents: encryptedData, attributes: nil) else {
|
|
throw NativeCryptoError.ioError(reason: "Error while writing output file.")
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
/// Decrypts ciphertext file with key using AES GCM
|
|
func decryptFile(fileParameters: FileParameters, key: Data) throws -> Bool {
|
|
let fileManager = FileManager.default
|
|
let inputFile = URL(fileURLWithPath: fileParameters.inputPath)
|
|
|
|
guard let data = fileManager.contents(atPath: inputFile.path) else {
|
|
throw NativeCryptoError.ioError(reason: "Error while reading input file.")
|
|
}
|
|
|
|
let decryptedData = try decrypt(data: data, key: key)
|
|
|
|
guard fileManager.createFile(atPath: fileParameters.outputPath, contents: decryptedData, attributes: nil) else {
|
|
throw NativeCryptoError.ioError(reason: "Error while writing output file.")
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|