Kaynağa Gözat

Merge branch 'develop'

Marcin Krzyżanowski 7 yıl önce
ebeveyn
işleme
d0084e4a6f
44 değiştirilmiş dosya ile 538 ekleme ve 402 silme
  1. 10 0
      CHANGELOG
  2. 2 2
      CryptoSwift.playground/Contents.swift
  3. 3 3
      CryptoSwift.podspec
  4. 16 13
      CryptoSwift.xcodeproj/project.pbxproj
  5. 2 1
      CryptoSwift.xcodeproj/xcshareddata/xcschemes/CryptoSwift.xcscheme
  6. 6 6
      Package.swift
  7. 10 10
      README.md
  8. 142 0
      Sources/CryptoSwift/AES.Cryptors.swift
  9. 16 16
      Sources/CryptoSwift/AES.swift
  10. 2 1
      Sources/CryptoSwift/Array+Extension.swift
  11. 3 3
      Sources/CryptoSwift/Array+Extensions.swift
  12. 36 14
      Sources/CryptoSwift/BlockMode/BlockMode.swift
  13. 7 9
      Sources/CryptoSwift/BlockMode/CBC.swift
  14. 7 9
      Sources/CryptoSwift/BlockMode/CFB.swift
  15. 6 8
      Sources/CryptoSwift/BlockMode/CTR.swift
  16. 2 2
      Sources/CryptoSwift/BlockMode/ECB.swift
  17. 6 8
      Sources/CryptoSwift/BlockMode/OFB.swift
  18. 7 9
      Sources/CryptoSwift/BlockMode/PCBC.swift
  19. 21 31
      Sources/CryptoSwift/Blowfish.swift
  20. 0 2
      Sources/CryptoSwift/ChaCha20.swift
  21. 15 48
      Sources/CryptoSwift/Collection+Extension.swift
  22. 2 2
      Sources/CryptoSwift/Cryptors.swift
  23. 3 6
      Sources/CryptoSwift/Foundation/AES+Foundation.swift
  24. 3 6
      Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift
  25. 1 4
      Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift
  26. 1 5
      Sources/CryptoSwift/Foundation/HMAC+Foundation.swift
  27. 2 11
      Sources/CryptoSwift/Foundation/Rabbit+Foundation.swift
  28. 1 1
      Sources/CryptoSwift/Info.plist
  29. 0 2
      Sources/CryptoSwift/Rabbit.swift
  30. 20 30
      Sources/CryptoSwift/SHA3.swift
  31. 2 0
      Sources/CryptoSwift/SecureBytes.swift
  32. 16 12
      Sources/CryptoSwift/String+Extension.swift
  33. 11 4
      Sources/CryptoSwift/UInt16+Extension.swift
  34. 13 6
      Sources/CryptoSwift/UInt32+Extension.swift
  35. 17 10
      Sources/CryptoSwift/UInt64+Extension.swift
  36. 15 13
      Sources/CryptoSwift/Utils.swift
  37. 59 51
      Tests/CryptoSwiftTests/AESTests.swift
  38. 5 5
      Tests/CryptoSwiftTests/Access.swift
  39. 10 8
      Tests/CryptoSwiftTests/BlowfishTests.swift
  40. 3 3
      Tests/CryptoSwiftTests/ChaCha20Tests.swift
  41. 20 0
      Tests/CryptoSwiftTests/DigestTests.swift
  42. 5 16
      Tests/CryptoSwiftTests/ExtensionsTest.swift
  43. 7 7
      Tests/CryptoSwiftTests/PBKDF.swift
  44. 3 5
      Tests/CryptoSwiftTests/RabbitTests.swift

+ 10 - 0
CHANGELOG

@@ -1,3 +1,13 @@
+0.8.0
+- Adds SHA3 Keccak variants
+- Adds String.bytes helper to convert String to array of bytes
+- Improves AES performance
+- Speeds up compilation times with Swift 4
+- Fixes: Blowfish minimum key size is 5
+- Removes Ciphers "iv" parameter (value moved to BlockMode)
+- BlockMode uses associated value for IV value where apply e.g. .CBC(iv: ivbytes)
+- Refactors internal hacks no longer needed with Swift 4
+
 0.7.2
 - Adds Padding enum (.pkcs5, .pkcs7, .noPadding, .zeroPadding)
 - Removes Generics from the public API.

+ 2 - 2
CryptoSwift.playground/Contents.swift

@@ -30,8 +30,8 @@ Digest.sha1(bytes)
 //: Digest calculated incrementally
 do {
     var digest = MD5()
-    let _ = try digest.update(withBytes: [0x31, 0x32])
-    let _ = try digest.update(withBytes: [0x33])
+    _ = try digest.update(withBytes: [0x31, 0x32])
+    _ = try digest.update(withBytes: [0x33])
     let result = try digest.finish()
     print(result)
 } catch {}

+ 3 - 3
CryptoSwift.podspec

@@ -1,9 +1,9 @@
 Pod::Spec.new do |s|
   s.name         = "CryptoSwift"
-  s.version      = "0.7.2"
+  s.version      = "0.8.0"
   s.source       = { :git => "https://github.com/krzyzanowskim/CryptoSwift.git", :tag => "#{s.version}" }
   s.summary      = "Cryptography in Swift. SHA, MD5, CRC, PBKDF, Poly1305, HMAC, ChaCha20, Rabbit, Blowfish, AES."
-  s.description  = "Cryptography functions and helpers for Swift implemented in Swift. SHA, MD5, PBKDF1, PBKDF2, CRC, Poly1305, HMAC, ChaCha20, Rabbit, Blowfish, AES."
+  s.description  = "Cryptography functions and helpers for Swift implemented in Swift. SHA-1, SHA-2, SHA-3, MD5, PBKDF1, PBKDF2, CRC, Poly1305, HMAC, ChaCha20, Rabbit, Blowfish, AES"
   s.homepage     = "https://github.com/krzyzanowskim/CryptoSwift"
   s.license      = {:type => "Attribution License", :file => "LICENSE"}
   s.authors      = {'Marcin Krzyżanowski' => 'marcin@krzyzanowskim.com'}
@@ -14,5 +14,5 @@ Pod::Spec.new do |s|
   s.tvos.deployment_target = "9.0"
   s.source_files  = "Sources/CryptoSwift/**/*.swift"
   s.requires_arc = true
-  s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.0', 'SWIFT_OPTIMIZATION_LEVEL' => '-Owholemodule', 'SWIFT_DISABLE_SAFETY_CHECKS' => 'YES', 'GCC_UNROLL_LOOPS' => 'YES'}
+  s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.0', 'SWIFT_OPTIMIZATION_LEVEL' => '-Owholemodule', 'SWIFT_DISABLE_SAFETY_CHECKS' => 'YES', 'SWIFT_ENFORCE_EXCLUSIVE_ACCESS' => 'compile-time', 'GCC_UNROLL_LOOPS' => 'YES'}
 end

+ 16 - 13
CryptoSwift.xcodeproj/project.pbxproj

@@ -11,6 +11,7 @@
 		750509991F6BEF2A00394A1B /* PKCS7.swift in Sources */ = {isa = PBXBuildFile; fileRef = 750509981F6BEF2A00394A1B /* PKCS7.swift */; };
 		750CC3EB1DC0CACE0096BE6E /* BlowfishTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 750CC3EA1DC0CACE0096BE6E /* BlowfishTests.swift */; };
 		75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */; };
+		751EE9781F93996100161FFC /* AES.Cryptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 751EE9771F93996100161FFC /* AES.Cryptors.swift */; };
 		753B33011DAB84D600D06422 /* RandomBytesSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753B33001DAB84D600D06422 /* RandomBytesSequenceTests.swift */; };
 		75482EA41CB310B7001F66A5 /* PBKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA31CB310B7001F66A5 /* PBKDF.swift */; };
 		754BE46819693E190098E6F3 /* DigestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754BE46719693E190098E6F3 /* DigestTests.swift */; };
@@ -156,6 +157,7 @@
 		750509981F6BEF2A00394A1B /* PKCS7.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PKCS7.swift; sourceTree = "<group>"; };
 		750CC3EA1DC0CACE0096BE6E /* BlowfishTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlowfishTests.swift; sourceTree = "<group>"; };
 		75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poly1305Tests.swift; sourceTree = "<group>"; };
+		751EE9771F93996100161FFC /* AES.Cryptors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AES.Cryptors.swift; sourceTree = "<group>"; };
 		753B33001DAB84D600D06422 /* RandomBytesSequenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomBytesSequenceTests.swift; sourceTree = "<group>"; };
 		75482EA31CB310B7001F66A5 /* PBKDF.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PBKDF.swift; sourceTree = "<group>"; };
 		754BE45519693E190098E6F3 /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -285,6 +287,7 @@
 		754BE46419693E190098E6F3 /* Tests */ = {
 			isa = PBXGroup;
 			children = (
+				E3FD2D511D6B813C00A9F35F /* Error+Extension.swift */,
 				754BE46719693E190098E6F3 /* DigestTests.swift */,
 				75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */,
 				758A94271A65C59200E46135 /* HMACTests.swift */,
@@ -299,7 +302,6 @@
 				75C2E76C1D55F097003D2BCA /* Access.swift */,
 				756BFDCA1A82B87300B9D9A4 /* Bridging.h */,
 				754BE46519693E190098E6F3 /* Supporting Files */,
-				E3FD2D511D6B813C00A9F35F /* Error+Extension.swift */,
 			);
 			name = Tests;
 			path = Tests/CryptoSwiftTests;
@@ -327,6 +329,7 @@
 			isa = PBXGroup;
 			children = (
 				75EC52381EE8B6CA0048EB3B /* AES.swift */,
+				751EE9771F93996100161FFC /* AES.Cryptors.swift */,
 				75EC52391EE8B6CA0048EB3B /* Array+Extension.swift */,
 				75EC523A1EE8B6CA0048EB3B /* Authenticator.swift */,
 				75EC523B1EE8B6CA0048EB3B /* BatchedCollection.swift */,
@@ -345,7 +348,6 @@
 				75EC52521EE8B6CA0048EB3B /* Foundation */,
 				75EC525C1EE8B6CA0048EB3B /* Generics.swift */,
 				75EC525D1EE8B6CA0048EB3B /* HMAC.swift */,
-				75EC525F1EE8B6CA0048EB3B /* Int+Extension.swift */,
 				75EC52611EE8B6CA0048EB3B /* MD5.swift */,
 				75EC52621EE8B6CA0048EB3B /* NoPadding.swift */,
 				75EC52631EE8B6CA0048EB3B /* Operators.swift */,
@@ -360,10 +362,11 @@
 				75EC52701EE8B6CA0048EB3B /* SHA2.swift */,
 				75EC52711EE8B6CA0048EB3B /* SHA3.swift */,
 				75EC52721EE8B6CA0048EB3B /* String+Extension.swift */,
+				75EC525F1EE8B6CA0048EB3B /* Int+Extension.swift */,
+				75EC52761EE8B6CA0048EB3B /* UInt8+Extension.swift */,
 				75EC52731EE8B6CA0048EB3B /* UInt16+Extension.swift */,
 				75EC52741EE8B6CA0048EB3B /* UInt32+Extension.swift */,
 				75EC52751EE8B6CA0048EB3B /* UInt64+Extension.swift */,
-				75EC52761EE8B6CA0048EB3B /* UInt8+Extension.swift */,
 				75EC52771EE8B6CA0048EB3B /* Updatable.swift */,
 				75EC52781EE8B6CA0048EB3B /* Utils.swift */,
 				75EC52791EE8B6CA0048EB3B /* ZeroPadding.swift */,
@@ -578,6 +581,7 @@
 				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 */,
 				75EC52B31EE8B83D0048EB3B /* UInt16+Extension.swift in Sources */,
@@ -689,13 +693,13 @@
 				CODE_SIGNING_REQUIRED = NO;
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = 1;
+				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEFINES_MODULE = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"DEBUG=1",
 					"$(inherited)",
@@ -713,7 +717,6 @@
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = CryptoSwift;
 				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos watchos appletvsimulator watchsimulator";
-				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3,4";
 				TVOS_DEPLOYMENT_TARGET = 9.0;
@@ -751,6 +754,7 @@
 				CODE_SIGNING_REQUIRED = NO;
 				COPY_PHASE_STRIP = YES;
 				CURRENT_PROJECT_VERSION = 1;
+				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEFINES_MODULE = YES;
 				ENABLE_NS_ASSERTIONS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -769,7 +773,6 @@
 				METAL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = CryptoSwift;
 				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos watchos appletvsimulator watchsimulator";
-				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3,4";
 				TVOS_DEPLOYMENT_TARGET = 9.0;
@@ -793,10 +796,11 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				OTHER_SWIFT_FLAGS = "-Xfrontend -debug-time-function-bodies";
 				PRODUCT_BUNDLE_IDENTIFIER = com.krzyzanowskim.CryptoSwift;
 				PRODUCT_NAME = CryptoSwift;
 				SKIP_INSTALL = YES;
-				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_SWIFT3_OBJC_INFERENCE = Off;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.0;
 				WATCHOS_DEPLOYMENT_TARGET = 2.0;
@@ -824,7 +828,9 @@
 				PRODUCT_NAME = CryptoSwift;
 				SKIP_INSTALL = YES;
 				SWIFT_DISABLE_SAFETY_CHECKS = YES;
+				SWIFT_ENFORCE_EXCLUSIVE_ACCESS = "compile-time";
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_SWIFT3_OBJC_INFERENCE = Off;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.0;
 				WATCHOS_DEPLOYMENT_TARGET = 2.0;
@@ -835,10 +841,6 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"DEBUG=1",
-					"$(inherited)",
-				);
 				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
 					"includes/**",
@@ -903,6 +905,7 @@
 				CODE_SIGNING_REQUIRED = NO;
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = 1;
+				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEFINES_MODULE = YES;
 				ENABLE_NS_ASSERTIONS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -924,7 +927,6 @@
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = CryptoSwift;
 				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos watchos appletvsimulator watchsimulator";
-				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3,4";
 				TVOS_DEPLOYMENT_TARGET = 9.0;
@@ -946,7 +948,6 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				ENABLE_BITCODE = YES;
 				"ENABLE_BITCODE[sdk=macosx*]" = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_UNROLL_LOOPS = YES;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -956,7 +957,9 @@
 				PRODUCT_NAME = CryptoSwift;
 				SKIP_INSTALL = YES;
 				SWIFT_DISABLE_SAFETY_CHECKS = YES;
+				SWIFT_ENFORCE_EXCLUSIVE_ACCESS = "compile-time";
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_SWIFT3_OBJC_INFERENCE = Off;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.0;
 				WATCHOS_DEPLOYMENT_TARGET = 2.0;

+ 2 - 1
CryptoSwift.xcodeproj/xcshareddata/xcschemes/CryptoSwift.xcscheme

@@ -29,7 +29,8 @@
       disableMainThreadChecker = "YES"
       language = ""
       systemAttachmentLifetime = "keepNever"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      codeCoverageEnabled = "YES">
       <Testables>
          <TestableReference
             skipped = "NO">

+ 6 - 6
Package.swift

@@ -2,9 +2,9 @@
 
 import PackageDescription
 
-let _ = Package(name: "CryptoSwift", products: [.library(name: "CryptoSwift", targets: ["CryptoSwift"])],
-              targets: [
-                  .target(name:"CryptoSwift"),
-                  .testTarget(name:"CryptoSwiftTests",dependencies:["CryptoSwift"])
-              ],
-              swiftLanguageVersions: [4])
+_ = Package(name: "CryptoSwift", products: [.library(name: "CryptoSwift", targets: ["CryptoSwift"])],
+            targets: [
+                .target(name: "CryptoSwift"),
+                .testTarget(name: "CryptoSwiftTests", dependencies: ["CryptoSwift"]),
+            ],
+            swiftLanguageVersions: [4])

+ 10 - 10
README.md

@@ -186,11 +186,11 @@ also check [Playground](/CryptoSwift.playground/Contents.swift)
 import CryptoSwift
 ```
 
-CryptoSwift uses array of bytes aka `Array<UInt8>` as a base type for all operations. Every data may be converted to a stream of bytes. You will find convenience functions that accept String or NSData, and it will be internally converted to the array of bytes.
+CryptoSwift uses array of bytes aka `Array<UInt8>` as a base type for all operations. Every data may be converted to a stream of bytes. You will find convenience functions that accept `String` or `Data`, and it will be internally converted to the array of bytes.
 
 ##### Data types conversion
 
-For you convenience **CryptoSwift** provides two functions to easily convert array of bytes to NSData and another way around:
+For you convenience **CryptoSwift** provides two functions to easily convert array of bytes to `Data` and another way around:
 
 Data from bytes:
 
@@ -213,7 +213,7 @@ let hex   = bytes.toHexString()            // "010203"
 
 Build bytes out of `String`
 ```swift
-let bytes = Array("string".utf8)
+let bytes: Array<UInt8> = "password".bytes  // Array("password".utf8)
 ```
 
 Also... check out helpers that work with **Base64** encoded data:
@@ -255,7 +255,7 @@ do {
 Hashing a String and printing result
 
 ```swift
-let hash = "123".md5()
+let hash = "123".md5() // "123".bytes.md5()
 ```
 
 ##### Calculate CRC
@@ -312,8 +312,8 @@ let decrypted = try Rabbit(key: key, iv: iv).decrypt(encrypted)
 ##### Blowfish
 
 ```swift
-let encrypted = try Blowfish(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7).encrypt(message)
-let decrypted = try Blowfish(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7).decrypt(encrypted)
+let encrypted = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).encrypt(message)
+let decrypted = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
 ```
 
 ##### AES
@@ -328,7 +328,7 @@ Variant of AES encryption (AES-128, AES-192, AES-256) depends on given key lengt
 
 AES-256 example
 ```swift
-try AES(key: [1,2,3,...,32], iv: [1,2,3,...,16], blockMode: .CBC, padding: .pkcs7)
+try AES(key: [1,2,3,...,32], blockMode: .CBC(iv: [1,2,3,...,16]), padding: .pkcs7)
 ```
  
 ###### All at once
@@ -371,8 +371,8 @@ let key: Array<UInt8> = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 let iv: Array<UInt8> = AES.randomIV(AES.blockSize)
 
 do {
-    let encrypted = try AES(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7).encrypt(input)
-    let decrypted = try AES(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7).decrypt(encrypted)
+    let encrypted = try AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).encrypt(input)
+    let decrypted = try AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
 } catch {
     print(error)
 }    
@@ -382,7 +382,7 @@ AES without data padding
 
 ```swift
 let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9]
-let encrypted: Array<UInt8> = try! AES(key: "secret0key000000", iv:"0123456789012345", blockMode: .CBC, padding: .noPadding).encrypt(input)
+let encrypted: Array<UInt8> = try! AES(key: Array("secret0key000000".utf8), blockMode: .CBC(iv: Array("0123456789012345".utf8)), padding: .noPadding).encrypt(input)
 ```
 
 Using convenience extensions

+ 142 - 0
Sources/CryptoSwift/AES.Cryptors.swift

@@ -0,0 +1,142 @@
+//
+//  AES.swift
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+// MARK: Cryptors
+extension AES: Cryptors {
+    public func makeEncryptor() throws -> AES.Encryptor {
+        return try AES.Encryptor(aes: self)
+    }
+
+    public func makeDecryptor() throws -> AES.Decryptor {
+        return try AES.Decryptor(aes: self)
+    }
+}
+
+// MARK: Encryptor
+extension AES {
+    public struct Encryptor: Updatable {
+        private var worker: BlockModeWorker
+        private let padding: Padding
+        private var accumulated = Array<UInt8>()
+        private var processedBytesTotalCount: Int = 0
+        private let paddingRequired: Bool
+
+        init(aes: AES) throws {
+            padding = aes.padding
+            worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.encrypt)
+            paddingRequired = aes.blockMode.options.contains(.paddingRequired)
+        }
+
+        public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
+            accumulated += bytes
+
+            if isLast {
+                accumulated = padding.add(to: accumulated, blockSize: AES.blockSize)
+            }
+
+            var processedBytes = 0
+            var encrypted = Array<UInt8>(reserveCapacity: accumulated.count)
+            for chunk in accumulated.batched(by: AES.blockSize) {
+                if isLast || (accumulated.count - processedBytes) >= AES.blockSize {
+                    encrypted += worker.encrypt(chunk)
+                    processedBytes += chunk.count
+                }
+            }
+            accumulated.removeFirst(processedBytes)
+            processedBytesTotalCount += processedBytes
+            return encrypted
+        }
+    }
+}
+
+// MARK: Decryptor
+extension AES {
+
+    public struct Decryptor: RandomAccessCryptor {
+        private var worker: BlockModeWorker
+        private let padding: Padding
+        private var accumulated = Array<UInt8>()
+        private var processedBytesTotalCount: Int = 0
+        private let paddingRequired: Bool
+
+        private var offset: Int = 0
+        private var offsetToRemove: Int = 0
+
+        init(aes: AES) throws {
+            padding = aes.padding
+
+            switch aes.blockMode {
+            case .CFB, .OFB, .CTR:
+                // CFB, OFB, CTR uses encryptBlock to decrypt
+                worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.encrypt)
+            default:
+                worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.decrypt)
+            }
+
+            paddingRequired = aes.blockMode.options.contains(.paddingRequired)
+        }
+
+        public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
+            // prepend "offset" number of bytes at the begining
+            if offset > 0 {
+                accumulated += Array<UInt8>(repeating: 0, count: offset) + bytes
+                offsetToRemove = offset
+                offset = 0
+            } else {
+                accumulated += bytes
+            }
+
+            var processedBytes = 0
+            var plaintext = Array<UInt8>(reserveCapacity: accumulated.count)
+            for chunk in accumulated.batched(by: AES.blockSize) {
+                if isLast || (accumulated.count - processedBytes) >= AES.blockSize {
+                    plaintext += worker.decrypt(chunk)
+
+                    // remove "offset" from the beginning of first chunk
+                    if offsetToRemove > 0 {
+                        plaintext.removeFirst(offsetToRemove)
+                        offsetToRemove = 0
+                    }
+
+                    processedBytes += chunk.count
+                }
+            }
+            accumulated.removeFirst(processedBytes)
+            processedBytesTotalCount += processedBytes
+
+            if isLast {
+                plaintext = padding.remove(from: plaintext, blockSize: AES.blockSize)
+            }
+
+            return plaintext
+        }
+
+        @discardableResult public mutating func seek(to position: Int) -> Bool {
+            guard var worker = self.worker as? RandomAccessBlockModeWorker else {
+                return false
+            }
+
+            worker.counter = UInt(position / AES.blockSize)
+            self.worker = worker
+
+            offset = position % AES.blockSize
+
+            accumulated = []
+
+            return true
+        }
+    }
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 16 - 16
Sources/CryptoSwift/AES.swift


+ 2 - 1
Sources/CryptoSwift/Array+Extension.swift

@@ -27,7 +27,8 @@ extension Array {
 
 extension Array {
 
-    /** split in chunks with given chunk size */
+    /// split in chunks with given chunk size
+    @available(*, deprecated: 0.8.0, message: "")
     public func chunks(size chunksize: Int) -> Array<Array<Element>> {
         var words = Array<Array<Element>>()
         words.reserveCapacity(count / chunksize)

+ 3 - 3
Sources/CryptoSwift/Array+Extensions.swift

@@ -19,7 +19,7 @@ public extension Array where Element == UInt8 {
     public func toHexString() -> String {
         return `lazy`.reduce("") {
             var s = String($1, radix: 16)
-            if s.characters.count == 1 {
+            if s.count == 1 {
                 s = "0" + s
             }
             return $0 + s
@@ -70,11 +70,11 @@ public extension Array where Element == UInt8 {
     }
 
     public func encrypt(cipher: Cipher) throws -> [Element] {
-        return try cipher.encrypt(self.slice)
+        return try cipher.encrypt(slice)
     }
 
     public func decrypt(cipher: Cipher) throws -> [Element] {
-        return try cipher.decrypt(self.slice)
+        return try cipher.decrypt(slice)
     }
 
     public func authenticate<A: Authenticator>(with authenticator: A) throws -> [Element] {

+ 36 - 14
Sources/CryptoSwift/BlockMode/BlockMode.swift

@@ -14,25 +14,47 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
-typealias CipherOperationOnBlock = (_ block: Array<UInt8>) -> Array<UInt8>?
+typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
 
 public enum BlockMode {
-    case ECB, CBC, PCBC, CFB, OFB, CTR
+    case ECB, CBC(iv: Array<UInt8>), PCBC(iv: Array<UInt8>), CFB(iv: Array<UInt8>), OFB(iv: Array<UInt8>), CTR(iv: Array<UInt8>)
 
-    func worker(_ iv: Array<UInt8>?, cipherOperation: @escaping CipherOperationOnBlock) -> BlockModeWorker {
+    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(iv: iv ?? [], cipherOperation: cipherOperation)
-        case .CBC:
-            return CBCModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
-        case .PCBC:
-            return PCBCModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
-        case .CFB:
-            return CFBModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
-        case .OFB:
-            return OFBModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
-        case .CTR:
-            return CTRModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+            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)
         }
     }
 

+ 7 - 9
Sources/CryptoSwift/BlockMode/CBC.swift

@@ -18,13 +18,11 @@
 //
 
 struct CBCModeWorker: BlockModeWorker {
-    typealias Element = Array<UInt8>
-
     let cipherOperation: CipherOperationOnBlock
-    private let iv: Element
-    private var prev: Element?
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
 
-    init(iv: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+    init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
     }
@@ -33,16 +31,16 @@ struct CBCModeWorker: BlockModeWorker {
         guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
             return Array(plaintext)
         }
-        prev = ciphertext
+        prev = ciphertext.slice
         return ciphertext
     }
 
     mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
-        guard let plaintext = cipherOperation(Array(ciphertext)) else {
+        guard let plaintext = cipherOperation(ciphertext) else {
             return Array(ciphertext)
         }
-        let result = xor(prev ?? iv, plaintext)
-        prev = Array(ciphertext)
+        let result: Array<UInt8> = xor(prev ?? iv, plaintext)
+        prev = ciphertext
         return result
     }
 }

+ 7 - 9
Sources/CryptoSwift/BlockMode/CFB.swift

@@ -18,13 +18,11 @@
 //
 
 struct CFBModeWorker: BlockModeWorker {
-    typealias Element = Array<UInt8>
-
     let cipherOperation: CipherOperationOnBlock
-    private let iv: Element
-    private var prev: Element?
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
 
-    init(iv: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+    init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
     }
@@ -33,16 +31,16 @@ struct CFBModeWorker: BlockModeWorker {
         guard let ciphertext = cipherOperation(prev ?? iv) else {
             return Array(plaintext)
         }
-        prev = xor(plaintext, ciphertext)
-        return prev ?? []
+        prev = xor(plaintext, ciphertext.slice)
+        return Array(prev ?? [])
     }
 
     mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
         guard let plaintext = cipherOperation(prev ?? iv) else {
             return Array(ciphertext)
         }
-        let result = xor(plaintext, ciphertext)
-        prev = Array(ciphertext)
+        let result: Array<UInt8> = xor(plaintext, ciphertext)
+        prev = ciphertext
         return result
     }
 }

+ 6 - 8
Sources/CryptoSwift/BlockMode/CTR.swift

@@ -18,13 +18,11 @@
 //
 
 struct CTRModeWorker: RandomAccessBlockModeWorker {
-    typealias Element = Array<UInt8>
-
     let cipherOperation: CipherOperationOnBlock
-    private let iv: Element
+    private let iv: ArraySlice<UInt8>
     var counter: UInt = 0
 
-    init(iv: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+    init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
     }
@@ -33,7 +31,7 @@ struct CTRModeWorker: RandomAccessBlockModeWorker {
         let nonce = buildNonce(iv, counter: UInt64(counter))
         counter = counter + 1
 
-        guard let ciphertext = cipherOperation(nonce) else {
+        guard let ciphertext = cipherOperation(nonce.slice) else {
             return Array(plaintext)
         }
 
@@ -45,10 +43,10 @@ struct CTRModeWorker: RandomAccessBlockModeWorker {
     }
 }
 
-private func buildNonce(_ iv: Array<UInt8>, counter: UInt64) -> Array<UInt8> {
+private func buildNonce(_ iv: ArraySlice<UInt8>, counter: UInt64) -> Array<UInt8> {
     let noncePartLen = AES.blockSize / 2
-    let noncePrefix = Array(iv[0..<noncePartLen])
-    let nonceSuffix = Array(iv[noncePartLen..<iv.count])
+    let noncePrefix = Array(iv[iv.startIndex..<iv.startIndex.advanced(by: noncePartLen)])
+    let nonceSuffix = Array(iv[iv.startIndex.advanced(by: noncePartLen)..<iv.startIndex.advanced(by: iv.count)])
     let c = UInt64(bytes: nonceSuffix) + counter
     return noncePrefix + c.bytes()
 }

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

@@ -21,12 +21,12 @@ struct ECBModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
     let cipherOperation: CipherOperationOnBlock
 
-    init(iv _: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+    init(cipherOperation: @escaping CipherOperationOnBlock) {
         self.cipherOperation = cipherOperation
     }
 
     mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
-        guard let ciphertext = cipherOperation(Array(plaintext)) else {
+        guard let ciphertext = cipherOperation(plaintext) else {
             return Array(plaintext)
         }
         return ciphertext

+ 6 - 8
Sources/CryptoSwift/BlockMode/OFB.swift

@@ -18,13 +18,11 @@
 //
 
 struct OFBModeWorker: BlockModeWorker {
-    typealias Element = Array<UInt8>
-
     let cipherOperation: CipherOperationOnBlock
-    private let iv: Element
-    private var prev: Element?
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
 
-    init(iv: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+    init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
     }
@@ -33,7 +31,7 @@ struct OFBModeWorker: BlockModeWorker {
         guard let ciphertext = cipherOperation(prev ?? iv) else {
             return Array(plaintext)
         }
-        prev = ciphertext
+        prev = ciphertext.slice
         return xor(plaintext, ciphertext)
     }
 
@@ -41,8 +39,8 @@ struct OFBModeWorker: BlockModeWorker {
         guard let decrypted = cipherOperation(prev ?? iv) else {
             return Array(ciphertext)
         }
-        let plaintext = xor(decrypted, ciphertext)
-        prev = decrypted
+        let plaintext: Array<UInt8> = xor(decrypted, ciphertext)
+        prev = decrypted.slice
         return plaintext
     }
 }

+ 7 - 9
Sources/CryptoSwift/BlockMode/PCBC.swift

@@ -18,13 +18,11 @@
 //
 
 struct PCBCModeWorker: BlockModeWorker {
-    typealias Element = Array<UInt8>
-
     let cipherOperation: CipherOperationOnBlock
-    private let iv: Element
-    private var prev: Element?
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
 
-    init(iv: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+    init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
     }
@@ -33,16 +31,16 @@ struct PCBCModeWorker: BlockModeWorker {
         guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
             return Array(plaintext)
         }
-        prev = xor(plaintext, ciphertext)
+        prev = xor(plaintext, ciphertext.slice)
         return ciphertext
     }
 
     mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
-        guard let plaintext = cipherOperation(Array(ciphertext)) else {
+        guard let plaintext = cipherOperation(ciphertext) else {
             return Array(ciphertext)
         }
-        let result = xor(prev ?? iv, plaintext)
-        prev = xor(plaintext, ciphertext)
+        let result: Array<UInt8> = xor(prev ?? iv, plaintext)
+        prev = xor(plaintext.slice, ciphertext)
         return result
     }
 }

+ 21 - 31
Sources/CryptoSwift/Blowfish.swift

@@ -30,21 +30,10 @@ public final class Blowfish {
     }
 
     public static let blockSize: Int = 8 // 64 bit
-    fileprivate let iv: Array<UInt8>
     fileprivate let blockMode: BlockMode
     fileprivate let padding: Padding
-    fileprivate lazy var decryptWorker: BlockModeWorker = {
-        switch self.blockMode {
-        case .CFB, .OFB, .CTR:
-            return self.blockMode.worker(self.iv, cipherOperation: self.encrypt)
-        default:
-            return self.blockMode.worker(self.iv, cipherOperation: self.decrypt)
-        }
-    }()
-
-    fileprivate lazy var encryptWorker: BlockModeWorker = {
-        self.blockMode.worker(self.iv, cipherOperation: self.encrypt)
-    }()
+    private var decryptWorker: BlockModeWorker!
+    private var encryptWorker: BlockModeWorker!
 
     private let N = 16 // rounds
     private var P: Array<UInt32>
@@ -323,8 +312,8 @@ public final class Blowfish {
         ],
     ]
 
-    public init(key: Array<UInt8>, iv: Array<UInt8>? = nil, blockMode: BlockMode = .CBC, padding: Padding) throws {
-        precondition(key.count >= 8 && key.count <= 56)
+    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
         self.padding = padding
@@ -332,18 +321,19 @@ public final class Blowfish {
         S = origS
         P = origP
 
-        if let iv = iv, !iv.isEmpty {
-            self.iv = iv
-        } else {
-            self.iv = Array<UInt8>(repeating: 0, count: Blowfish.blockSize)
-        }
+        expandKey(key: key)
+        try setupBlockModeWorkers()
+    }
 
-        if blockMode.options.contains(.initializationVectorRequired) && self.iv.count != Blowfish.blockSize {
-            assert(false, "Block size and Initialization Vector must be the same length!")
-            throw Error.invalidInitializationVector
-        }
+    private func setupBlockModeWorkers() throws {
+        encryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
 
-        expandKey(key: key)
+        switch blockMode {
+        case .CFB, .OFB, .CTR:
+            decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
+        default:
+            decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: decrypt)
+        }
     }
 
     private func reset() {
@@ -384,11 +374,11 @@ public final class Blowfish {
         }
     }
 
-    fileprivate func encrypt(block: Array<UInt8>) -> Array<UInt8>? {
+    fileprivate func encrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
         var result = Array<UInt8>()
 
-        var l = UInt32(bytes: block[0..<4])
-        var r = UInt32(bytes: block[4..<8])
+        var l = UInt32(bytes: block[block.startIndex..<block.startIndex.advanced(by: 4)])
+        var r = UInt32(bytes: block[block.startIndex.advanced(by: 4)..<block.startIndex.advanced(by: 8)])
 
         encryptBlowfishBlock(l: &l, r: &r)
 
@@ -413,11 +403,11 @@ public final class Blowfish {
         return result
     }
 
-    fileprivate func decrypt(block: Array<UInt8>) -> Array<UInt8>? {
+    fileprivate func decrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
         var result = Array<UInt8>()
 
-        var l = UInt32(bytes: block[0..<4])
-        var r = UInt32(bytes: block[4..<8])
+        var l = UInt32(bytes: block[block.startIndex..<block.startIndex.advanced(by: 4)])
+        var r = UInt32(bytes: block[block.startIndex.advanced(by: 4)..<block.startIndex.advanced(by: 8)])
 
         decryptBlowfishBlock(l: &l, r: &r)
 

+ 0 - 2
Sources/CryptoSwift/ChaCha20.swift

@@ -17,8 +17,6 @@
 //  https://tools.ietf.org/html/rfc7539
 //
 
-private typealias Key = SecureBytes
-
 public final class ChaCha20: BlockCipher {
 
     public enum Error: Swift.Error {

+ 15 - 48
Sources/CryptoSwift/Collection+Extension.swift

@@ -13,68 +13,35 @@
 //  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
-extension Collection where Self.Iterator.Element == UInt8, Self.Index == Int {
+extension Collection where Self.Element == UInt8, Self.Index == Int {
 
+    // Big endian order
     func toUInt32Array() -> Array<UInt32> {
-        let count = self.count
-        var result = Array<UInt32>()
-        result.reserveCapacity(16)
-        for idx in stride(from: startIndex, to: endIndex, by: 4) {
-            var val: UInt32 = 0
-            val |= count > 3 ? UInt32(self[idx.advanced(by: 3)]) << 24 : 0
-            val |= count > 2 ? UInt32(self[idx.advanced(by: 2)]) << 16 : 0
-            val |= count > 1 ? UInt32(self[idx.advanced(by: 1)]) << 8 : 0
-            val |= count > 0 ? UInt32(self[idx]) : 0
-            result.append(val)
+        if isEmpty {
+            return []
         }
 
-        return result
-    }
-
-    func toUInt64Array() -> Array<UInt64> {
-        let count = self.count
-        var result = Array<UInt64>()
-        result.reserveCapacity(32)
-        for idx in stride(from: startIndex, to: endIndex, by: 8) {
-            var val: UInt64 = 0
-            val |= count > 7 ? UInt64(self[idx.advanced(by: 7)]) << 56 : 0
-            val |= count > 6 ? UInt64(self[idx.advanced(by: 6)]) << 48 : 0
-            val |= count > 5 ? UInt64(self[idx.advanced(by: 5)]) << 40 : 0
-            val |= count > 4 ? UInt64(self[idx.advanced(by: 4)]) << 32 : 0
-            val |= count > 3 ? UInt64(self[idx.advanced(by: 3)]) << 24 : 0
-            val |= count > 2 ? UInt64(self[idx.advanced(by: 2)]) << 16 : 0
-            val |= count > 1 ? UInt64(self[idx.advanced(by: 1)]) << 8 : 0
-            val |= count > 0 ? UInt64(self[idx.advanced(by: 0)]) << 0 : 0
+        var result = Array<UInt32>(reserveCapacity: 16)
+        for idx in stride(from: startIndex, to: endIndex, by: 4) {
+            let val = UInt32(bytes: self, fromIndex: idx).bigEndian
             result.append(val)
         }
 
         return result
     }
 
-    /// Initialize integer from array of bytes. Caution: may be slow!
-    @available(*, deprecated: 0.6.0, message: "Dont use it. Too generic to be fast")
-    func toInteger<T>() -> T where T: FixedWidthInteger {
-        if count == 0 {
-            return 0
-        }
-
-        let size = MemoryLayout<T>.size
-        var bytes = reversed() // FIXME: check it this is equivalent of Array(...)
-        if bytes.count < size {
-            let paddingCount = size - bytes.count
-            if paddingCount > 0 {
-                bytes += Array<UInt8>(repeating: 0, count: paddingCount)
-            }
+    // Big endian order
+    func toUInt64Array() -> Array<UInt64> {
+        if isEmpty {
+            return []
         }
 
-        if size == 1 {
-            return T(truncatingIfNeeded: UInt64(bytes[0]))
+        var result = Array<UInt64>(reserveCapacity: 32)
+        for idx in stride(from: startIndex, to: endIndex, by: 8) {
+            let val = UInt64(bytes: self, fromIndex: idx).bigEndian
+            result.append(val)
         }
 
-        var result: T = 0
-        for byte in bytes.reversed() {
-            result = result << 8 | T(byte)
-        }
         return result
     }
 }

+ 2 - 2
Sources/CryptoSwift/Cryptors.swift

@@ -26,10 +26,10 @@ public protocol Cryptors: class {
     associatedtype DecryptorType: Updatable
 
     /// Cryptor suitable for encryption
-    func makeEncryptor() -> EncryptorType
+    func makeEncryptor() throws -> EncryptorType
 
     /// Cryptor suitable for decryption
-    func makeDecryptor() -> DecryptorType
+    func makeDecryptor() throws -> DecryptorType
 
     /// Generate array of random bytes. Helper function.
     static func randomIV(_ blockSize: Int) -> Array<UInt8>

+ 3 - 6
Sources/CryptoSwift/Foundation/AES+Foundation.swift

@@ -18,11 +18,8 @@ import Foundation
 
 extension AES {
 
-    public convenience init(key: String, iv: String, blockMode: BlockMode = .CBC, padding: Padding = .pkcs7) throws {
-        guard let kkey = key.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes, let iiv = iv.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes else {
-            throw Error.invalidKeyOrInitializationVector
-        }
-
-        try self.init(key: kkey, iv: iiv, blockMode: blockMode, padding: padding)
+    /// 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)
     }
 }

+ 3 - 6
Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift

@@ -18,11 +18,8 @@ import Foundation
 
 extension Blowfish {
 
-    public convenience init(key: String, iv: String, blockMode: BlockMode = .CBC, padding: Padding = .pkcs7) throws {
-        guard let kkey = key.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes, let iiv = iv.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes else {
-            throw Error.invalidKeyOrInitializationVector
-        }
-
-        try self.init(key: kkey, iv: iiv, blockMode: blockMode, padding: padding)
+    /// 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)
     }
 }

+ 1 - 4
Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift

@@ -19,9 +19,6 @@ import Foundation
 extension ChaCha20 {
 
     public convenience init(key: String, iv: String) throws {
-        guard let kkey = key.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes, let iiv = iv.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes else {
-            throw Error.invalidKeyOrInitializationVector
-        }
-        try self.init(key: kkey, iv: iiv)
+        try self.init(key: key.bytes, iv: iv.bytes)
     }
 }

+ 1 - 5
Sources/CryptoSwift/Foundation/HMAC+Foundation.swift

@@ -19,10 +19,6 @@ import Foundation
 extension HMAC {
 
     public convenience init(key: String, variant: HMAC.Variant = .md5) throws {
-        guard let kkey = key.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes else {
-            throw Error.invalidInput
-        }
-
-        self.init(key: kkey, variant: variant)
+        self.init(key: key.bytes, variant: variant)
     }
 }

+ 2 - 11
Sources/CryptoSwift/Foundation/Rabbit+Foundation.swift

@@ -19,19 +19,10 @@ import Foundation
 extension Rabbit {
 
     public convenience init(key: String) throws {
-        guard let kkey = key.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes else {
-            throw Error.invalidKeyOrInitializationVector
-        }
-        try self.init(key: kkey)
+        try self.init(key: key.bytes)
     }
 
     public convenience init(key: String, iv: String) throws {
-        guard let kkey = key.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes,
-            let iiv = iv.data(using: String.Encoding.utf8, allowLossyConversion: false)?.bytes
-        else {
-            throw Error.invalidKeyOrInitializationVector
-        }
-
-        try self.init(key: kkey, iv: iiv)
+        try self.init(key: key.bytes, iv: iv.bytes)
     }
 }

+ 1 - 1
Sources/CryptoSwift/Info.plist

@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.7.2</string>
+	<string>0.8.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 0 - 2
Sources/CryptoSwift/Rabbit.swift

@@ -14,8 +14,6 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
-private typealias Key = SecureBytes
-
 public final class Rabbit: BlockCipher {
 
     public enum Error: Swift.Error {

+ 20 - 30
Sources/CryptoSwift/SHA3.swift

@@ -36,59 +36,50 @@ public final class SHA3: DigestType {
 
     public let blockSize: Int
     public let digestLength: Int
+    public let markByte: UInt8
 
     fileprivate var accumulated = Array<UInt8>()
     fileprivate var processedBytesTotalCount: Int = 0
     fileprivate var accumulatedHash: Array<UInt64>
 
-    public enum Variant: RawRepresentable {
-        case sha224, sha256, sha384, sha512
+    public enum Variant {
+        case sha224, sha256, sha384, sha512, keccak224, keccak256, keccak384, keccak512
 
         var digestLength: Int {
             return 100 - (blockSize / 2)
         }
 
         var blockSize: Int {
-            return (1600 - rawValue * 2) / 8
+            return (1600 - outputLength * 2) / 8
         }
 
-        public typealias RawValue = Int
-        public var rawValue: RawValue {
+        var markByte: UInt8 {
             switch self {
-            case .sha224:
+            case .sha224, .sha256, .sha384, .sha512:
+                return 0x06 // 0x1F for SHAKE
+            case .keccak224, .keccak256, .keccak384, .keccak512:
+                return 0x01
+            }
+        }
+
+        public var outputLength: Int {
+            switch self {
+            case .sha224, .keccak224:
                 return 224
-            case .sha256:
+            case .sha256, .keccak256:
                 return 256
-            case .sha384:
+            case .sha384, .keccak384:
                 return 384
-            case .sha512:
+            case .sha512, .keccak512:
                 return 512
             }
         }
-
-        public init?(rawValue: RawValue) {
-            switch rawValue {
-            case 224:
-                self = .sha224
-                break
-            case 256:
-                self = .sha256
-                break
-            case 384:
-                self = .sha384
-                break
-            case 512:
-                self = .sha512
-                break
-            default:
-                return nil
-            }
-        }
     }
 
     public init(variant: SHA3.Variant) {
         blockSize = variant.blockSize
         digestLength = variant.digestLength
+        markByte = variant.markByte
         accumulatedHash = Array<UInt64>(repeating: 0, count: digestLength)
     }
 
@@ -272,8 +263,7 @@ extension SHA3: Updatable {
                 let q = (r / 8) - (accumulated.count % (r / 8))
                 accumulated += Array<UInt8>(repeating: 0, count: q)
             }
-
-            accumulated[markByteIndex] |= 0x06 // 0x1F for SHAKE
+            accumulated[markByteIndex] |= markByte
             accumulated[self.accumulated.count - 1] |= 0x80
         }
 

+ 2 - 0
Sources/CryptoSwift/SecureBytes.swift

@@ -20,6 +20,8 @@
     import Darwin
 #endif
 
+typealias Key = SecureBytes
+
 ///  Keeps bytes in memory. Because this is class, bytes are not copied
 ///  and memory area is locked as long as referenced, then unlocked on deinit
 final class SecureBytes {

+ 16 - 12
Sources/CryptoSwift/String+Extension.swift

@@ -17,52 +17,56 @@
 /** String extension */
 extension String {
 
+    public var bytes: Array<UInt8> {
+        return data(using: String.Encoding.utf8, allowLossyConversion: true)?.bytes ?? Array(utf8)
+    }
+
     public func md5() -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).md5().toHexString()
+        return bytes.md5().toHexString()
     }
 
     public func sha1() -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).sha1().toHexString()
+        return bytes.sha1().toHexString()
     }
 
     public func sha224() -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).sha224().toHexString()
+        return bytes.sha224().toHexString()
     }
 
     public func sha256() -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).sha256().toHexString()
+        return bytes.sha256().toHexString()
     }
 
     public func sha384() -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).sha384().toHexString()
+        return bytes.sha384().toHexString()
     }
 
     public func sha512() -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).sha512().toHexString()
+        return bytes.sha512().toHexString()
     }
 
     public func sha3(_ variant: SHA3.Variant) -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).sha3(variant).toHexString()
+        return bytes.sha3(variant).toHexString()
     }
 
     public func crc32(seed: UInt32? = nil, reflect: Bool = true) -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).crc32(seed: seed, reflect: reflect).bytes().toHexString()
+        return bytes.crc32(seed: seed, reflect: reflect).bytes().toHexString()
     }
 
     public func crc16(seed: UInt16? = nil) -> String {
-        return utf8.lazy.map({ $0 as UInt8 }).crc16(seed: seed).bytes().toHexString()
+        return bytes.crc16(seed: seed).bytes().toHexString()
     }
 
     /// - parameter cipher: Instance of `Cipher`
     /// - returns: hex string of bytes
     public func encrypt(cipher: Cipher) throws -> String {
-        return try Array(utf8).encrypt(cipher: cipher).toHexString()
+        return try bytes.encrypt(cipher: cipher).toHexString()
     }
 
     /// - parameter cipher: Instance of `Cipher`
     /// - returns: base64 encoded string of encrypted bytes
     public func encryptToBase64(cipher: Cipher) throws -> String? {
-        return try Array(utf8).encrypt(cipher: cipher).toBase64()
+        return try bytes.encrypt(cipher: cipher).toBase64()
     }
 
     // decrypt() does not make sense for String
@@ -70,6 +74,6 @@ extension String {
     /// - parameter authenticator: Instance of `Authenticator`
     /// - returns: hex string of string
     public func authenticate<A: Authenticator>(with authenticator: A) throws -> String {
-        return try Array(utf8).authenticate(with: authenticator).toHexString()
+        return try bytes.authenticate(with: authenticator).toHexString()
     }
 }

+ 11 - 4
Sources/CryptoSwift/UInt16+Extension.swift

@@ -18,14 +18,21 @@
 extension UInt16 {
 
     @_specialize(exported: true, where T == ArraySlice<UInt8>)
-    init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
+    init<T: Collection>(bytes: T) where T.Element == UInt8, T.Index == Int {
         self = UInt16(bytes: bytes, fromIndex: bytes.startIndex)
     }
 
     @_specialize(exported: true, where T == ArraySlice<UInt8>)
-    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Iterator.Element == UInt8, T.Index == Int {
-        let val0 = UInt16(bytes[index.advanced(by: 0)]) << 8
-        let val1 = UInt16(bytes[index.advanced(by: 1)])
+    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int {
+        if bytes.isEmpty {
+            self = 0
+            return
+        }
+
+        let count = bytes.count
+
+        let val0 = count > 0 ? UInt16(bytes[index.advanced(by: 0)]) << 8 : 0
+        let val1 = count > 1 ? UInt16(bytes[index.advanced(by: 1)]) : 0
 
         self = val0 | val1
     }

+ 13 - 6
Sources/CryptoSwift/UInt32+Extension.swift

@@ -27,16 +27,23 @@ extension UInt32: _UInt32Type {}
 extension UInt32 {
 
     @_specialize(exported: true, where T == ArraySlice<UInt8>)
-    init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.Index == Int {
+    init<T: Collection>(bytes: T) where T.Element == UInt8, T.Index == Int {
         self = UInt32(bytes: bytes, fromIndex: bytes.startIndex)
     }
 
     @_specialize(exported: true, where T == ArraySlice<UInt8>)
-    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Iterator.Element == UInt8, T.Index == Int {
-        let val0 = UInt32(bytes[index.advanced(by: 0)]) << 24
-        let val1 = UInt32(bytes[index.advanced(by: 1)]) << 16
-        let val2 = UInt32(bytes[index.advanced(by: 2)]) << 8
-        let val3 = UInt32(bytes[index.advanced(by: 3)])
+    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int {
+        if bytes.isEmpty {
+            self = 0
+            return
+        }
+
+        let count = bytes.count
+
+        let val0 = count > 0 ? UInt32(bytes[index.advanced(by: 0)]) << 24 : 0
+        let val1 = count > 1 ? UInt32(bytes[index.advanced(by: 1)]) << 16 : 0
+        let val2 = count > 2 ? UInt32(bytes[index.advanced(by: 2)]) << 8 : 0
+        let val3 = count > 3 ? UInt32(bytes[index.advanced(by: 3)]) : 0
 
         self = val0 | val1 | val2 | val3
     }

+ 17 - 10
Sources/CryptoSwift/UInt64+Extension.swift

@@ -18,20 +18,27 @@
 extension UInt64 {
 
     @_specialize(exported: true, where T == ArraySlice<UInt8>)
-    init<T: Collection>(bytes: T) where T.Iterator.Element == UInt8, T.IndexDistance == Int, T.Index == Int {
+    init<T: Collection>(bytes: T) where T.Element == UInt8, T.Index == Int {
         self = UInt64(bytes: bytes, fromIndex: bytes.startIndex)
     }
 
     @_specialize(exported: true, where T == ArraySlice<UInt8>)
-    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Iterator.Element == UInt8, T.IndexDistance == Int, T.Index == Int {
-        let val0 = UInt64(bytes[index.advanced(by: 0)]) << 56
-        let val1 = UInt64(bytes[index.advanced(by: 1)]) << 48
-        let val2 = UInt64(bytes[index.advanced(by: 2)]) << 40
-        let val3 = UInt64(bytes[index.advanced(by: 3)]) << 32
-        let val4 = UInt64(bytes[index.advanced(by: 4)]) << 24
-        let val5 = UInt64(bytes[index.advanced(by: 5)]) << 16
-        let val6 = UInt64(bytes[index.advanced(by: 6)]) << 8
-        let val7 = UInt64(bytes[index.advanced(by: 7)])
+    init<T: Collection>(bytes: T, fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int {
+        if bytes.isEmpty {
+            self = 0
+            return
+        }
+
+        let count = bytes.count
+
+        let val0 = count > 0 ? UInt64(bytes[index.advanced(by: 0)]) << 56 : 0
+        let val1 = count > 0 ? UInt64(bytes[index.advanced(by: 1)]) << 48 : 0
+        let val2 = count > 0 ? UInt64(bytes[index.advanced(by: 2)]) << 40 : 0
+        let val3 = count > 0 ? UInt64(bytes[index.advanced(by: 3)]) << 32 : 0
+        let val4 = count > 0 ? UInt64(bytes[index.advanced(by: 4)]) << 24 : 0
+        let val5 = count > 0 ? UInt64(bytes[index.advanced(by: 5)]) << 16 : 0
+        let val6 = count > 0 ? UInt64(bytes[index.advanced(by: 6)]) << 8 : 0
+        let val7 = count > 0 ? UInt64(bytes[index.advanced(by: 7)]) : 0
 
         self = val0 | val1 | val2 | val3 | val4 | val5 | val6 | val7
     }

+ 15 - 13
Sources/CryptoSwift/Utils.swift

@@ -60,24 +60,26 @@ func reversed(_ uint32: UInt32) -> UInt32 {
     return v
 }
 
-func xor(_ a: Array<UInt8>, _ b: Array<UInt8>) -> Array<UInt8> {
-    return xor(a.suffix(from: a.startIndex), b.suffix(from: b.startIndex))
+func xor<T, V>(_ left: T, _ right: V) -> ArraySlice<UInt8> where T: RandomAccessCollection, V: RandomAccessCollection, T.Element == UInt8, T.Index == Int, T.IndexDistance == Int, V.Element == UInt8, V.IndexDistance == Int, V.Index == Int {
+    return xor(left, right).slice
 }
 
-func xor(_ a: Array<UInt8>, _ b: ArraySlice<UInt8>) -> Array<UInt8> {
-    return xor(a.suffix(from: a.startIndex), b.suffix(from: b.startIndex))
-}
+func xor<T, V>(_ left: T, _ right: V) -> Array<UInt8> where T: RandomAccessCollection, V: RandomAccessCollection, T.Element == UInt8, T.Index == Int, T.IndexDistance == Int, V.Element == UInt8, V.IndexDistance == Int, V.Index == Int {
+    let length = Swift.min(left.count, right.count)
 
-func xor(_ a: ArraySlice<UInt8>, _ b: Array<UInt8>) -> Array<UInt8> {
-    return xor(a.suffix(from: a.startIndex), b.suffix(from: b.startIndex))
-}
+    let buf = UnsafeMutablePointer<UInt8>.allocate(capacity: length)
+    buf.initialize(to: 0, count: length)
+    defer {
+        buf.deinitialize()
+        buf.deallocate(capacity: length)
+    }
 
-func xor(_ a: ArraySlice<UInt8>, _ b: ArraySlice<UInt8>) -> Array<UInt8> {
-    var xored = Array<UInt8>(repeating: 0, count: min(a.count, b.count))
-    for i in 0..<xored.count {
-        xored[xored.startIndex.advanced(by: i)] = a[a.startIndex.advanced(by: i)] ^ b[b.startIndex.advanced(by: i)]
+    // xor
+    for i in 0..<length {
+        buf[i] = left[left.startIndex.advanced(by: i)] ^ right[right.startIndex.advanced(by: i)]
     }
-    return xored
+
+    return Array(UnsafeBufferPointer(start: buf, count: length))
 }
 
 /**

+ 59 - 51
Tests/CryptoSwiftTests/AESTests.swift

@@ -31,11 +31,15 @@ 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, iv: iv, blockMode: .CBC, padding: .noPadding)
-        let encrypted = try! aes.encrypt(input)
-        XCTAssertEqual(encrypted, expected, "encryption failed")
-        let decrypted = try! aes.decrypt(encrypted)
-        XCTAssertEqual(decrypted, input, "decryption failed")
+        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .noPadding)
+        do {
+            let encrypted = try aes.encrypt(input)
+            XCTAssertEqual(encrypted, expected, "encryption failed")
+            let decrypted = try aes.decrypt(encrypted)
+            XCTAssertEqual(decrypted, input, "decryption failed")
+        } catch {
+            XCTFail("\(error)")
+        }
     }
 
     func testAESEncrypt3() {
@@ -44,11 +48,15 @@ final class AESTests: XCTestCase {
         let input: Array<UInt8> = [0x62, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
         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, iv: iv, blockMode: .CBC, padding: .noPadding)
-        let encrypted = try! aes.encrypt(input)
-        XCTAssertEqual(encrypted, expected, "encryption failed")
-        let decrypted = try! aes.decrypt(encrypted)
-        XCTAssertEqual(decrypted, input, "decryption failed")
+        do {
+            let aes = try AES(key: key, iv: iv, padding: .noPadding)
+            let encrypted = try aes.encrypt(input)
+            XCTAssertEqual(encrypted, expected, "encryption failed")
+            let decrypted = try aes.decrypt(encrypted)
+            XCTAssertEqual(decrypted, input, "decryption failed")
+        } catch {
+            XCTFail("\(error)")
+        }
     }
 
     func testAESEncryptCBCNoPadding() {
@@ -57,7 +65,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, iv: iv, blockMode: .CBC, 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)
@@ -70,7 +78,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, iv: iv, blockMode: .CBC, 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)
@@ -82,10 +90,10 @@ 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, iv: iv, blockMode: .CBC, padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
 
         var ciphertext = Array<UInt8>()
-        var encryptor = aes.makeEncryptor()
+        var encryptor = try! aes.makeEncryptor()
         ciphertext += try! encryptor.update(withBytes: plaintext[0..<8])
         ciphertext += try! encryptor.update(withBytes: plaintext[8..<16])
         ciphertext += try! encryptor.update(withBytes: plaintext[16..<32])
@@ -97,12 +105,12 @@ 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: Array("passwordpassword".utf8), iv: Array("drowssapdrowssap".utf8))
-            var encryptor = aes.makeEncryptor()
+            let aes = try AES(key: "passwordpassword".bytes, blockMode: .CBC(iv: "drowssapdrowssap".bytes))
+            var encryptor = try! aes.makeEncryptor()
 
-            ciphertext += try encryptor.update(withBytes: Array(plaintext.utf8))
+            ciphertext += try encryptor.update(withBytes: plaintext.bytes)
             ciphertext += try encryptor.finish()
-            XCTAssertEqual(try aes.encrypt(Array(plaintext.utf8)), ciphertext, "encryption failed")
+            XCTAssertEqual(try aes.encrypt(plaintext.bytes), ciphertext, "encryption failed")
         } catch {
             XCTAssert(false, "\(error)")
         }
@@ -113,9 +121,9 @@ 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, iv: iv, blockMode: .CBC, padding: .pkcs7)
+        let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
         var plaintext = Array<UInt8>()
-        var decryptor = aes.makeDecryptor()
+        var decryptor = try! aes.makeDecryptor()
         plaintext += try! decryptor.update(withBytes: ciphertext[0..<8])
         plaintext += try! decryptor.update(withBytes: ciphertext[8..<16])
         plaintext += try! decryptor.update(withBytes: ciphertext[16..<32])
@@ -129,7 +137,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, iv: iv, blockMode: .CFB, 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)
@@ -141,8 +149,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, iv: iv, blockMode: .CFB).encrypt(plaintext)
-        let decrypted: Array<UInt8> = try! AES(key: key, iv: iv, blockMode: .CFB).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")
     }
 
@@ -152,7 +160,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, iv: iv, blockMode: .OFB, 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)
@@ -165,7 +173,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, iv: iv, blockMode: .OFB, 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)
@@ -178,7 +186,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, iv: iv, blockMode: .PCBC, 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")
@@ -192,7 +200,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, iv: iv, blockMode: .CTR, 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")
@@ -207,7 +215,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, iv: iv, blockMode: .CTR, padding: .zeroPadding)
+        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .zeroPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
         XCTAssertEqual(plaintext.count, 17)
@@ -220,7 +228,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, iv: iv, blockMode: .CTR, 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)
@@ -234,7 +242,7 @@ final class AESTests: XCTestCase {
         var plaintext: Array<UInt8> = Array<UInt8>(repeating: 0, count: 6000)
 
         for i in 0..<plaintext.count / 6 {
-            let s = Array(String(format: "%05d", i).utf8)
+            let s = String(format: "%05d", i).bytes
             plaintext[i * 6 + 0] = s[0]
             plaintext[i * 6 + 1] = s[1]
             plaintext[i * 6 + 2] = s[2]
@@ -243,10 +251,10 @@ final class AESTests: XCTestCase {
             plaintext[i * 6 + 5] = "|".utf8.first!
         }
 
-        let aes = try! AES(key: key, iv: iv, blockMode: .CTR, padding: .noPadding)
+        let aes = try! AES(key: key, blockMode: .CTR(iv: iv), padding: .noPadding)
         let encrypted = try! aes.encrypt(plaintext)
 
-        var decryptor = aes.makeDecryptor()
+        var decryptor = try! aes.makeDecryptor()
         decryptor.seek(to: 2)
         var part1 = try! decryptor.update(withBytes: Array(encrypted[2..<5]))
         part1 += try! decryptor.finish()
@@ -275,8 +283,8 @@ 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, iv: iv, blockMode: .CTR, padding: .noPadding)
-        var encryptor = aes.makeEncryptor()
+        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])
         encrypted += try! encryptor.update(withBytes: plaintext[5..<15])
@@ -284,7 +292,7 @@ final class AESTests: XCTestCase {
         encrypted += try! encryptor.finish()
         XCTAssertEqual(encrypted, expected, "encryption failed")
 
-        var decryptor = aes.makeDecryptor()
+        var decryptor = try! aes.makeDecryptor()
         var decrypted = Array<UInt8>()
         decrypted += try! decryptor.update(withBytes: expected[0..<5])
         decrypted += try! decryptor.update(withBytes: expected[5..<15])
@@ -299,8 +307,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, iv: iv, blockMode: .CBC, padding: .pkcs7)
-        let aes2 = try! AES(key: key2, iv: iv, blockMode: .CBC, 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")
@@ -314,7 +322,7 @@ final class AESTests: XCTestCase {
         let iv = "fedcba9876543210"
 
         do {
-            let aes = try AES(key: key, iv: iv, blockMode: .CBC, padding: .noPadding)
+            let aes = try AES(key: key, iv: iv, padding: .noPadding)
             let ciphertext = try aes.decrypt(Array<UInt8>(hex: encryptedValue))
             XCTAssertEqual(ciphertext, expected)
         } catch {
@@ -324,10 +332,10 @@ final class AESTests: XCTestCase {
 
     // https://github.com/krzyzanowskim/CryptoSwift/issues/394
     func testIssue394() {
-        let plaintext = Array("Nullam quis risus eget urna mollis ornare vel eu leo.".utf8)
-        let key = Array("passwordpassword".utf8).md5() // -md md5
-        let iv = Array("drowssapdrowssap".utf8) // -iv 64726f777373617064726f7773736170
-        let aes = try! AES(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7) // -aes-128-cbc
+        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 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
@@ -339,9 +347,9 @@ final class AESTests: XCTestCase {
     // https://github.com/krzyzanowskim/CryptoSwift/issues/411
     func testIssue411() {
         let ciphertext: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05, 0xaf, 0x46, 0x58, 0x2d, 0x66, 0x52, 0x10, 0xae, 0x86, 0xd3, 0x8e, 0x8f] // test
-        let key = Array("passwordpassword".utf8).md5() // -md md5
-        let iv = Array("drowssapdrowssap".utf8) // -iv 64726f777373617064726f7773736170
-        let aes = try! AES(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7) // -aes-128-cbc
+        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 plaintext = try! ciphertext.decrypt(cipher: aes)
         XCTAssertEqual("74657374", plaintext.toHexString())
     }
@@ -355,20 +363,20 @@ final class AESTests: 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, iv: iv, blockMode: .CBC, padding: .pkcs7)
-            measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true, for: { () -> Void in
+            let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+            measure {
                 _ = try! aes.encrypt(message)
-            })
+            }
         }
 
         func testAESDecryptPerformance() {
             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, iv: iv, blockMode: .CBC, padding: .pkcs7)
-            measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true, for: { () -> Void in
+            let aes = try! AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7)
+            measure {
                 _ = try! aes.decrypt(message)
-            })
+            }
         }
     }
 #endif

+ 5 - 5
Tests/CryptoSwiftTests/Access.swift

@@ -183,23 +183,23 @@ class Access: XCTestCase {
     func testAES() {
         do {
             let cipher = try AES(key: "secret0key000000", iv: "0123456789012345")
-            var encryptor = cipher.makeEncryptor()
+            var encryptor = try cipher.makeEncryptor()
             _ = try encryptor.update(withBytes: [1, 2, 3])
             _ = try encryptor.finish()
 
-            var decryptor = cipher.makeDecryptor()
+            var decryptor = try cipher.makeDecryptor()
             _ = try decryptor.update(withBytes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
             _ = try decryptor.finish()
 
             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], iv: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], blockMode: .CBC, 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
         } catch {
-            XCTFail(error.localizedDescription)
+            XCTFail("\(error)")
         }
     }
 
@@ -209,7 +209,7 @@ class Access: XCTestCase {
             let enc = try cipher.encrypt([1, 2, 3])
             _ = try cipher.decrypt(enc)
 
-            _ = try Blowfish(key: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], iv: [1, 2, 3, 4, 5, 6, 7, 8], blockMode: .CBC, padding: .noPadding)
+            _ = try Blowfish(key: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], iv: [1, 2, 3, 4, 5, 6, 7, 8], padding: .noPadding)
 
             _ = Blowfish.blockSize
         } catch {

+ 10 - 8
Tests/CryptoSwiftTests/BlowfishTests.swift

@@ -167,10 +167,10 @@ class BlowfishTests: XCTestCase {
     }
 
     func testCBCZeroPadding() {
-        let key = Array<UInt8>.init(hex: "0123456789ABCDEFF0E1D2C3B4A59687")
-        let iv = Array<UInt8>.init(hex: "FEDCBA9876543210")
-        let input = Array<UInt8>.init(hex: "37363534333231204E6F77206973207468652074696D6520666F722000")
-        XCTAssertEqual(try Blowfish(key: key, iv: iv, blockMode: .CBC, padding: .zeroPadding).encrypt(input), Array<UInt8>(hex: "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"))
+        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"))
     }
 
     func testEncryptDecrypt() {
@@ -179,7 +179,7 @@ class BlowfishTests: XCTestCase {
         let input = Array<UInt8>.init(hex: "37363534333231204E6F77206973207468652074696D6520666F722000")
 
         do {
-            let cipher = try Blowfish(key: key, iv: iv, blockMode: .CBC, 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)
@@ -191,9 +191,11 @@ class BlowfishTests: XCTestCase {
     // https://github.com/krzyzanowskim/CryptoSwift/issues/415
     func testDecryptCFB415() {
         do {
-            let plaintext = Array("secret12".utf8)
-            let encrypted = try Blowfish(key: "passwordpassword", iv: "12345678", blockMode: .CFB, padding: .noPadding).encrypt(plaintext)
-            let decrypted = try Blowfish(key: "passwordpassword", iv: "12345678", blockMode: .CFB, padding: .noPadding).decrypt(encrypted)
+            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)
             XCTAssertEqual(plaintext, decrypted)
         } catch {
             XCTFail(error.localizedDescription)

+ 3 - 3
Tests/CryptoSwiftTests/ChaCha20Tests.swift

@@ -38,7 +38,7 @@ final class ChaCha20Tests: XCTestCase {
 
         for idx in 0..<keys.count {
             let expectedHex = expectedHexes[idx]
-            let message = Array<UInt8>(repeating: 0, count: (expectedHex.characters.count / 2))
+            let message = Array<UInt8>(repeating: 0, count: (expectedHex.count / 2))
 
             do {
                 let encrypted = try message.encrypt(cipher: ChaCha20(key: keys[idx], iv: ivs[idx]))
@@ -82,7 +82,7 @@ final class ChaCha20Tests: XCTestCase {
         let key: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f]
         let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
         let expectedHex = "F798A189F195E66982105FFB640BB7757F579DA31602FC93EC01AC56F85AC3C134A4547B733B46413042C9440049176905D3BE59EA1C53F15916155C2BE8241A38008B9A26BC35941E2444177C8ADE6689DE95264986D95889FB60E84629C9BD9A5ACB1CC118BE563EB9B3A4A472F82E09A7E778492B562EF7130E88DFE031C79DB9D4F7C7A899151B9A475032B63FC385245FE054E3DD5A97A5F576FE064025D3CE042C566AB2C507B138DB853E3D6959660996546CC9C4A6EAFDC777C040D70EAF46F76DAD3979E5C5360C3317166A1C894C94A371876A94DF7628FE4EAAF2CCB27D5AAAE0AD7AD0F9D4B6AD3B54098746D4524D38407A6DEB3AB78FAB78C9"
-        let plaintext: Array<UInt8> = Array<UInt8>(repeating: 0, count: (expectedHex.characters.count / 2))
+        let plaintext: Array<UInt8> = Array<UInt8>(repeating: 0, count: (expectedHex.count / 2))
 
         do {
             let cipher = try ChaCha20(key: key, iv: iv)
@@ -108,7 +108,7 @@ final class ChaCha20Tests: XCTestCase {
         func testChaCha20Performance() {
             let key: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f]
             let iv: Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
-            let message = Array<UInt8>(repeating: 7, count: 1024)
+            let message = Array<UInt8>(repeating: 7, count: 1024 * 1024)
             measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true, for: { () -> Void in
                 do {
                     _ = try ChaCha20(key: key, iv: iv).encrypt(message)

+ 20 - 0
Tests/CryptoSwiftTests/DigestTests.swift

@@ -73,26 +73,46 @@ final class DigestTests: XCTestCase {
         XCTAssertEqual(SHA3(variant: .sha256).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532")
         XCTAssertEqual(SHA3(variant: .sha384).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25")
         XCTAssertEqual(SHA3(variant: .sha512).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0")
+        XCTAssertEqual(SHA3(variant: .keccak224).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "c30411768506ebe1c2871b1ee2e87d38df342317300a9b97a95ec6a8")
+        XCTAssertEqual(SHA3(variant: .keccak256).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
+        XCTAssertEqual(SHA3(variant: .keccak384).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "f7df1165f033337be098e7d288ad6a2f74409d7a60b49c36642218de161b1f99f8c681e4afaf31a34db29fb763e3c28e")
+        XCTAssertEqual(SHA3(variant: .keccak512).calculate(for: Array<UInt8>(hex: "616263")).toHexString(), "18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96")
 
         XCTAssertEqual(SHA3(variant: .sha224).calculate(for: Array<UInt8>(hex: "")).toHexString(), "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7")
         XCTAssertEqual(SHA3(variant: .sha256).calculate(for: Array<UInt8>(hex: "")).toHexString(), "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
         XCTAssertEqual(SHA3(variant: .sha384).calculate(for: Array<UInt8>(hex: "")).toHexString(), "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004")
         XCTAssertEqual(SHA3(variant: .sha512).calculate(for: Array<UInt8>(hex: "")).toHexString(), "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")
+        XCTAssertEqual(SHA3(variant: .keccak224).calculate(for: Array<UInt8>(hex: "")).toHexString(), "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd")
+        XCTAssertEqual(SHA3(variant: .keccak256).calculate(for: Array<UInt8>(hex: "")).toHexString(), "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
+        XCTAssertEqual(SHA3(variant: .keccak384).calculate(for: Array<UInt8>(hex: "")).toHexString(), "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff")
+        XCTAssertEqual(SHA3(variant: .keccak512).calculate(for: Array<UInt8>(hex: "")).toHexString(), "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e")
 
         XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.sha224), "8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33")
         XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.sha256), "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376")
         XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.sha384), "991c665755eb3a4b6bbdfb75c78a492e8c56a22c5c4d7e429bfdbc32b9d4ad5aa04a1f076e62fea19eef51acd0657c22")
         XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.sha512), "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e")
+        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.keccak224), "e51faa2b4655150b931ee8d700dc202f763ca5f962c529eae55012b6")
+        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.keccak256), "45d3b367a6904e6e8d502ee04999a7c27647f91fa845d456525fd352ae3d7371")
+        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.keccak384), "b41e8896428f1bcbb51e17abd6acc98052a3502e0d5bf7fa1af949b4d3c855e7c4dc2c390326b3f3e74c7b1e2b9a3657")
+        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha3(.keccak512), "6aa6d3669597df6d5a007b00d09c20795b5c4218234e1698a944757a488ecdc09965435d97ca32c3cfed7201ff30e070cd947f1fc12b9d9214c467d342bcba5d")
 
         XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.sha224), "543e6868e1666c1a643630df77367ae5a62a85070a51c14cbf665cbc")
         XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.sha256), "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18")
         XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.sha384), "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7")
         XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.sha512), "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185")
+        XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.keccak224), "344298994b1b06873eae2ce739c425c47291a2e24189e01b524f88dc")
+        XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.keccak256), "f519747ed599024f3882238e5ab43960132572b7345fbeb9a90769dafd21ad67")
+        XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.keccak384), "cc063f34685135368b34f7449108f6d10fa727b09d696ec5331771da46a923b6c34dbd1d4f77e595689c1f3800681c28")
+        XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha3(.keccak512), "ac2fb35251825d3aa48468a9948c0a91b8256f6d97d8fa4160faff2dd9dfcc24f3f1db7a983dad13d53439ccac0b37e24037e7b95f80f59f37a2f683c4ba4682")
 
         XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.sha224), Array<UInt8>(hex: "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
         XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.sha256), Array<UInt8>(hex: "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
         XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.sha384), Array<UInt8>(hex: "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
         XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.sha512), Array<UInt8>(hex: "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
+        XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.keccak224), Array<UInt8>(hex: "19f9167be2a04c43abd0ed554788101b9c339031acc8e1468531303f"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
+        XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.keccak256), Array<UInt8>(hex: "fadae6b49f129bbb812be8407b7b2894f34aecf6dbd1f9b0f0c7e9853098fc96"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
+        XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.keccak384), Array<UInt8>(hex: "0c8324e1ebc182822c5e2a086cac07c2fe00e3bce61d01ba8ad6b71780e2dec5fb89e5ae90cb593e57bc6258fdd94e17"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
+        XCTAssertEqual(Array<UInt8>(repeating: 0x61, count: 1_000_000).sha3(.keccak512), Array<UInt8>(hex: "5cf53f2e556be5a624425ede23d0e8b2c7814b4ba0e4e09cbbf3c2fac7056f61e048fc341262875ebc58a5183fea651447124370c1ebf4d6c89bc9a7731063bb"), "One million (1,000,000) repetitions of the character 'a' (0x61)")
     }
 
     func testMD5Data() {

+ 5 - 16
Tests/CryptoSwiftTests/ExtensionsTest.swift

@@ -25,12 +25,12 @@ final class ExtensionsTest: XCTestCase {
     }
 
     func testToUInt32Array() {
-        let chunk: ArraySlice<UInt8> = [1, 1, 1, 7, 2, 3, 4, 5]
+        let chunk: ArraySlice<UInt8> = [0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1]
         let result = chunk.toUInt32Array()
 
         XCTAssert(result.count == 2, "Invalid conversion")
-        XCTAssert(result[0] == 117_506_305, "Invalid conversion")
-        XCTAssert(result[1] == 84_148_994, "Invalid conversion")
+        XCTAssertEqual(result[0], 0x5060708)
+        XCTAssertEqual(result[1], 0x1020304)
     }
 
     func testDataInit() {
@@ -49,7 +49,7 @@ final class ExtensionsTest: XCTestCase {
 
     func testEmptyStringEncrypt() {
         do {
-            let cipher = try AES(key: Array("secret0key000000".utf8).md5(), iv: Array("secret0key000000".utf8).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)
@@ -81,15 +81,6 @@ final class ExtensionsTest: XCTestCase {
 
     extension ExtensionsTest {
 
-        func testArrayChunksPerformance() {
-            measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: false, for: { () -> Void in
-                let message = Array<UInt8>(repeating: 7, count: 1024 * 1024)
-                self.startMeasuring()
-                _ = message.chunks(size: AES.blockSize)
-                self.stopMeasuring()
-            })
-        }
-
         func testArrayInitHexPerformance() {
             var str = "b1b2b3b3b3b3b3b3b1b2b3b3b3b3b3b3"
             for _ in 0...12 {
@@ -99,7 +90,6 @@ final class ExtensionsTest: XCTestCase {
                 _ = Array<UInt8>(hex: str)
             }
         }
-
     }
 #endif
 
@@ -118,8 +108,7 @@ extension ExtensionsTest {
 
         #if !CI
             tests += [
-                ("testArrayChunksPerformance", testArrayChunksPerformance),
-                ("testArrayInitHexPerformance", testArrayInitHexPerformance)
+                ("testArrayInitHexPerformance", testArrayInitHexPerformance),
             ]
         #endif
         return tests

+ 7 - 7
Tests/CryptoSwiftTests/PBKDF.swift

@@ -46,19 +46,19 @@ class PBKDF: XCTestCase {
     }
 
     func testPBKDF2Length() {
-        let password: Array<UInt8> = Array("s33krit".utf8)
-        let salt: Array<UInt8> = Array("nacl".utf8)
+        let password: Array<UInt8> = "s33krit".bytes
+        let salt: Array<UInt8> = "nacl".bytes
         let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 2, keyLength: 8, variant: .sha1).calculate()
-        XCTAssert(value.toHexString() == "a53cf3df485e5cd9", "PBKDF2 fail")
+        XCTAssertEqual(value.toHexString(), "a53cf3df485e5cd9")
     }
 
     #if !CI
         func testPerformance() {
-            let password: Array<UInt8> = Array("s33krit".utf8)
-            let salt: Array<UInt8> = Array("nacl".utf8)
-            measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true, for: { () -> Void in
+            let password: Array<UInt8> = "s33krit".bytes
+            let salt: Array<UInt8> = "nacl".bytes
+            measure {
                 _ = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 65536, keyLength: 32, variant: .sha1).calculate()
-            })
+            }
         }
     #endif
 

+ 3 - 5
Tests/CryptoSwiftTests/RabbitTests.swift

@@ -117,11 +117,9 @@ class RabbitTests: XCTestCase {
             let key: Array<UInt8> = Array<UInt8>(repeating: 0, count: Rabbit.keySize)
             let iv: Array<UInt8> = Array<UInt8>(repeating: 0, count: Rabbit.ivSize)
             let message = Array<UInt8>(repeating: 7, count: (1024 * 1024) * 1)
-            measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true, for: { () -> Void in
-                let encrypted = try! Rabbit(key: key, iv: iv).encrypt(message)
-                self.stopMeasuring()
-                XCTAssert(!encrypted.isEmpty, "not encrypted")
-            })
+            measure {
+                _ = try! Rabbit(key: key, iv: iv).encrypt(message)
+            }
         }
     }
 #endif

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor