Created
December 7, 2021 04:59
-
-
Save dimitribouniol/41659e9a32daa42e3c4d3d0210546fde to your computer and use it in GitHub Desktop.
CommonSwiftyCrypto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import CommonCrypto | |
import Bytes // https://github.com/mochidev/Bytes | |
class Cryptor { | |
enum CryptorError: Error { | |
case cryptorCreationError(CCCryptorStatus) | |
case cryptorUpdateError(CCCryptorStatus) | |
case cryptorFinalizeError(CCCryptorStatus) | |
case cryptorResetError(CCCryptorStatus) | |
} | |
enum Operation: UInt32 { | |
case encrypt = 0 | |
case decrypt | |
} | |
enum Algorithm: UInt32 { | |
case AES = 0 | |
case DES | |
case TDES | |
case CAST | |
case RC4 | |
case RC2 | |
case Blowfish | |
} | |
struct Options: OptionSet { | |
let rawValue: UInt32 | |
static let PKCS7Padding = Options(rawValue: CCOptions(kCCOptionPKCS7Padding)) | |
static let ECBMode = Options(rawValue: CCOptions(kCCOptionECBMode)) | |
} | |
var cryptor: CCCryptorRef? | |
init( | |
operation: Operation, | |
algorithm: Algorithm, | |
options: Options, | |
key: Bytes, | |
initializationVector: Bytes? | |
) throws { | |
let status = CCCryptorCreate( | |
operation.rawValue, // op | |
algorithm.rawValue, // alg | |
options.rawValue, // options | |
key, // key | |
key.count, // keyLength | |
initializationVector, // iv | |
&cryptor // cryptorRef | |
) | |
guard status == kCCSuccess else { | |
if let cryptor = cryptor { CCCryptorRelease(cryptor) } | |
throw CryptorError.cryptorCreationError(status) | |
} | |
} | |
func update(data: Bytes) throws -> Bytes { | |
var output = Bytes(repeating: 0, count: CCCryptorGetOutputLength(cryptor, data.count, false)) | |
var finalOutputSize: Int = 0 | |
let status = CCCryptorUpdate( | |
cryptor, | |
data, data.count, | |
&output, output.count, | |
&finalOutputSize) | |
guard status == kCCSuccess else { | |
throw CryptorError.cryptorUpdateError(status) | |
} | |
output.removeLast(output.count - finalOutputSize) | |
return output | |
} | |
func finalize() throws -> Bytes { | |
var output = Bytes(repeating: 0, count: CCCryptorGetOutputLength(cryptor, 0, true)) | |
var finalOutputSize: Int = 0 | |
let status = CCCryptorFinal( | |
cryptor, | |
&output, output.count, | |
&finalOutputSize) | |
guard status == kCCSuccess else { | |
throw CryptorError.cryptorFinalizeError(status) | |
} | |
output.removeLast(output.count - finalOutputSize) | |
return output | |
} | |
func reset(initializationVector: Bytes?) throws { | |
let status = CCCryptorReset(cryptor, initializationVector) | |
guard status == kCCSuccess else { | |
throw CryptorError.cryptorResetError(status) | |
} | |
} | |
deinit { | |
if let cryptor = cryptor { | |
CCCryptorRelease(cryptor) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment