Skip to content

Instantly share code, notes, and snippets.

@dimitribouniol
Created December 7, 2021 04:59
Show Gist options
  • Save dimitribouniol/41659e9a32daa42e3c4d3d0210546fde to your computer and use it in GitHub Desktop.
Save dimitribouniol/41659e9a32daa42e3c4d3d0210546fde to your computer and use it in GitHub Desktop.
CommonSwiftyCrypto
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