Forráskód Böngészése

Replace BlockMode enum with structs for each block mode.

Block need to be more customizable, hence this change. Enums are limited.
Block mode instance may now return additional data eg. MAC
Marcin Krzyżanowski 7 éve
szülő
commit
609827b076

+ 6 - 8
CryptoSwift.xcodeproj/project.pbxproj

@@ -35,11 +35,13 @@
 		75211FC420724A10004E41F8 /* CryptoSwift-Test.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 75211FB420724A10004E41F8 /* CryptoSwift-Test.xcconfig */; };
 		7523742D2083C61D0016D662 /* GCM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7523742C2083C61C0016D662 /* GCM.swift */; };
 		7529366A20683DFC00195874 /* AEADChaCha20Poly1305.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7529366920683DFC00195874 /* AEADChaCha20Poly1305.swift */; };
+		752BED9D208C120D00FC4743 /* Blowfish+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52541EE8B6CA0048EB3B /* Blowfish+Foundation.swift */; };
+		752BED9E208C121000FC4743 /* Blowfish.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52491EE8B6CA0048EB3B /* Blowfish.swift */; };
+		752BED9F208C135700FC4743 /* AES+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52531EE8B6CA0048EB3B /* AES+Foundation.swift */; };
 		753B33011DAB84D600D06422 /* RandomBytesSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753B33001DAB84D600D06422 /* RandomBytesSequenceTests.swift */; };
 		754310442050111A003FB1DF /* CompactMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754310432050111A003FB1DF /* CompactMap.swift */; };
 		75482EA41CB310B7001F66A5 /* PBKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA31CB310B7001F66A5 /* PBKDF.swift */; };
 		754BE46819693E190098E6F3 /* DigestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754BE46719693E190098E6F3 /* DigestTests.swift */; };
-		75563016208BCC6A000E0BE3 /* UInt128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75563015208BCC6A000E0BE3 /* UInt128.swift */; };
 		755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755FB1D9199E347D00475437 /* ExtensionsTest.swift */; };
 		7564F0522072EAEB00CA5A96 /* PBKDFPerf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7576F6F6207290F8006688F8 /* PBKDFPerf.swift */; };
 		7564F0532072EAEB00CA5A96 /* ChaCha20TestsPerf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7576F6F020728EAB006688F8 /* ChaCha20TestsPerf.swift */; };
@@ -85,7 +87,6 @@
 		75EC52891EE8B8170048EB3B /* OFB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52461EE8B6CA0048EB3B /* OFB.swift */; };
 		75EC528A1EE8B8170048EB3B /* PCBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52471EE8B6CA0048EB3B /* PCBC.swift */; };
 		75EC528B1EE8B8170048EB3B /* RandomAccessBlockModeWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52481EE8B6CA0048EB3B /* RandomAccessBlockModeWorker.swift */; };
-		75EC528C1EE8B81A0048EB3B /* Blowfish.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52491EE8B6CA0048EB3B /* Blowfish.swift */; };
 		75EC528D1EE8B81A0048EB3B /* ChaCha20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC524A1EE8B6CA0048EB3B /* ChaCha20.swift */; };
 		75EC528E1EE8B81A0048EB3B /* Checksum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC524B1EE8B6CA0048EB3B /* Checksum.swift */; };
 		75EC528F1EE8B81A0048EB3B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC524C1EE8B6CA0048EB3B /* Cipher.swift */; };
@@ -93,8 +94,6 @@
 		75EC52911EE8B81A0048EB3B /* Cryptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC524E1EE8B6CA0048EB3B /* Cryptors.swift */; };
 		75EC52931EE8B81A0048EB3B /* Digest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52501EE8B6CA0048EB3B /* Digest.swift */; };
 		75EC52941EE8B81A0048EB3B /* DigestType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52511EE8B6CA0048EB3B /* DigestType.swift */; };
-		75EC52951EE8B8200048EB3B /* AES+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52531EE8B6CA0048EB3B /* AES+Foundation.swift */; };
-		75EC52961EE8B8200048EB3B /* Blowfish+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52541EE8B6CA0048EB3B /* Blowfish+Foundation.swift */; };
 		75EC52971EE8B8200048EB3B /* ChaCha20+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52551EE8B6CA0048EB3B /* ChaCha20+Foundation.swift */; };
 		75EC52981EE8B8200048EB3B /* Array+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52561EE8B6CA0048EB3B /* Array+Foundation.swift */; };
 		75EC52991EE8B8200048EB3B /* Data+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EC52571EE8B6CA0048EB3B /* Data+Extension.swift */; };
@@ -885,6 +884,7 @@
 				75EC52901EE8B81A0048EB3B /* Collection+Extension.swift in Sources */,
 				0EE73E71204D598100110E11 /* CMAC.swift in Sources */,
 				7523742D2083C61D0016D662 /* GCM.swift in Sources */,
+				752BED9F208C135700FC4743 /* AES+Foundation.swift in Sources */,
 				E6200E141FB9A7AE00258382 /* HKDF.swift in Sources */,
 				75EC529F1EE8B8230048EB3B /* HMAC.swift in Sources */,
 				75EC52B91EE8B83D0048EB3B /* ZeroPadding.swift in Sources */,
@@ -895,9 +895,9 @@
 				75EC52821EE8B8170048EB3B /* BlockMode.swift in Sources */,
 				75EC52AE1EE8B83D0048EB3B /* SecureBytes.swift in Sources */,
 				75EC528F1EE8B81A0048EB3B /* Cipher.swift in Sources */,
-				75EC528C1EE8B81A0048EB3B /* Blowfish.swift in Sources */,
 				75EC52A01EE8B8290048EB3B /* Int+Extension.swift in Sources */,
 				75EC52B01EE8B83D0048EB3B /* SHA2.swift in Sources */,
+				752BED9D208C120D00FC4743 /* Blowfish+Foundation.swift in Sources */,
 				75EC52B71EE8B83D0048EB3B /* Updatable.swift in Sources */,
 				75EC528E1EE8B81A0048EB3B /* Checksum.swift in Sources */,
 				754310442050111A003FB1DF /* CompactMap.swift in Sources */,
@@ -908,7 +908,6 @@
 				75EC52B41EE8B83D0048EB3B /* UInt32+Extension.swift in Sources */,
 				75EC52911EE8B81A0048EB3B /* Cryptors.swift in Sources */,
 				75EC52881EE8B8170048EB3B /* ECB.swift in Sources */,
-				75563016208BCC6A000E0BE3 /* UInt128.swift in Sources */,
 				75EC52841EE8B8170048EB3B /* BlockModeWorker.swift in Sources */,
 				75EC52A41EE8B8290048EB3B /* Operators.swift in Sources */,
 				75EC529A1EE8B8200048EB3B /* HMAC+Foundation.swift in Sources */,
@@ -921,6 +920,7 @@
 				75EC52871EE8B8170048EB3B /* CTR.swift in Sources */,
 				75EC52A21EE8B8290048EB3B /* MD5.swift in Sources */,
 				75EC527C1EE8B8130048EB3B /* AES.swift in Sources */,
+				752BED9E208C121000FC4743 /* Blowfish.swift in Sources */,
 				75EC52A91EE8B83D0048EB3B /* PKCS7Padding.swift in Sources */,
 				75EC52A51EE8B8290048EB3B /* Padding.swift in Sources */,
 				75EC527F1EE8B8130048EB3B /* BatchedCollection.swift in Sources */,
@@ -928,7 +928,6 @@
 				75EC52B61EE8B83D0048EB3B /* UInt8+Extension.swift in Sources */,
 				75EC52891EE8B8170048EB3B /* OFB.swift in Sources */,
 				75EC52831EE8B8170048EB3B /* BlockModeOptions.swift in Sources */,
-				75EC52961EE8B8200048EB3B /* Blowfish+Foundation.swift in Sources */,
 				751EE9781F93996100161FFC /* AES.Cryptors.swift in Sources */,
 				75EC528B1EE8B8170048EB3B /* RandomAccessBlockModeWorker.swift in Sources */,
 				75EC527D1EE8B8130048EB3B /* Array+Extension.swift in Sources */,
@@ -942,7 +941,6 @@
 				75EC52A71EE8B8390048EB3B /* PBKDF2.swift in Sources */,
 				75EC529D1EE8B8200048EB3B /* Utils+Foundation.swift in Sources */,
 				75EC527E1EE8B8130048EB3B /* Authenticator.swift in Sources */,
-				75EC52951EE8B8200048EB3B /* AES+Foundation.swift in Sources */,
 				75EC52AB1EE8B83D0048EB3B /* Rabbit.swift in Sources */,
 				75EC529C1EE8B8200048EB3B /* String+FoundationExtension.swift in Sources */,
 				75EC52B81EE8B83D0048EB3B /* Utils.swift in Sources */,

+ 2 - 4
Sources/CryptoSwift/AES.Cryptors.swift

@@ -82,11 +82,9 @@ extension AES {
         init(aes: AES) throws {
             padding = aes.padding
 
-            switch aes.blockMode {
-            case .CFB, .OFB, .CTR, .GCM:
-                // CFB, OFB, CTR uses encryptBlock to decrypt
+            if aes.blockMode.options.contains(.useEncryptToDecrypt) {
                 worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.encrypt)
-            case .CBC, .ECB, .PCBC:
+            } else {
                 worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.decrypt)
             }
         }

+ 5 - 73
Sources/CryptoSwift/BlockMode/BlockMode.swift

@@ -13,78 +13,10 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
-typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
+public typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
 
-public enum BlockMode {
-    case ECB
-    case CBC(iv: Array<UInt8>)
-    case PCBC(iv: Array<UInt8>)
-    case CFB(iv: Array<UInt8>)
-    case OFB(iv: Array<UInt8>)
-    case CTR(iv: Array<UInt8>)
-    /// Additional authenticated data (AAD) is optional.
-    case GCM(iv: Array<UInt8>, aad: Array<UInt8>?)
-
-    public enum Error: Swift.Error {
-        /// Invalid key or IV
-        case invalidKeyOrInitializationVector
-        /// Invalid IV
-        case invalidInitializationVector
-    }
-
-    func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
-        switch self {
-        case .ECB:
-            return ECBModeWorker(cipherOperation: cipherOperation)
-        case let .CBC(iv):
-            if iv.count != blockSize {
-                throw Error.invalidInitializationVector
-            }
-            return CBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
-        case let .PCBC(iv):
-            if iv.count != blockSize {
-                throw Error.invalidInitializationVector
-            }
-            return PCBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
-        case let .CFB(iv):
-            if iv.count != blockSize {
-                throw Error.invalidInitializationVector
-            }
-            return CFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
-        case let .OFB(iv):
-            if iv.count != blockSize {
-                throw Error.invalidInitializationVector
-            }
-            return OFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
-        case let .CTR(iv):
-            if iv.count != blockSize {
-                throw Error.invalidInitializationVector
-            }
-            return CTRModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
-        case let .GCM(iv, aad):
-            if iv.isEmpty {
-                throw Error.invalidInitializationVector
-            }
-            return GCMModeWorker(iv: iv.slice, aad: aad?.slice, cipherOperation: cipherOperation)
-        }
-    }
-
-    var options: BlockModeOptions {
-        switch self {
-        case .ECB:
-            return .paddingRequired
-        case .CBC:
-            return [.initializationVectorRequired, .paddingRequired]
-        case .CFB:
-            return .initializationVectorRequired
-        case .CTR:
-            return .initializationVectorRequired
-        case .OFB:
-            return .initializationVectorRequired
-        case .PCBC:
-            return [.initializationVectorRequired, .paddingRequired]
-        case .GCM:
-            return .initializationVectorRequired
-        }
-    }
+public protocol BlockMode {
+    var options: BlockModeOptions { get }
+    //TODO: doesn't have to be public
+    func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker
 }

+ 7 - 2
Sources/CryptoSwift/BlockMode/BlockModeOptions.swift

@@ -13,10 +13,15 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
-struct BlockModeOptions: OptionSet {
-    let rawValue: Int
+public struct BlockModeOptions: OptionSet {
+    public let rawValue: Int
+
+    public init(rawValue: Int) {
+        self.rawValue = rawValue
+    }
 
     static let none = BlockModeOptions(rawValue: 1 << 0)
     static let initializationVectorRequired = BlockModeOptions(rawValue: 1 << 1)
     static let paddingRequired = BlockModeOptions(rawValue: 1 << 2)
+    static let useEncryptToDecrypt = BlockModeOptions(rawValue: 1 << 3)
 }

+ 2 - 2
Sources/CryptoSwift/BlockMode/BlockModeWorker.swift

@@ -13,7 +13,7 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
-protocol BlockModeWorker {
+public protocol BlockModeWorker {
     var cipherOperation: CipherOperationOnBlock { get }
 
     mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8>
@@ -21,7 +21,7 @@ protocol BlockModeWorker {
 }
 
 // TODO: remove and merge with BlockModeWorker
-protocol BlockModeWorkerFinalizing: BlockModeWorker {
+public protocol BlockModeWorkerFinalizing: BlockModeWorker {
     // Any final calculations, eg. calculate tag
     mutating func finalize(encrypt ciphertext: ArraySlice<UInt8>) -> Array<UInt8>
     mutating func finalize(decrypt plaintext: ArraySlice<UInt8>) -> Array<UInt8>

+ 22 - 0
Sources/CryptoSwift/BlockMode/CBC.swift

@@ -16,6 +16,28 @@
 //  Cipher-block chaining (CBC)
 //
 
+public struct CBC: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOptions = [.initializationVectorRequired, .paddingRequired]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return CBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
 struct CBCModeWorker: BlockModeWorker {
     let cipherOperation: CipherOperationOnBlock
     private let iv: ArraySlice<UInt8>

+ 22 - 0
Sources/CryptoSwift/BlockMode/CFB.swift

@@ -16,6 +16,28 @@
 //  Cipher feedback (CFB)
 //
 
+public struct CFB: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOptions = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return CFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
 struct CFBModeWorker: BlockModeWorker {
     let cipherOperation: CipherOperationOnBlock
     private let iv: ArraySlice<UInt8>

+ 22 - 0
Sources/CryptoSwift/BlockMode/CTR.swift

@@ -16,6 +16,28 @@
 //  Counter (CTR)
 //
 
+public struct CTR: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOptions = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return CTRModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
 struct CTRModeWorker: RandomAccessBlockModeWorker {
     let cipherOperation: CipherOperationOnBlock
     private let iv: ArraySlice<UInt8>

+ 11 - 0
Sources/CryptoSwift/BlockMode/ECB.swift

@@ -16,6 +16,17 @@
 //  Electronic codebook (ECB)
 //
 
+public struct ECB: BlockMode {
+    public let options: BlockModeOptions = .paddingRequired
+
+    public init() {
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        return ECBModeWorker(cipherOperation: cipherOperation)
+    }
+}
+
 struct ECBModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
     let cipherOperation: CipherOperationOnBlock

+ 33 - 0
Sources/CryptoSwift/BlockMode/GCM.swift

@@ -18,6 +18,39 @@
 //  ref: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.694.695&rep=rep1&type=pdf
 //
 
+public struct GCM: BlockMode {
+    public let options: BlockModeOptions = .initializationVectorRequired
+
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    private let iv: Array<UInt8>
+    private let additionalAuthenticatedData: Array<UInt8>?
+    public var authenticationTag: Array<UInt8>?
+
+    // encrypt
+    public init(iv: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil) {
+        self.iv = iv
+        self.additionalAuthenticatedData = additionalAuthenticatedData
+    }
+
+    // decrypt
+    public init(iv: Array<UInt8>, authenticationTag: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil) {
+        self.init(iv: iv, additionalAuthenticatedData: additionalAuthenticatedData)
+        self.authenticationTag = authenticationTag
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        if iv.isEmpty {
+            throw Error.invalidInitializationVector
+        }
+
+        return GCMModeWorker(iv: iv.slice, aad: additionalAuthenticatedData?.slice, cipherOperation: cipherOperation)
+    }
+}
+
 struct GCMModeWorker: BlockModeWorkerFinalizing {
     let cipherOperation: CipherOperationOnBlock
     // GCM nonce is 96-bits by default. It's the most effective length for the IV

+ 22 - 0
Sources/CryptoSwift/BlockMode/OFB.swift

@@ -16,6 +16,28 @@
 // Output Feedback (OFB)
 //
 
+public struct OFB: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOptions = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return OFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
 struct OFBModeWorker: BlockModeWorker {
     let cipherOperation: CipherOperationOnBlock
     private let iv: ArraySlice<UInt8>

+ 22 - 0
Sources/CryptoSwift/BlockMode/PCBC.swift

@@ -16,6 +16,28 @@
 //  Propagating Cipher Block Chaining (PCBC)
 //
 
+public struct PCBC: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOptions = [.initializationVectorRequired, .paddingRequired]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return PCBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
 struct PCBCModeWorker: BlockModeWorker {
     let cipherOperation: CipherOperationOnBlock
     private let iv: ArraySlice<UInt8>

+ 3 - 6
Sources/CryptoSwift/Blowfish.swift

@@ -314,7 +314,7 @@ public final class Blowfish {
         ],
     ]
 
-    public init(key: Array<UInt8>, blockMode: BlockMode = .CBC(iv: Array<UInt8>(repeating: 0, count: Blowfish.blockSize)), padding: Padding) throws {
+    public init(key: Array<UInt8>, blockMode: BlockMode = CBC(iv: Array<UInt8>(repeating: 0, count: Blowfish.blockSize)), padding: Padding) throws {
         precondition(key.count >= 5 && key.count <= 56)
 
         self.blockMode = blockMode
@@ -331,13 +331,10 @@ public final class Blowfish {
     private func setupBlockModeWorkers() throws {
         encryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
 
-        switch blockMode {
-        case .CFB, .OFB, .CTR:
+        if blockMode.options.contains(.useEncryptToDecrypt) {
             decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
-        case .CBC, .ECB, .PCBC:
+        } else {
             decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: decrypt)
-        case .GCM:
-            throw Error.invalidBlockMode
         }
     }
 

+ 1 - 1
Sources/CryptoSwift/CMAC.swift

@@ -34,7 +34,7 @@ public final class CMAC: Authenticator {
     // MARK: Authenticator
 
     public func authenticate(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
-        let aes = try AES(key: Array(key), blockMode: .CBC(iv: CMAC.Zero), padding: .noPadding)
+        let aes = try AES(key: Array(key), blockMode: CBC(iv: CMAC.Zero), padding: .noPadding)
 
         let l = try aes.encrypt(CMAC.Zero)
         var subKey1 = leftShiftOneBit(l)

+ 1 - 1
Sources/CryptoSwift/Foundation/AES+Foundation.swift

@@ -18,6 +18,6 @@ import Foundation
 extension AES {
     /// Initialize with CBC block mode.
     public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws {
-        try self.init(key: key.bytes, blockMode: .CBC(iv: iv.bytes), padding: padding)
+        try self.init(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: padding)
     }
 }

+ 1 - 1
Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift

@@ -18,6 +18,6 @@ import Foundation
 extension Blowfish {
     /// Initialize with CBC block mode.
     public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws {
-        try self.init(key: key.bytes, blockMode: .CBC(iv: iv.bytes), padding: padding)
+        try self.init(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: padding)
     }
 }

+ 43 - 36
Tests/Tests/AESTests.swift

@@ -25,7 +25,7 @@ final class AESTests: XCTestCase {
         let input: Array<UInt8> = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
         let expected: Array<UInt8> = [0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x4, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a]
 
-        let aes = try! AES(key: aesKey, blockMode: .ECB, padding: .noPadding)
+        let aes = try! AES(key: aesKey, blockMode: ECB(), padding: .noPadding)
         let encrypted = try! aes.encrypt(input)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -39,7 +39,7 @@ final class AESTests: XCTestCase {
 
         let expected: Array<UInt8> = [0xae, 0x8c, 0x59, 0x95, 0xb2, 0x6f, 0x8e, 0x3d, 0xb0, 0x6f, 0x0a, 0xa5, 0xfe, 0xc4, 0xf0, 0xc2]
 
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .noPadding)
         do {
             let encrypted = try aes.encrypt(input)
             XCTAssertEqual(encrypted, expected, "encryption failed")
@@ -73,7 +73,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d]
 
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -86,7 +86,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0x89, 0x64, 0xe0, 0xb1, 0x49, 0xc1, 0x0b, 0x7b, 0x68, 0x2e, 0x6e, 0x39, 0xaa, 0xeb, 0x73, 0x1c]
 
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -98,7 +98,7 @@ final class AESTests: XCTestCase {
         let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
 
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
 
         var ciphertext = Array<UInt8>()
         var encryptor = try! aes.makeEncryptor()
@@ -113,7 +113,7 @@ final class AESTests: XCTestCase {
         do {
             var ciphertext = Array<UInt8>()
             let plaintext = "Today Apple launched the open source Swift community, as well as amazing new tools and resources."
-            let aes = try AES(key: "passwordpassword".bytes, blockMode: .CBC(iv: "drowssapdrowssap".bytes))
+            let aes = try AES(key: "passwordpassword".bytes, blockMode: CBC(iv: "drowssapdrowssap".bytes))
             var encryptor = try! aes.makeEncryptor()
 
             ciphertext += try encryptor.update(withBytes: plaintext.bytes)
@@ -129,7 +129,7 @@ final class AESTests: XCTestCase {
         let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
         let ciphertext: Array<UInt8> = [118, 73, 171, 172, 129, 25, 178, 70, 206, 233, 142, 155, 18, 233, 25, 125, 76, 187, 200, 88, 117, 107, 53, 129, 37, 82, 158, 150, 152, 163, 143, 68, 169, 105, 137, 234, 93, 98, 239, 215, 41, 45, 51, 254, 138, 92, 251, 17]
 
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
         var plaintext = Array<UInt8>()
         var decryptor = try! aes.makeDecryptor()
         plaintext += try! decryptor.update(withBytes: ciphertext[0..<8])
@@ -145,7 +145,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a]
 
-        let aes = try! AES(key: key, blockMode: .CFB(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -157,8 +157,8 @@ final class AESTests: XCTestCase {
         let key: Array<UInt8> = [56, 118, 37, 51, 125, 78, 103, 107, 119, 40, 74, 88, 117, 112, 123, 75, 122, 89, 72, 36, 46, 91, 106, 60, 54, 110, 34, 126, 69, 126, 61, 87]
         let iv: Array<UInt8> = [69, 122, 99, 87, 83, 112, 110, 65, 54, 109, 107, 89, 73, 122, 74, 49]
         let plaintext: Array<UInt8> = [123, 10, 32, 32, 34, 67, 111, 110, 102, 105, 114, 109, 34, 32, 58, 32, 34, 116, 101, 115, 116, 105, 110, 103, 34, 44, 10, 32, 32, 34, 70, 105, 114, 115, 116, 78, 97, 109, 101, 34, 32, 58, 32, 34, 84, 101, 115, 116, 34, 44, 10, 32, 32, 34, 69, 109, 97, 105, 108, 34, 32, 58, 32, 34, 116, 101, 115, 116, 64, 116, 101, 115, 116, 46, 99, 111, 109, 34, 44, 10, 32, 32, 34, 76, 97, 115, 116, 78, 97, 109, 101, 34, 32, 58, 32, 34, 84, 101, 115, 116, 101, 114, 34, 44, 10, 32, 32, 34, 80, 97, 115, 115, 119, 111, 114, 100, 34, 32, 58, 32, 34, 116, 101, 115, 116, 105, 110, 103, 34, 44, 10, 32, 32, 34, 85, 115, 101, 114, 110, 97, 109, 101, 34, 32, 58, 32, 34, 84, 101, 115, 116, 34, 10, 125]
-        let encrypted: Array<UInt8> = try! AES(key: key, blockMode: .CFB(iv: iv)).encrypt(plaintext)
-        let decrypted: Array<UInt8> = try! AES(key: key, blockMode: .CFB(iv: iv)).decrypt(encrypted)
+        let encrypted: Array<UInt8> = try! AES(key: key, blockMode: CFB(iv: iv)).encrypt(plaintext)
+        let decrypted: Array<UInt8> = try! AES(key: key, blockMode: CFB(iv: iv)).decrypt(encrypted)
         XCTAssert(decrypted == plaintext, "decryption failed")
     }
 
@@ -168,7 +168,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a]
 
-        let aes = try! AES(key: key, blockMode: .OFB(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: OFB(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -181,7 +181,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60]
 
-        let aes = try! AES(key: key, blockMode: .OFB(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: OFB(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -194,7 +194,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6]
 
-        let aes = try! AES(key: key, blockMode: .PCBC(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: PCBC(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         print(encrypted.toHexString())
         XCTAssertEqual(encrypted, expected, "encryption failed")
@@ -208,7 +208,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a]
         let expected: Array<UInt8> = [0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce]
 
-        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted.count, plaintext.count)
         XCTAssertEqual(encrypted, expected, "encryption failed")
@@ -223,7 +223,7 @@ final class AESTests: XCTestCase {
         let iv: Array<UInt8> = [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff]
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xfd]
 
-        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .zeroPadding)
+        let aes = try! AES(key: key, blockMode: CTR(iv: iv), padding: .zeroPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(plaintext.count, 17)
@@ -236,7 +236,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0x01]
         let expected: Array<UInt8> = [0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x37]
 
-        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -259,7 +259,7 @@ final class AESTests: XCTestCase {
             plaintext[i * 6 + 5] = "|".utf8.first!
         }
 
-        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         var decryptor = try! aes.makeDecryptor()
@@ -291,7 +291,7 @@ final class AESTests: XCTestCase {
         let plaintext: Array<UInt8> = [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0x01, 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0x01]
         let expected: Array<UInt8> = [0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0xd, 0xb6, 0xce, 0x37, 0x40, 0xbd, 0x82, 0x85, 0x5d, 0x11, 0xfc, 0x8e, 0x49, 0x4a, 0xa9, 0xed, 0x23, 0xe0, 0xb9, 0x40, 0x2d]
 
-        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
         var encryptor = try! aes.makeEncryptor()
         var encrypted = Array<UInt8>()
         encrypted += try! encryptor.update(withBytes: plaintext[0..<5])
@@ -315,8 +315,8 @@ final class AESTests: XCTestCase {
         let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
         let plaintext: Array<UInt8> = [49, 46, 50, 50, 50, 51, 51, 51, 51]
 
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
-        let aes2 = try! AES(key: key2, blockMode: .CBC(iv: iv), padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
+        let aes2 = try! AES(key: key2, blockMode: CBC(iv: iv), padding: .pkcs7)
         let encrypted = try! aes.encrypt(plaintext)
         let decrypted = try? aes2.decrypt(encrypted)
         XCTAssertTrue(decrypted! != plaintext, "failed")
@@ -343,7 +343,7 @@ final class AESTests: XCTestCase {
         let plaintext = "Nullam quis risus eget urna mollis ornare vel eu leo.".bytes
         let key = "passwordpassword".bytes.md5() // -md md5
         let iv = "drowssapdrowssap".bytes // -iv 64726f777373617064726f7773736170
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7) // -aes-128-cbc
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7) // -aes-128-cbc
         let ciphertext = try! aes.encrypt(plaintext) // enc
 
         // $ echo -n "Nullam quis risus eget urna mollis ornare vel eu leo." | openssl enc -aes-128-cbc -md md5 -nosalt -iv 64726f777373617064726f7773736170 -pass pass:passwordpassword -base64
@@ -357,7 +357,7 @@ final class AESTests: XCTestCase {
         let ciphertext: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f] // test
         let key = "passwordpassword".bytes.md5() // -md md5
         let iv = "drowssapdrowssap".bytes // -iv 64726f777373617064726f7773736170
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7) // -aes-128-cbc
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7) // -aes-128-cbc
         let plaintext = try! ciphertext.decrypt(cipher: aes)
         XCTAssertEqual("74657374", plaintext.toHexString())
     }
@@ -370,10 +370,11 @@ extension AESTests {
         let key = Array<UInt8>(hex: "0x00000000000000000000000000000000")
         let iv = Array<UInt8>(hex: "0x000000000000000000000000")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: nil), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt([UInt8]())
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "58e2fccefa7e3061367f1d57a4e7455a")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "58e2fccefa7e3061367f1d57a4e7455a")) // T (128-bit)
     }
 
     func testAESGCMTestCase2() {
@@ -382,10 +383,11 @@ extension AESTests {
         let plaintext = Array<UInt8>(hex: "0x00000000000000000000000000000000")
         let iv = Array<UInt8>(hex: "0x000000000000000000000000")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: nil), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "0388dace60b6a392f328c2b971b2fe78")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "ab6e47d42cec13bdf53a67b21257bddf")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "ab6e47d42cec13bdf53a67b21257bddf")) // T (128-bit)
     }
 
     func testAESGCMTestCase3() {
@@ -394,11 +396,12 @@ extension AESTests {
         let plaintext = Array<UInt8>(hex: "0xd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255")
         let iv = Array<UInt8>(hex: "0xcafebabefacedbaddecaf888")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: nil), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "0x42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "0x4d5c2af327cd64a62cf35abd2ba6fab4")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "0x4d5c2af327cd64a62cf35abd2ba6fab4")) // T (128-bit)
     }
 
     func testAESGCMTestCase4() {
@@ -408,11 +411,12 @@ extension AESTests {
         let iv = Array<UInt8>(hex: "0xcafebabefacedbaddecaf888")
         let auth = Array<UInt8>(hex: "0xfeedfacedeadbeeffeedfacedeadbeefabaddad2")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: auth), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv, additionalAuthenticatedData: auth), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "0x42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "0x5bc94fbc3221a5db94fae95ae7121a47")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "0x5bc94fbc3221a5db94fae95ae7121a47")) // T (128-bit)
     }
 
     func testAESGCMTestCase5() {
@@ -422,11 +426,12 @@ extension AESTests {
         let iv = Array<UInt8>(hex: "0xcafebabefacedbad")
         let auth = Array<UInt8>(hex: "0xfeedfacedeadbeeffeedfacedeadbeefabaddad2")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: auth), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv, additionalAuthenticatedData: auth), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "0x61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "0x3612d2e79e3b0785561be14aaca2fccb")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "0x3612d2e79e3b0785561be14aaca2fccb")) // T (128-bit)
     }
 
     func testAESGCMTestCase6() {
@@ -436,11 +441,12 @@ extension AESTests {
         let iv = Array<UInt8>(hex: "0x9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b")
         let auth = Array<UInt8>(hex: "0xfeedfacedeadbeeffeedfacedeadbeefabaddad2")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: auth), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv, additionalAuthenticatedData: auth), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "0x8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "0x619cc5aefffe0bfa462af43c1699d050")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "0x619cc5aefffe0bfa462af43c1699d050")) // T (128-bit)
     }
 
     func testAESGCMTestCase7() {
@@ -449,11 +455,12 @@ extension AESTests {
         let plaintext = Array<UInt8>(hex: "")
         let iv = Array<UInt8>(hex: "0x000000000000000000000000")
 
-        let aes = try! AES(key: key, blockMode: .GCM(iv: iv, aad: nil), padding: .noPadding)
+        var authenticationTag: Array<UInt8> = []
+        let aes = try! AES(key: key, blockMode: GCM(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(Array(encrypted.prefix(encrypted.endIndex - 16)), [UInt8](hex: "")) // C
-        XCTAssertEqual(Array(encrypted.suffix(16)), [UInt8](hex: "0xcd33b28ac773f74ba00ed1f312572435")) // T (128-bit)
+        XCTAssertEqual(authenticationTag, [UInt8](hex: "0xcd33b28ac773f74ba00ed1f312572435")) // T (128-bit)
     }
 }
 

+ 2 - 2
Tests/Tests/AESTestsPerf.swift

@@ -22,7 +22,7 @@ final class AESTestsPerf: XCTestCase {
         let key: Array<UInt8> = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]
         let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
         let message = Array<UInt8>(repeating: 7, count: 1024 * 1024)
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
         measure {
             _ = try! aes.encrypt(message)
         }
@@ -32,7 +32,7 @@ final class AESTestsPerf: XCTestCase {
         let key: Array<UInt8> = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]
         let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
         let message = Array<UInt8>(repeating: 7, count: 1024 * 1024)
-        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
         measure {
             _ = try! aes.decrypt(message)
         }

+ 1 - 1
Tests/Tests/Access.swift

@@ -201,7 +201,7 @@ class Access: XCTestCase {
             let enc = try cipher.encrypt([1, 2, 3])
             _ = try cipher.decrypt(enc)
 
-            _ = try AES(key: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], blockMode: .CBC(iv: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]), padding: .noPadding)
+            _ = try AES(key: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], blockMode: CBC(iv: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]), padding: .noPadding)
 
             _ = AES.Variant.aes128
             _ = AES.blockSize

+ 6 - 6
Tests/Tests/BlowfishTests.swift

@@ -162,13 +162,13 @@ class BlowfishTests: XCTestCase {
 
     func testEncrypt() {
         for test in tests {
-            XCTAssertEqual(try Blowfish(key: test.key, blockMode: .ECB, padding: .noPadding).encrypt(test.input), test.output)
+            XCTAssertEqual(try Blowfish(key: test.key, blockMode: ECB(), padding: .noPadding).encrypt(test.input), test.output)
         }
     }
 
     func testDecrypt() {
         for test in tests {
-            XCTAssertEqual(try Blowfish(key: test.key, blockMode: .ECB, padding: .noPadding).decrypt(test.output), test.input)
+            XCTAssertEqual(try Blowfish(key: test.key, blockMode: ECB(), padding: .noPadding).decrypt(test.output), test.input)
         }
     }
 
@@ -176,7 +176,7 @@ class BlowfishTests: XCTestCase {
         let key = Array<UInt8>(hex: "0123456789ABCDEFF0E1D2C3B4A59687")
         let iv = Array<UInt8>(hex: "FEDCBA9876543210")
         let input = Array<UInt8>(hex: "37363534333231204E6F77206973207468652074696D6520666F722000")
-        XCTAssertEqual(try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .zeroPadding).encrypt(input), Array<UInt8>(hex: "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"))
+        XCTAssertEqual(try Blowfish(key: key, blockMode: CBC(iv: iv), padding: .zeroPadding).encrypt(input), Array<UInt8>(hex: "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"))
     }
 
     func testEncryptDecrypt() {
@@ -185,7 +185,7 @@ class BlowfishTests: XCTestCase {
         let input = Array<UInt8>.init(hex: "37363534333231204E6F77206973207468652074696D6520666F722000")
 
         do {
-            let cipher = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+            let cipher = try Blowfish(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)
             let ciphertext = try cipher.encrypt(input)
             let plaintext = try cipher.decrypt(ciphertext)
             XCTAssertEqual(plaintext, input)
@@ -200,8 +200,8 @@ class BlowfishTests: XCTestCase {
             let plaintext = "secret12".bytes
             let key = "passwordpassword".bytes
             let iv = "12345678".bytes
-            let encrypted = try Blowfish(key: key, blockMode: .CFB(iv: iv), padding: .noPadding).encrypt(plaintext)
-            let decrypted = try Blowfish(key: key, blockMode: .CFB(iv: iv), padding: .noPadding).decrypt(encrypted)
+            let encrypted = try Blowfish(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt(plaintext)
+            let decrypted = try Blowfish(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt(encrypted)
             XCTAssertEqual(plaintext, decrypted)
         } catch {
             XCTFail(error.localizedDescription)

+ 1 - 1
Tests/Tests/ExtensionsTest.swift

@@ -56,7 +56,7 @@ final class ExtensionsTest: XCTestCase {
 
     func testEmptyStringEncrypt() {
         do {
-            let cipher = try AES(key: "secret0key000000".bytes.md5(), blockMode: .ECB)
+            let cipher = try AES(key: "secret0key000000".bytes.md5(), blockMode: ECB())
             let encrypted = try "".encryptToBase64(cipher: cipher)
             let decrypted = try encrypted?.decryptBase64ToString(cipher: cipher)
             XCTAssertEqual("", decrypted)