Marcin Krzyżanowski 10 жил өмнө
parent
commit
30a1e3d721
38 өөрчлөгдсөн 796 нэмэгдсэн , 547 устгасан
  1. 1 1
      CryptoSwift.podspec
  2. 18 16
      CryptoSwift.xcodeproj/project.pbxproj
  3. 22 0
      CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/9396A4FE-F8F7-4542-8F75-DE77E1FEBEB9.plist
  4. 40 0
      CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/Info.plist
  5. 15 1
      CryptoSwift.xcodeproj/xcshareddata/xcschemes/CryptoSwift.xcscheme
  6. 116 117
      CryptoSwift/AES.swift
  7. 4 3
      CryptoSwift/ArrayExtension.swift
  8. 3 3
      CryptoSwift/Authenticator.swift
  9. 48 28
      CryptoSwift/ChaCha20.swift
  10. 10 21
      CryptoSwift/Cipher.swift
  11. 75 124
      CryptoSwift/CipherBlockMode.swift
  12. 9 6
      CryptoSwift/Generics.swift
  13. 18 10
      CryptoSwift/HMAC.swift
  14. 4 4
      CryptoSwift/Hash.swift
  15. 18 7
      CryptoSwift/HashBase.swift
  16. 1 1
      CryptoSwift/IntExtension.swift
  17. 6 6
      CryptoSwift/MD5.swift
  18. 13 4
      CryptoSwift/NSDataExtension.swift
  19. 52 0
      CryptoSwift/PKCS5.swift
  20. 20 19
      CryptoSwift/PKCS7.swift
  21. 14 0
      CryptoSwift/Padding.swift
  22. 0 32
      CryptoSwift/PaddingMode.swift
  23. 0 7
      CryptoSwift/Playground/CryptoPlayground.playground/contents.xcplayground
  24. 0 7
      CryptoSwift/Playground/CryptoPlayground.playground/section-1.swift
  25. 0 7
      CryptoSwift/Poly1305.swift
  26. 9 5
      CryptoSwift/SHA1.swift
  27. 61 18
      CryptoSwift/SHA2.swift
  28. 1 1
      CryptoSwift/UInt32Extension.swift
  29. 1 1
      CryptoSwift/UInt64Extension.swift
  30. 23 0
      CryptoSwift/Utils.swift
  31. 81 30
      CryptoSwiftTests/AESTests.swift
  32. 20 11
      CryptoSwiftTests/ChaCha20Tests.swift
  33. 10 0
      CryptoSwiftTests/ExtensionsTest.swift
  34. 24 6
      CryptoSwiftTests/HMACTests.swift
  35. 8 12
      CryptoSwiftTests/HashTests.swift
  36. 12 12
      CryptoSwiftTests/PaddingTests.swift
  37. 10 5
      CryptoSwiftTests/Poly1305Tests.swift
  38. 29 22
      README.md

+ 1 - 1
CryptoSwift.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name         = "CryptoSwift"
-  s.version      = "0.0.8"
+  s.version      = "0.0.9"
   s.summary      = "Cryptography in Swift. SHA, MD5, CRC, Poly1305, HMAC, ChaCha20, AES."
   s.description  = "Cryptography functions and helpers for Swift implemented in Swift. SHA, MD5, CRC, Poly1305, HMAC, ChaCha20, AES."
   s.homepage     = "https://github.com/krzyzanowskim/CryptoSwift"

+ 18 - 16
CryptoSwift.xcodeproj/project.pbxproj

@@ -14,18 +14,18 @@
 		751C5C3D19B26B000094C75D /* Poly1305.swift in Sources */ = {isa = PBXBuildFile; fileRef = 751C5C3C19B26B000094C75D /* Poly1305.swift */; };
 		752DEF7719693EA000E17557 /* NSDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEF7619693EA000E17557 /* NSDataExtension.swift */; };
 		752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752E087A199FF27C005B0EA0 /* SHA1.swift */; };
+		753988211AB72E4100FAF3FC /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C8FEC19979F94005AD904 /* ArrayExtension.swift */; };
 		75445821196AA2A5002FF20E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75445820196AA2A5002FF20E /* Security.framework */; settings = {ATTRIBUTES = (Required, ); }; };
 		7547195119931802002FA5F1 /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7547195019931802002FA5F1 /* IntExtension.swift */; };
 		754BE45B19693E190098E6F3 /* CryptoSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 754BE45A19693E190098E6F3 /* CryptoSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		754BE46819693E190098E6F3 /* HashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754BE46719693E190098E6F3 /* HashTests.swift */; };
+		754C30B71AA13BC000E6FFA4 /* PKCS7.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C30B61AA13BC000E6FFA4 /* PKCS7.swift */; };
 		754C8FED19979F94005AD904 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C8FEC19979F94005AD904 /* ArrayExtension.swift */; };
-		754DD76E19A149AF00E52288 /* CryptoHashBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754DD76D19A149AF00E52288 /* CryptoHashBase.swift */; };
+		754DD76E19A149AF00E52288 /* HashBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754DD76D19A149AF00E52288 /* HashBase.swift */; };
 		755111E819B7B7DF00C2AD86 /* Authenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755111E719B7B7DF00C2AD86 /* Authenticator.swift */; };
 		7552614E1993051E000D2B20 /* Hash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7552614D1993051E000D2B20 /* Hash.swift */; };
 		755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755FB1D9199E347D00475437 /* ExtensionsTest.swift */; };
 		7563B2E819B14D4300B152CD /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7563B2E719B14D4300B152CD /* Cipher.swift */; };
-		757DA24F1A4E59F2002BA3EF /* PKCS7.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA24E1A4E59F2002BA3EF /* PKCS7.swift */; };
-		757DA2511A4E5E95002BA3EF /* PaddingMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2501A4E5E95002BA3EF /* PaddingMode.swift */; };
 		757DA2531A4ED0A4002BA3EF /* PaddingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */; };
 		757DA2551A4ED408002BA3EF /* AESTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2541A4ED408002BA3EF /* AESTests.swift */; };
 		757DA2571A4ED47B002BA3EF /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2561A4ED47B002BA3EF /* Helpers.swift */; };
@@ -36,11 +36,12 @@
 		758A94291A65C67400E46135 /* HMACTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758A94271A65C59200E46135 /* HMACTests.swift */; };
 		758C764119B61AE500653BC6 /* Generics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758C764019B61AE500653BC6 /* Generics.swift */; };
 		758C764319B61DE900653BC6 /* UInt16Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758C764219B61DE900653BC6 /* UInt16Extension.swift */; };
-		758F3F761992E57D0014BBDA /* Playground in Resources */ = {isa = PBXBuildFile; fileRef = 758F3F751992E57D0014BBDA /* Playground */; };
 		758F3F781992F6CE0014BBDA /* UInt8Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758F3F771992F6CE0014BBDA /* UInt8Extension.swift */; };
 		7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7599C9C5199EA28700A3988B /* StringExtension.swift */; };
 		759D481119B517BC005FF7FC /* BitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759D481019B517BC005FF7FC /* BitExtension.swift */; };
+		75A663A61AA0CAD00052110B /* Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75A663A51AA0CAD00052110B /* Padding.swift */; };
 		75A74B271A1FF6B2004419F1 /* AES.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75A74B261A1FF6B2004419F1 /* AES.swift */; };
+		75B0A5701AB1A1BB000BD8D2 /* PKCS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75B0A56F1AB1A1BB000BD8D2 /* PKCS5.swift */; };
 		75B601EB197D6A6C0009B53D /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 754BE45519693E190098E6F3 /* CryptoSwift.framework */; };
 		75BC3AE31A4E412000ADF343 /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */; };
 		75D94E2419B60C08007CB2A4 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D94E2319B60C08007CB2A4 /* Operators.swift */; };
@@ -129,15 +130,14 @@
 		754BE46019693E190098E6F3 /* CryptoSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CryptoSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		754BE46619693E190098E6F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		754BE46719693E190098E6F3 /* HashTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashTests.swift; sourceTree = "<group>"; };
+		754C30B61AA13BC000E6FFA4 /* PKCS7.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PKCS7.swift; sourceTree = "<group>"; };
 		754C8FEC19979F94005AD904 /* ArrayExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = "<group>"; };
-		754DD76D19A149AF00E52288 /* CryptoHashBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CryptoHashBase.swift; sourceTree = "<group>"; };
+		754DD76D19A149AF00E52288 /* HashBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HashBase.swift; sourceTree = "<group>"; };
 		755111E719B7B7DF00C2AD86 /* Authenticator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authenticator.swift; sourceTree = "<group>"; };
 		7552614D1993051E000D2B20 /* Hash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Hash.swift; sourceTree = "<group>"; };
 		755FB1D9199E347D00475437 /* ExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionsTest.swift; sourceTree = "<group>"; };
 		7563B2E719B14D4300B152CD /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		756BFDCA1A82B87300B9D9A4 /* Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bridging.h; sourceTree = "<group>"; };
-		757DA24E1A4E59F2002BA3EF /* PKCS7.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PKCS7.swift; sourceTree = "<group>"; };
-		757DA2501A4E5E95002BA3EF /* PaddingMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingMode.swift; sourceTree = "<group>"; };
 		757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingTests.swift; sourceTree = "<group>"; };
 		757DA2541A4ED408002BA3EF /* AESTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AESTests.swift; sourceTree = "<group>"; };
 		757DA2561A4ED47B002BA3EF /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
@@ -147,11 +147,12 @@
 		758A94271A65C59200E46135 /* HMACTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMACTests.swift; sourceTree = "<group>"; };
 		758C764019B61AE500653BC6 /* Generics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Generics.swift; sourceTree = "<group>"; };
 		758C764219B61DE900653BC6 /* UInt16Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UInt16Extension.swift; sourceTree = "<group>"; };
-		758F3F751992E57D0014BBDA /* Playground */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Playground; path = CryptoSwift/Playground; sourceTree = "<group>"; };
 		758F3F771992F6CE0014BBDA /* UInt8Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UInt8Extension.swift; sourceTree = "<group>"; };
 		7599C9C5199EA28700A3988B /* StringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = "<group>"; };
 		759D481019B517BC005FF7FC /* BitExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BitExtension.swift; sourceTree = "<group>"; };
+		75A663A51AA0CAD00052110B /* Padding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Padding.swift; sourceTree = "<group>"; };
 		75A74B261A1FF6B2004419F1 /* AES.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AES.swift; sourceTree = "<group>"; };
+		75B0A56F1AB1A1BB000BD8D2 /* PKCS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PKCS5.swift; sourceTree = "<group>"; };
 		75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherBlockMode.swift; sourceTree = "<group>"; };
 		75D94E2319B60C08007CB2A4 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
 		75D94E2519B60C4F007CB2A4 /* UInt32Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UInt32Extension.swift; sourceTree = "<group>"; };
@@ -190,7 +191,6 @@
 		754BE44B19693E190098E6F3 = {
 			isa = PBXGroup;
 			children = (
-				758F3F751992E57D0014BBDA /* Playground */,
 				754BE45719693E190098E6F3 /* CryptoSwift */,
 				754BE46419693E190098E6F3 /* CryptoSwiftTests */,
 				754BE45619693E190098E6F3 /* Products */,
@@ -214,9 +214,11 @@
 				7552614D1993051E000D2B20 /* Hash.swift */,
 				7563B2E719B14D4300B152CD /* Cipher.swift */,
 				75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */,
-				757DA2501A4E5E95002BA3EF /* PaddingMode.swift */,
+				75A663A51AA0CAD00052110B /* Padding.swift */,
+				75B0A56F1AB1A1BB000BD8D2 /* PKCS5.swift */,
+				754C30B61AA13BC000E6FFA4 /* PKCS7.swift */,
 				755111E719B7B7DF00C2AD86 /* Authenticator.swift */,
-				754DD76D19A149AF00E52288 /* CryptoHashBase.swift */,
+				754DD76D19A149AF00E52288 /* HashBase.swift */,
 				750A545F1992D2680017DA75 /* MD5.swift */,
 				752E087A199FF27C005B0EA0 /* SHA1.swift */,
 				75153D4119AA3C7900750381 /* SHA2.swift */,
@@ -225,7 +227,6 @@
 				751C5C3C19B26B000094C75D /* Poly1305.swift */,
 				758A94251A65AEB100E46135 /* HMAC.swift */,
 				75A74B261A1FF6B2004419F1 /* AES.swift */,
-				757DA24E1A4E59F2002BA3EF /* PKCS7.swift */,
 				759D481019B517BC005FF7FC /* BitExtension.swift */,
 				758F3F771992F6CE0014BBDA /* UInt8Extension.swift */,
 				7547195019931802002FA5F1 /* IntExtension.swift */,
@@ -374,7 +375,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				758F3F761992E57D0014BBDA /* Playground in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -395,13 +395,13 @@
 			files = (
 				75D94E2819B60DDE007CB2A4 /* UInt64Extension.swift in Sources */,
 				751C5C3D19B26B000094C75D /* Poly1305.swift in Sources */,
-				757DA2511A4E5E95002BA3EF /* PaddingMode.swift in Sources */,
 				7552614E1993051E000D2B20 /* Hash.swift in Sources */,
 				75BC3AE31A4E412000ADF343 /* CipherBlockMode.swift in Sources */,
 				7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */,
 				7563B2E819B14D4300B152CD /* Cipher.swift in Sources */,
 				752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */,
 				75EB380119ABDD710002375A /* ChaCha20.swift in Sources */,
+				75A663A61AA0CAD00052110B /* Padding.swift in Sources */,
 				750A54601992D2680017DA75 /* MD5.swift in Sources */,
 				75164E4919AD30AC00737F30 /* Utils.swift in Sources */,
 				758A94261A65AEB100E46135 /* HMAC.swift in Sources */,
@@ -411,12 +411,13 @@
 				7547195119931802002FA5F1 /* IntExtension.swift in Sources */,
 				758C764319B61DE900653BC6 /* UInt16Extension.swift in Sources */,
 				75D94E2419B60C08007CB2A4 /* Operators.swift in Sources */,
+				75B0A5701AB1A1BB000BD8D2 /* PKCS5.swift in Sources */,
 				757EF7F519AAA82400586276 /* CRC.swift in Sources */,
 				75D94E2619B60C4F007CB2A4 /* UInt32Extension.swift in Sources */,
 				75A74B271A1FF6B2004419F1 /* AES.swift in Sources */,
+				754C30B71AA13BC000E6FFA4 /* PKCS7.swift in Sources */,
 				755111E819B7B7DF00C2AD86 /* Authenticator.swift in Sources */,
-				757DA24F1A4E59F2002BA3EF /* PKCS7.swift in Sources */,
-				754DD76E19A149AF00E52288 /* CryptoHashBase.swift in Sources */,
+				754DD76E19A149AF00E52288 /* HashBase.swift in Sources */,
 				758C764119B61AE500653BC6 /* Generics.swift in Sources */,
 				758F3F781992F6CE0014BBDA /* UInt8Extension.swift in Sources */,
 				75153D4219AA3C7900750381 /* SHA2.swift in Sources */,
@@ -430,6 +431,7 @@
 				758A94291A65C67400E46135 /* HMACTests.swift in Sources */,
 				75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */,
 				757DA2571A4ED47B002BA3EF /* Helpers.swift in Sources */,
+				753988211AB72E4100FAF3FC /* ArrayExtension.swift in Sources */,
 				754BE46819693E190098E6F3 /* HashTests.swift in Sources */,
 				757DA2591A4ED4D7002BA3EF /* ChaCha20Tests.swift in Sources */,
 				755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */,

+ 22 - 0
CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/9396A4FE-F8F7-4542-8F75-DE77E1FEBEB9.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>classNames</key>
+	<dict>
+		<key>ChaCha20Tests</key>
+		<dict>
+			<key>testChaCha20Performance()</key>
+			<dict>
+				<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+				<dict>
+					<key>baselineAverage</key>
+					<real>0.15</real>
+					<key>baselineIntegrationDisplayName</key>
+					<string>Local Baseline</string>
+				</dict>
+			</dict>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 40 - 0
CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/Info.plist

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>runDestinationsByUUID</key>
+	<dict>
+		<key>9396A4FE-F8F7-4542-8F75-DE77E1FEBEB9</key>
+		<dict>
+			<key>localComputer</key>
+			<dict>
+				<key>busSpeedInMHz</key>
+				<integer>100</integer>
+				<key>cpuCount</key>
+				<integer>1</integer>
+				<key>cpuKind</key>
+				<string>Intel Core i7</string>
+				<key>cpuSpeedInMHz</key>
+				<integer>1700</integer>
+				<key>logicalCPUCoresPerPackage</key>
+				<integer>4</integer>
+				<key>modelCode</key>
+				<string>MacBookAir6,2</string>
+				<key>physicalCPUCoresPerPackage</key>
+				<integer>2</integer>
+				<key>platformIdentifier</key>
+				<string>com.apple.platform.macosx</string>
+			</dict>
+			<key>targetArchitecture</key>
+			<string>x86_64</string>
+			<key>targetDevice</key>
+			<dict>
+				<key>modelCode</key>
+				<string>iPhone7,2</string>
+				<key>platformIdentifier</key>
+				<string>com.apple.platform.iphonesimulator</string>
+			</dict>
+		</dict>
+	</dict>
+</dict>
+</plist>

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

@@ -3,7 +3,7 @@
    LastUpgradeVersion = "0610"
    version = "1.3">
    <BuildAction
-      parallelizeBuildables = "YES"
+      parallelizeBuildables = "NO"
       buildImplicitDependencies = "YES">
       <BuildActionEntries>
          <BuildActionEntry
@@ -51,6 +51,20 @@
                BlueprintName = "CryptoSwiftTests"
                ReferencedContainer = "container:CryptoSwift.xcodeproj">
             </BuildableReference>
+            <SkippedTests>
+               <Test
+                  Identifier = "AESTests/testAESPerformance()">
+               </Test>
+               <Test
+                  Identifier = "AESTests/testAESPerformanceCommonCrypto()">
+               </Test>
+               <Test
+                  Identifier = "ChaCha20Tests/testChaCha20Performance()">
+               </Test>
+               <Test
+                  Identifier = "RaufelderTests">
+               </Test>
+            </SkippedTests>
          </TestableReference>
       </Testables>
       <MacroExpansion>

+ 116 - 117
CryptoSwift/AES.swift

@@ -8,29 +8,44 @@
 
 import Foundation
 
-private enum AESVariant:Int {
-    case unknown, aes128, aes192, aes256
+public class AES {
     
-    var Nk:Int { // Nk words
-        return [4,6,8][self.rawValue - 1]
+    public enum AESVariant:Int {
+        case unknown, aes128, aes192, aes256
+        
+        var Nk:Int { // Nk words
+            return [4,6,8][self.rawValue - 1]
+        }
+        
+        var Nb:Int { // Nb words
+            return 4
+        }
+        
+        var Nr:Int { // Nr
+            return Nk + 6
+        }
     }
     
-    var Nb:Int { // Nb words
-        return 4
-    }
+    public let blockMode:CipherBlockMode
+    public static let blockSize:Int = 16 // 128 /8
     
-    var Nr:Int { // Nr
-        return Nk + 6
+    public var variant:AESVariant {
+        switch (self.key.count * 8) {
+        case 128:
+            return .aes128
+        case 192:
+            return .aes192
+        case 256:
+            return .aes256
+        default:
+            return .unknown
+        }
     }
-}
-
-public class AES {
-    public let blockMode:CipherBlockMode
-    private let variant:AESVariant
-    private let key:NSData
-    private let iv:NSData?
+    private let key:[UInt8]
+    private let iv:[UInt8]?
+    public lazy var expandedKey:[UInt8] = { AES.expandKey(self.key, variant: self.variant) }()
     
-    private let sBox:[UInt8] = [
+    static private let sBox:[UInt8] = [
         0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 
         0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 
         0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 
@@ -48,7 +63,7 @@ public class AES {
         0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 
         0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]
     
-    private let invSBox:[UInt8] = [
+    static private let invSBox:[UInt8] = [
         0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
         0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
         0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54,
@@ -75,7 +90,7 @@ public class AES {
         0x21, 0x0c, 0x7d]
     
     // Parameters for Linear Congruence Generators
-    private let Rcon:[UInt8] = [
+    static private let Rcon:[UInt8] = [
         0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
         0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
         0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
@@ -93,46 +108,32 @@ public class AES {
         0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
         0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]
     
-    public init?(key:NSData, iv:NSData, blockMode:CipherBlockMode = .CBC) {
+    public init?(key:[UInt8], iv:[UInt8], blockMode:CipherBlockMode = .CBC) {
         self.key = key
-        self.blockMode = blockMode
         self.iv = iv
+        self.blockMode = blockMode
         
-        switch (key.length * 8) {
-        case 128:
-            self.variant = .aes128
-            break
-        case 192:
-            self.variant = .aes192
-            break
-        case 256:
-            self.variant = .aes256
-            break
-        default:
-            self.variant = .unknown
-            return nil
-        }
-        
-        if (blockMode.requireIV() && iv.length != AES.blockSizeBytes()) {
-            assertionFailure("Block and Initialization Vector must be the same length!")
+        if (blockMode.needIV && iv.count != AES.blockSize) {
+            assert(false, "Block size and Initialization Vector must be the same length!")
             return nil
         }
     }
     
-    convenience public init?(key:NSData, blockMode:CipherBlockMode = .CBC) {
+    convenience public init?(key:[UInt8], blockMode:CipherBlockMode = .CBC) {
         // default IV is all 0x00...
-        let defaultIV = NSMutableData(length: AES.blockSizeBytes())!
+        let defaultIV = [UInt8](count: AES.blockSize, repeatedValue: 0)
         self.init(key: key, iv: defaultIV, blockMode: blockMode)
     }
     
-    public class func blockSizeBytes() -> Int {
-        return 128 / 8 // 16 bytes
+    convenience public init?(key:String, iv:String, blockMode:CipherBlockMode = .CBC) {
+        if let kkey = key.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.bytes(), let iiv = iv.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.bytes() {
+            self.init(key: kkey, iv: iiv, blockMode: blockMode)
+        } else {
+            self.init(key: [UInt8](), iv: [UInt8](), blockMode: blockMode) //FIXME: this is due Swift bug, remove this line later, when fixed
+            return nil
+        }
     }
     
-    public class func blockSizeBytes() -> UInt8 {
-        return UInt8(truncatingBitPattern: self.blockSizeBytes())
-    }
-
     /**
     Encrypt message. If padding is necessary, then PKCS7 padding is added and needs to be removed after decryption.
     
@@ -140,81 +141,81 @@ public class AES {
     
     :returns: Encrypted data
     */
-    public func encrypt(message:NSData, addPadding: Bool = true) -> NSData? {
-        var finalMessage = message;
 
-        if (addPadding) {
-            finalMessage = PKCS7(data: message).addPadding(AES.blockSizeBytes())
-        } else if (message.length % AES.blockSizeBytes() != 0) {
+    public func encrypt(bytes:[UInt8], padding:Padding? = PKCS7()) -> [UInt8]? {
+        var finalBytes = bytes;
+
+        if let padding = padding {
+            finalBytes = padding.add(bytes, blockSize: AES.blockSize)
+        } else if (bytes.count % AES.blockSize != 0) {
             // 128 bit block exceeded, need padding
-            assertionFailure("AES 128-bit block exceeded!")
+            assert(false, "AES 128-bit block exceeded!");
             return nil
         }
-        
-        let blocks = finalMessage.bytes().chunks(AES.blockSizeBytes())
-        let out = blockMode.encryptBlocks(blocks, iv: self.iv?.bytes(), cipher: encryptBlock)
-        return out == nil ? nil : NSData.withBytes(out!)
+
+        let blocks = finalBytes.chunks(AES.blockSize) // 0.34
+        return blockMode.encryptBlocks(blocks, iv: self.iv, cipherOperation: encryptBlock)
     }
     
-    private func encryptBlock(block:[UInt8]) -> [UInt8] {
-        let expandedKey = expandKey()
+    private func encryptBlock(block:[UInt8]) -> [UInt8]? {
+        var out:[UInt8] = [UInt8]()
         
-        var state:[[UInt8]] = [[UInt8]](count: variant.Nb, repeatedValue: [UInt8](count: variant.Nb, repeatedValue: 0))
-        for (i, row) in enumerate(state) {
-            for (j, val) in enumerate(row) {
-                state[j][i] = block[i * row.count + j]
+        autoreleasepool { () -> () in
+            var state:[[UInt8]] = [[UInt8]](count: variant.Nb, repeatedValue: [UInt8](count: variant.Nb, repeatedValue: 0))
+            for (i, row) in enumerate(state) {
+                for (j, val) in enumerate(row) {
+                    state[j][i] = block[i * row.count + j]
+                }
             }
-        }
-        
-        state = addRoundKey(state,expandedKey, 0)
-        
-        for roundCount in 1..<variant.Nr {
-            state = subBytes(state)
+            
+            state = addRoundKey(state,expandedKey, 0)
+            
+            for roundCount in 1..<variant.Nr {
+                subBytes(&state)
+                state = shiftRows(state)
+                state = mixColumns(state)
+                state = addRoundKey(state, expandedKey, roundCount)
+            }
+            
+            subBytes(&state)
             state = shiftRows(state)
-            state = mixColumns(state)
-            state = addRoundKey(state, expandedKey, roundCount)
-        }
-        
-        state = subBytes(state)
-        state = shiftRows(state)
-        state = addRoundKey(state, expandedKey, variant.Nr)
-        
-        var out:[UInt8] = [UInt8]()
-        for i in 0..<state.count {
-            for j in 0..<state[0].count {
-                out.append(state[j][i])
+            state = addRoundKey(state, expandedKey, variant.Nr)
+
+
+            out = [UInt8](count: state.count * state.first!.count, repeatedValue: 0)
+            for i in 0..<state.count {
+                for j in 0..<state[i].count {
+                    out[(i * 4) + j] = state[j][i]
+                }
             }
         }
-        
         return out
     }
     
-    public func decrypt(message:NSData, removePadding:Bool = true) -> NSData? {
-        if (message.length % AES.blockSizeBytes() != 0) {
+    public func decrypt(bytes:[UInt8], padding:Padding? = PKCS7()) -> [UInt8]? {
+        if (bytes.count % AES.blockSize != 0) {
             // 128 bit block exceeded
-            assertionFailure("AES 128-bit block exceeded!")
+            assert(false,"AES 128-bit block exceeded!")
             return nil
         }
         
-        let blocks = message.bytes().chunks(AES.blockSizeBytes())
-        var out:[UInt8]?
+        let blocks = bytes.chunks(AES.blockSize)
+        let out:[UInt8]?
         if (blockMode == .CFB) {
             // CFB uses encryptBlock to decrypt
-            out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipher: encryptBlock)
+            out = blockMode.decryptBlocks(blocks, iv: self.iv, cipherOperation: encryptBlock)
         } else {
-            out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipher: decryptBlock)
+            out = blockMode.decryptBlocks(blocks, iv: self.iv, cipherOperation: decryptBlock)
         }
         
-        if (out != nil && removePadding) {
-            return PKCS7(data: NSData.withBytes(out!)).removePadding()
+        if let out = out, let padding = padding {
+            return padding.remove(out, blockSize: nil)
         }
         
-        return out == nil ? nil : NSData.withBytes(out!)
+        return out;
     }
     
-    private func decryptBlock(block:[UInt8]) -> [UInt8] {
-        let expandedKey = expandKey()
-        
+    private func decryptBlock(block:[UInt8]) -> [UInt8]? {
         var state:[[UInt8]] = [[UInt8]](count: variant.Nb, repeatedValue: [UInt8](count: variant.Nb, repeatedValue: 0))
         for (i, row) in enumerate(state) {
             for (j, val) in enumerate(row) {
@@ -245,7 +246,7 @@ public class AES {
         return out
     }
     
-    public func expandKey() -> [UInt8] {
+    static private func expandKey(key:[UInt8], variant:AESVariant) -> [UInt8] {
         
         /*
         * Function used in the Key Expansion routine that takes a four-byte
@@ -255,22 +256,22 @@ public class AES {
         func subWord(word:[UInt8]) -> [UInt8] {
             var result = word
             for i in 0..<4 {
-                result[i] = sBox[Int(word[i])]
+                result[i] = self.sBox[Int(word[i])]
             }
             return result
         }
 
-        var w:[UInt8] = [UInt8](count: variant.Nb * (variant.Nr + 1) * 4, repeatedValue: 0)
-        let keyBytes:[UInt8] = key.bytes()
+        var w = [UInt8](count: variant.Nb * (variant.Nr + 1) * 4, repeatedValue: 0)
         for i in 0..<variant.Nk {
             for wordIdx in 0..<4 {
-                w[(4*i)+wordIdx] = keyBytes[(4*i)+wordIdx]
+                w[(4*i)+wordIdx] = key[(4*i)+wordIdx]
             }
         }
         
-        var i = variant.Nk
-        while (i < variant.Nb * (variant.Nr + 1)) {
-            var tmp:[UInt8] = [UInt8](count: 4, repeatedValue: 0)
+        var tmp:[UInt8]
+        for (var i = variant.Nk; i < variant.Nb * (variant.Nr + 1); i++) {
+            tmp = [UInt8](count: 4, repeatedValue: 0)
+            
             for wordIdx in 0..<4 {
                 tmp[wordIdx] = w[4*(i-1)+wordIdx]
             }
@@ -286,8 +287,6 @@ public class AES {
             for wordIdx in 0..<4 {
                 w[4*i+wordIdx] = w[4*(i-variant.Nk)+wordIdx]^tmp[wordIdx];
             }
-            
-            i++
         }
         return w;
     }
@@ -296,21 +295,19 @@ public class AES {
 extension AES {
     
     // byte substitution with table (S-box)
-    public func subBytes(state:[[UInt8]]) -> [[UInt8]] {
-        var result = state
+    public func subBytes(inout state:[[UInt8]]) {
         for (i,row) in enumerate(state) {
             for (j,value) in enumerate(row) {
-                result[i][j] = sBox[Int(value)]
+                state[i][j] = AES.sBox[Int(value)]
             }
         }
-        return result
     }
     
     public func invSubBytes(state:[[UInt8]]) -> [[UInt8]] {
         var result = state
         for (i,row) in enumerate(state) {
             for (j,value) in enumerate(row) {
-                result[i][j] = invSBox[Int(value)]
+                result[i][j] = AES.invSBox[Int(value)]
             }
         }
         return result
@@ -357,7 +354,7 @@ extension AES {
     }
     
     public func matrixMultiplyPolys(matrix:[[UInt8]], _ array:[UInt8]) -> [UInt8] {
-        var returnArray:[UInt8] = array.map({ _ in return 0 })
+        var returnArray:[UInt8] = [UInt8](count: array.count, repeatedValue: 0)
         for (i, row) in enumerate(matrix) {
             for (j, boxVal) in enumerate(row) {
                 returnArray[i] = multiplyPolys(boxVal, array[j]) ^ returnArray[i]
@@ -367,11 +364,14 @@ extension AES {
     }
 
     public func addRoundKey(state:[[UInt8]], _ expandedKeyW:[UInt8], _ round:Int) -> [[UInt8]] {
-        var newState = state.map({ val -> [UInt8] in return val.map { _ in return 0 } })
+        var newState = [[UInt8]](count: state.count, repeatedValue: [UInt8](count: variant.Nb, repeatedValue: 0))
+        let idxRow = 4*variant.Nb*round
         for c in 0..<variant.Nb {
-            for i in 0..<4 {
-                newState[i][c] = state[i][c] ^ expandedKeyW[(4*variant.Nb*round)+(variant.Nb*c)+i]
-            }
+            let idxCol = variant.Nb*c
+            newState[0][c] = state[0][c] ^ expandedKeyW[idxRow+idxCol+0]
+            newState[1][c] = state[1][c] ^ expandedKeyW[idxRow+idxCol+1]
+            newState[2][c] = state[2][c] ^ expandedKeyW[idxRow+idxCol+2]
+            newState[3][c] = state[3][c] ^ expandedKeyW[idxRow+idxCol+3]
         }
         return newState
     }
@@ -381,7 +381,8 @@ extension AES {
         var state = state
         var colBox:[[UInt8]] = [[2,3,1,1],[1,2,3,1],[1,1,2,3],[3,1,1,2]]
         
-        var rowMajorState = state.map({ val -> [UInt8] in return val.map { _ in return 0 } }) // zeroing
+        var rowMajorState = [[UInt8]](count: state.count, repeatedValue: [UInt8](count: state.first!.count, repeatedValue: 0)) //state.map({ val -> [UInt8] in return val.map { _ in return 0 } }) // zeroing
+        var newRowMajorState = rowMajorState
         
         for i in 0..<state.count {
             for j in 0..<state[0].count {
@@ -389,8 +390,6 @@ extension AES {
             }
         }
         
-        var newRowMajorState = state.map({ val -> [UInt8] in return val.map { _ in return 0 } })
-        
         for (i, row) in enumerate(rowMajorState) {
             newRowMajorState[i] = matrixMultiplyPolys(colBox, row)
         }

+ 4 - 3
CryptoSwift/ArrayExtension.swift

@@ -11,10 +11,11 @@ import Foundation
 extension Array {
     
     /** split in chunks with given chunk size */
-    internal func chunks(chunksize:Int) -> [Array<T>] {
-        var words:[[T]] = [[T]]()
+    func chunks(chunksize:Int) -> [Array<T>] {
+        var words = [[T]]()
+        words.reserveCapacity(self.count / chunksize)        
         for var idx = chunksize; idx <= self.count; idx = idx + chunksize {
-            let word = Array(self[idx - chunksize..<idx])
+            let word = Array(self[idx - chunksize..<idx]) // this is slow for large table
             words.append(word)
         }
         let reminder = Array(suffix(self, self.count % chunksize))

+ 3 - 3
CryptoSwift/Authenticator.swift

@@ -17,15 +17,15 @@ public enum Authenticator {
     
     :param: key 256-bit key
     */
-    case Poly1305(key: NSData)
-    case HMAC(key: NSData, variant:CryptoSwift.HMAC.Variant)
+    case Poly1305(key: [UInt8])
+    case HMAC(key: [UInt8], variant:CryptoSwift.HMAC.Variant)
     
     /**
     Generates an authenticator for message using a one-time key and returns the 16-byte result
     
     :returns: 16-byte message authentication code
     */
-    public func authenticate(message: NSData) -> NSData? {
+    public func authenticate(message: [UInt8]) -> [UInt8]? {
         switch (self) {
         case .Poly1305(let key):
             return CryptoSwift.Poly1305.authenticate(key: key, message: message)

+ 48 - 28
CryptoSwift/ChaCha20.swift

@@ -10,7 +10,7 @@ import Foundation
 
 public class ChaCha20 {
     
-    private let blockSizeBytes = 512 / 8
+    static let blockSize = 64 // 512 / 8
     private let stateSize = 16
     private var context:Context?
     
@@ -24,7 +24,7 @@ public class ChaCha20 {
         }
     }
     
-    init?(key:NSData, iv:NSData) {
+    public init?(key:[UInt8], iv:[UInt8]) {
         if let c = contextSetup(iv: iv, key: key) {
             context = c
         } else {
@@ -32,23 +32,29 @@ public class ChaCha20 {
         }
     }
     
-    func encrypt(message:NSData) -> NSData? {
-        if (context == nil) {
+    convenience public init?(key:String, iv:String) {
+        if let kkey = key.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.bytes(), let iiv = iv.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.bytes() {
+            self.init(key: kkey, iv: iiv)
+        } else {
+            self.init(key: [UInt8](), iv: [UInt8]()) //FIXME: this is due Swift bug, remove this line later, when fixed
             return nil
         }
-        
-        if let output = encryptBytes(message.bytes()) {
-            return NSData.withBytes(output)
+    }
+
+    
+    public func encrypt(bytes:[UInt8]) -> [UInt8]? {
+        if (context == nil) {
+            return nil
         }
         
-        return nil
+        return encryptBytes(bytes)
     }
     
-    func decrypt(message:NSData) -> NSData? {
-        return encrypt(message)
+    public func decrypt(bytes:[UInt8]) -> [UInt8]? {
+        return encrypt(bytes)
     }
     
-    private func wordToByte(input:[UInt32] /* 64 */) -> [UInt8]? /* 16 */ {
+    private final func wordToByte(input:[UInt32] /* 64 */) -> [UInt8]? /* 16 */ {
         if (input.count != stateSize) {
             return nil;
         }
@@ -69,19 +75,19 @@ public class ChaCha20 {
         }
 
         var output = [UInt8]()
+        output.reserveCapacity(16)
 
         for i in 0..<16 {
             x[i] = x[i] &+ input[i]
-            output += x[i].bytes().reverse()
+            output += [UInt8((x[i] & 0xFFFFFFFF) >> 24),
+                       UInt8((x[i] & 0xFFFFFF) >> 16),
+                       UInt8((x[i] & 0xFFFF) >> 8),
+                       UInt8((x[i] & 0xFF) >> 0)]
         }
 
         return output;
     }
-    
-    private func contextSetup(# iv:NSData, key:NSData) -> Context? {
-        return contextSetup(iv: iv.bytes(), key: key.bytes())
-    }
-    
+        
     private func contextSetup(# iv:[UInt8], key:[UInt8]) -> Context? {
         var ctx = Context()
         let kbits = key.count * 8
@@ -93,7 +99,7 @@ public class ChaCha20 {
         // 4 - 8
         for (var i = 0; i < 4; i++) {
             let start = i * 4
-            ctx.input[i + 4] = UInt32.withBytes(key[start..<(start + 4)]).bigEndian
+            ctx.input[i + 4] = wordNumber(key[start..<(start + 4)])
         }
         
         var addPos = 0;
@@ -117,19 +123,21 @@ public class ChaCha20 {
         // 8 - 11
         for (var i = 0; i < 4; i++) {
             let start = addPos + (i*4)
-            ctx.input[i + 8] = UInt32.withBytes(key[start..<(start + 4)]).bigEndian
+            
+            let bytes = key[start..<(start + 4)]
+            ctx.input[i + 8] = wordNumber(bytes)
         }
 
         // iv
         ctx.input[12] = 0
         ctx.input[13] = 0
-        ctx.input[14] = UInt32.withBytes(iv[0..<4]).bigEndian
-        ctx.input[15] = UInt32.withBytes(iv[4..<8]).bigEndian
+        ctx.input[14] = wordNumber(iv[0..<4])
+        ctx.input[15] = wordNumber(iv[4..<8])
         
         return ctx
     }
     
-    private func encryptBytes(message:[UInt8]) -> [UInt8]? {
+    private final func encryptBytes(message:[UInt8]) -> [UInt8]? {
         
         if let ctx = context {
             var c:[UInt8] = [UInt8](count: message.count, repeatedValue: 0)
@@ -145,25 +153,25 @@ public class ChaCha20 {
                         ctx.input[13] = ctx.input[13] &+ 1
                         /* stopping at 2^70 bytes per nonce is user's responsibility */
                     }
-                    if (bytes <= blockSizeBytes) {
+                    if (bytes <= ChaCha20.blockSize) {
                         for (var i = 0; i < bytes; i++) {
                             c[i + cPos] = message[i + mPos] ^ output[i]
                         }
                         return c
                     }
-                    for (var i = 0; i < blockSizeBytes; i++) {
+                    for (var i = 0; i < ChaCha20.blockSize; i++) {
                         c[i + cPos] = message[i + mPos] ^ output[i]
                     }
-                    bytes -= blockSizeBytes
-                    cPos += blockSizeBytes
-                    mPos += blockSizeBytes
+                    bytes -= ChaCha20.blockSize
+                    cPos += ChaCha20.blockSize
+                    mPos += ChaCha20.blockSize
                 }
             }
         }
         return nil;
     }
     
-    private func quarterround(inout a:UInt32, inout _ b:UInt32, inout _ c:UInt32, inout _ d:UInt32) {
+    private final func quarterround(inout a:UInt32, inout _ b:UInt32, inout _ c:UInt32, inout _ d:UInt32) {
         a = a &+ b
         d = rotateLeft((d ^ a), 16)
         
@@ -177,3 +185,15 @@ public class ChaCha20 {
         b = rotateLeft((b ^ c), 7);
     }
 }
+
+// MARK: Helpers
+
+/// Change array to number. It's here because arrayOfBytes is too slow
+private func wordNumber(bytes:ArraySlice<UInt8>) -> UInt32 {
+    var value:UInt32 = 0
+    for (var i:UInt32 = 0, j = 0; i < 4; i++, j++) {
+        value = value | UInt32(bytes[j]) << (8 * i)
+    }
+    return value
+}
+

+ 10 - 21
CryptoSwift/Cipher.swift

@@ -17,7 +17,7 @@ public enum Cipher {
     
     :returns: Value of Cipher
     */
-    case ChaCha20(key: NSData, iv: NSData)
+    case ChaCha20(key: [UInt8], iv: [UInt8])
     /**
     AES
     
@@ -27,7 +27,7 @@ public enum Cipher {
     
     :returns: Value of Cipher
     */
-    case AES(key: NSData, iv: NSData, blockMode: CipherBlockMode)
+    case AES(key: [UInt8], iv: [UInt8], blockMode: CipherBlockMode)
     
     /**
     Encrypt message
@@ -36,14 +36,14 @@ public enum Cipher {
     
     :returns: encrypted message
     */
-    public func encrypt(message: NSData) -> NSData? {
+    public func encrypt(bytes: [UInt8]) -> [UInt8]? {
         switch (self) {
             case .ChaCha20(let key, let iv):
                 var chacha = CryptoSwift.ChaCha20(key: key, iv: iv)
-                return chacha?.encrypt(message)
+                return chacha?.encrypt(bytes)
             case .AES(let key, let iv, let blockMode):
                 var aes = CryptoSwift.AES(key: key, iv: iv, blockMode: blockMode)
-                return aes?.encrypt(message)
+                return aes?.encrypt(bytes)
         }
     }
     
@@ -54,33 +54,22 @@ public enum Cipher {
     
     :returns: Plaintext message
     */
-    public func decrypt(message: NSData) -> NSData? {
+    public func decrypt(bytes: [UInt8]) -> [UInt8]? {
         switch (self) {
             case .ChaCha20(let key, let iv):
                 var chacha = CryptoSwift.ChaCha20(key: key, iv: iv);
-                return chacha?.decrypt(message)
+                return chacha?.decrypt(bytes)
             case .AES(let key, let iv, let blockMode):
                 var aes = CryptoSwift.AES(key: key, iv: iv, blockMode: blockMode);
-                return aes?.decrypt(message)
+                return aes?.decrypt(bytes)
         }
     }
 
-    static public func randomIV(key: NSData) -> [UInt8] {
+    static public func randomIV(blockSize:Int) -> [UInt8] {
         var randomIV:[UInt8] = [UInt8]();
-        for (var i = 0; i < key.length; i++) {
+        for (var i = 0; i < blockSize; i++) {
             randomIV.append(UInt8(truncatingBitPattern: arc4random_uniform(256)));
         }
         return randomIV
     }
-    
-    /**
-    Convenience function to generate Initialization Vector (IV) for given key. Use this function to generate IV for you key.
-    
-    :param: key Given key
-    
-    :returns: Random IV
-    */
-    static public func randomIV(key: NSData) -> NSData {
-        return NSData.withBytes(randomIV(key))
-    }
 }

+ 75 - 124
CryptoSwift/CipherBlockMode.swift

@@ -8,18 +8,33 @@
 
 import Foundation
 
+// I have no better name for that
+typealias CipherOperationOnBlock = (block: [UInt8]) -> [UInt8]?
+
+private protocol BlockMode {
+    var needIV:Bool { get }
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]?
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]?
+}
+
 public enum CipherBlockMode {
     case ECB, CBC, CFB
     
-    func requireIV() -> Bool {
+    private var mode:BlockMode {
         switch (self) {
-        case CBC, CFB:
-            return true
-        default:
-            return false
+        case CBC:
+            return CBCMode()
+        case CFB:
+            return CFBMode()
+        case ECB:
+            return ECBMode()
         }
     }
     
+    var needIV: Bool {
+        return mode.needIV
+    }
+    
     /**
     Process input blocks with given block cipher mode. With fallback to plain mode.
     
@@ -29,7 +44,7 @@ public enum CipherBlockMode {
     
     :returns: encrypted bytes
     */
-    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         
         // if IV is not available, fallback to plain
         var finalBlockMode:CipherBlockMode = self
@@ -37,91 +52,61 @@ public enum CipherBlockMode {
             finalBlockMode = .ECB
         }
         
-        switch (finalBlockMode) {
-        case CBC:
-            return CBCMode.encryptBlocks(blocks, iv: iv, cipher: cipher)
-        case CFB:
-            return CFBMode.encryptBlocks(blocks, iv: iv, cipher: cipher)
-        case ECB:
-            return ECBMode.encryptBlocks(blocks, cipher: cipher)
-        }
+        return finalBlockMode.mode.encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
     
-    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
         // if IV is not available, fallback to plain
         var finalBlockMode:CipherBlockMode = self
         if (iv == nil) {
             finalBlockMode = .ECB
         }
-        
-        switch (finalBlockMode) {
-        case CBC:
-            return CBCMode.decryptBlocks(blocks, iv: iv, cipher: cipher)
-        case CFB:
-            return CFBMode.decryptBlocks(blocks, iv: iv, cipher: cipher)
-        case ECB:
-            return ECBMode.decryptBlocks(blocks, cipher: cipher)
-        }
+
+        return finalBlockMode.mode.decryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
 }
 
 /**
 *  Cipher-block chaining (CBC)
 */
-private struct CBCMode {
-    static func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
-        
+private struct CBCMode: BlockMode {
+    var needIV:Bool = true
+    
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        precondition(blocks.count > 0)
+        assert(iv != nil, "CFB require IV")
         if (iv == nil) {
-            assertionFailure("CBC require IV")
-            return nil
+            return nil;
         }
         
-        var out:[UInt8]?
-        var lastCiphertext:[UInt8] = iv!
-        for (idx,plaintext) in enumerate(blocks) {
-            // for the first time ciphertext = iv
-            // ciphertext = plaintext (+) ciphertext
-            var xoredPlaintext:[UInt8] = plaintext
-            for i in 0..<plaintext.count {
-                xoredPlaintext[i] = lastCiphertext[i] ^ plaintext[i]
-            }
-            
-            // encrypt with cipher
-            if let encrypted = cipher(block: xoredPlaintext) {
-                lastCiphertext = encrypted
-                
-                if (out == nil) {
-                    out = [UInt8]()
-                }
-                
-                out = out! + encrypted
+        
+        var out:[UInt8] = [UInt8]()
+        out.reserveCapacity(blocks.count * blocks[0].count)
+        var prevCiphertext = iv! // for the first time prevCiphertext = iv
+        for plaintext in blocks {
+            if let encrypted = cipherOperation(block: xor(prevCiphertext, plaintext)) {
+                out.extend(encrypted)
+                prevCiphertext = encrypted
             }
         }
         return out;
     }
     
-    static func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        precondition(blocks.count > 0)
+        assert(iv != nil, "CFB require IV")
         if (iv == nil) {
-            assertionFailure("CBC require IV")
             return nil
         }
 
-        var out:[UInt8]?
-        var lastCiphertext:[UInt8] = iv!
-        for (idx,ciphertext) in enumerate(blocks) {
-            if let decrypted = cipher(block: ciphertext) { // decrypt
-                
-                var xored:[UInt8] = [UInt8](count: ciphertext.count, repeatedValue: 0)
-                for i in 0..<ciphertext.count {
-                    xored[i] = lastCiphertext[i] ^ decrypted[i]
-                }
-
-                if (out == nil) {
-                    out = [UInt8]()
-                }
-                out = out! + xored
+        var out:[UInt8] = [UInt8]()
+        out.reserveCapacity(blocks.count * blocks[0].count)
+        var prevCiphertext = iv! // for the first time prevCiphertext = iv
+        for ciphertext in blocks {
+            if let decrypted = cipherOperation(block: ciphertext) { // decrypt
+                out.extend(xor(prevCiphertext, decrypted))
             }
-            lastCiphertext = ciphertext
+            prevCiphertext = ciphertext
         }
         
         return out
@@ -131,85 +116,51 @@ private struct CBCMode {
 /**
 *  Cipher feedback (CFB)
 */
-private struct CFBMode {
-    static func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
-        
+private struct CFBMode: BlockMode {
+    var needIV:Bool = true
+    
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        assert(iv != nil, "CFB require IV")
         if (iv == nil) {
-            assertionFailure("CFB require IV")
             return nil
         }
         
-        var out:[UInt8]?
-        var lastCiphertext:[UInt8] = iv!
-        for (idx,plaintext) in enumerate(blocks) {
-            if let encrypted = cipher(block: lastCiphertext) {
-                var xoredPlaintext:[UInt8] = [UInt8](count: plaintext.count, repeatedValue: 0)
-                for i in 0..<plaintext.count {
-                    xoredPlaintext[i] = plaintext[i] ^ encrypted[i]
-                }
-                lastCiphertext = xoredPlaintext
+        var out:[UInt8] = [UInt8]()
+        out.reserveCapacity(blocks.count * blocks[0].count)
 
-                
-                if (out == nil) {
-                    out = [UInt8]()
-                }
-                
-                out = out! + xoredPlaintext
+        var lastCiphertext = iv!
+        for plaintext in blocks {
+            if let encrypted = cipherOperation(block: lastCiphertext) {
+                lastCiphertext = xor(plaintext,encrypted)
+                out.extend(lastCiphertext)
             }
         }
         return out;
     }
     
-    static func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
-        if (iv == nil) {
-            assertionFailure("CFB require IV")
-            return nil
-        }
-        
-        var out:[UInt8]?
-        var lastCiphertext:[UInt8] = iv!
-        for (idx,ciphertext) in enumerate(blocks) {
-            if let decrypted = cipher(block: lastCiphertext) {
-                var xored:[UInt8] = [UInt8](count: ciphertext.count, repeatedValue: 0)
-                for i in 0..<ciphertext.count {
-                    xored[i] = ciphertext[i] ^ decrypted[i]
-                }
-                lastCiphertext = xored
-                
-                
-                if (out == nil) {
-                    out = [UInt8]()
-                }
-                
-                out = out! + xored
-            }
-        }
-        return out;
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        return encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
-
 }
 
 
 /**
 *  Electronic codebook (ECB)
 */
-private struct ECBMode {
-    static func encryptBlocks(blocks:[[UInt8]], cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
-        var out:[UInt8]?
-        for (idx,plaintext) in enumerate(blocks) {
-            if let encrypted = cipher(block: plaintext) {
-                
-                if (out == nil) {
-                    out = [UInt8]()
-                }
-
-                out = out! + encrypted
+private struct ECBMode: BlockMode {
+    var needIV:Bool = false
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        var out:[UInt8] = [UInt8]()
+        out.reserveCapacity(blocks.count * blocks[0].count)
+        for plaintext in blocks {
+            if let encrypted = cipherOperation(block: plaintext) {
+                out.extend(encrypted)
             }
         }
         return out
     }
     
-    static func decryptBlocks(blocks:[[UInt8]], cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
-        return encryptBlocks(blocks, cipher: cipher)
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        return encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
-}
+}

+ 9 - 6
CryptoSwift/Generics.swift

@@ -34,7 +34,9 @@ func integerFromBitsArray<T: UnsignedIntegerType>(bits: [Bit]) -> T
     return bitPattern
 }
 
-/** initialize integer from array of bytes */
+/// Initialize integer from array of bytes.
+/// I found this method slow
+@availability(*, deprecated=0.8)
 func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
     var totalBytes = Swift.min(bytes.count, sizeof(T))
     // get slice of Int
@@ -53,15 +55,16 @@ func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
     return i
 }
 
-/** array of bytes, little-endian representation */
+/// Array of bytes, little-endian representation. Don't use if not necessary.
+/// I found this method slow
 func arrayOfBytes<T>(value:T, length:Int? = nil) -> [UInt8] {
-    let totalBytes = length ?? (sizeofValue(value) * 8)
+    let totalBytes = length ?? sizeof(T)
     var v = value
     
     var valuePointer = UnsafeMutablePointer<T>.alloc(1)
     valuePointer.memory = value
     
-    var bytesPointer = UnsafeMutablePointer<Byte>(valuePointer)
+    var bytesPointer = UnsafeMutablePointer<UInt8>(valuePointer)
     var bytes = [UInt8](count: totalBytes, repeatedValue: 0)
     for j in 0..<min(sizeof(T),totalBytes) {
         bytes[totalBytes - 1 - j] = (bytesPointer + j).memory
@@ -77,13 +80,13 @@ func arrayOfBytes<T>(value:T, length:Int? = nil) -> [UInt8] {
 
 // helper to be able tomake shift operation on T
 func <<<T:SignedIntegerType>(lhs: T, rhs: Int) -> Int {
-    let a = lhs as Int
+    let a = lhs as! Int
     let b = rhs
     return a << b
 }
 
 func <<<T:UnsignedIntegerType>(lhs: T, rhs: Int) -> UInt {
-    let a = lhs as UInt
+    let a = lhs as! UInt
     let b = rhs
     return a << b
 }

+ 18 - 10
CryptoSwift/HMAC.swift

@@ -13,6 +13,21 @@ public class HMAC {
     public enum Variant {
         case sha1, sha256, sha384, sha512, md5
         
+        var size:Int {
+            switch (self) {
+            case .sha1:
+                return SHA1(NSData()).size
+            case .sha256:
+                return SHA2.Variant.sha256.size
+            case .sha384:
+                return SHA2.Variant.sha384.size
+            case .sha512:
+                return SHA2.Variant.sha512.size
+            case .md5:
+                return MD5(NSData()).size
+            }
+        }
+        
         func calculateHash(# bytes:[UInt8]) -> [UInt8]? {
             switch (self) {
             case .sha1:
@@ -38,23 +53,16 @@ public class HMAC {
         }
     }
     
-    let key:[UInt8]
+    var key:[UInt8]
     let variant:Variant
     
-    class internal func authenticate(# key: NSData, message: NSData, variant:HMAC.Variant = .md5) -> NSData? {
-        if let mac = HMAC.authenticate(key: key.bytes(), message: message.bytes(), variant: variant) {
-            return NSData(bytes: mac, length: mac.count)
-        }
-        return nil
-    }
-    
     class internal func authenticate(# key: [UInt8], message: [UInt8], variant:HMAC.Variant = .md5) -> [UInt8]? {
         return HMAC(key, variant: variant)?.authenticate(message: message)
     }
 
     // MARK: - Private
     
-    private init? (_ key: [UInt8], variant:HMAC.Variant = .md5) {
+    internal init? (_ key: [UInt8], variant:HMAC.Variant = .md5) {
         self.variant = variant
         self.key = key
 
@@ -69,7 +77,7 @@ public class HMAC {
         }
     }
     
-    private func authenticate(# message:[UInt8]) -> [UInt8]? {
+    internal func authenticate(# message:[UInt8]) -> [UInt8]? {
         var opad = [UInt8](count: variant.blockSize(), repeatedValue: 0x5c)
         for (idx, val) in enumerate(key) {
             opad[idx] = key[idx] ^ opad[idx]

+ 4 - 4
CryptoSwift/Hash.swift

@@ -21,13 +21,13 @@ public enum Hash {
         case sha1(let data):
             return SHA1(data).calculate()
         case sha224(let data):
-            return SHA2(data).calculate32(.sha224)
+            return SHA2(data, variant: .sha224).calculate32()
         case sha256(let data):
-            return SHA2(data).calculate32(.sha256)
+            return SHA2(data, variant: .sha256).calculate32()
         case sha384(let data):
-            return SHA2(data).calculate64(.sha384)
+            return SHA2(data, variant: .sha384).calculate64()
         case sha512(let data):
-            return SHA2(data).calculate64(.sha512)
+            return SHA2(data, variant: .sha512).calculate64()
         case crc32(let data):
             return CRC().crc32(data);
         default:

+ 18 - 7
CryptoSwift/CryptoHashBase.swift → CryptoSwift/HashBase.swift

@@ -8,31 +8,42 @@
 
 import Foundation
 
-class HashBase {
+protocol _Hash {
+    var size:Int { get }
+    func prepare(len:Int) -> NSMutableData;
+}
+
+internal class HashBase {
     
     var message: NSData
     
-    init(_ message: NSData) {
+    internal init(_ message: NSData) {
         self.message = message
     }
     
     /** Common part for hash calculation. Prepare header data. */
-    func prepare(_ len:Int = 64) -> NSMutableData {
+    internal func prepare(_ len:Int = 64) -> NSMutableData {
         var tmpMessage: NSMutableData = NSMutableData(data: self.message)
         
         // Step 1. Append Padding Bits
         tmpMessage.appendBytes([0x80]) // append one bit (UInt8 with one bit) to message
         
         // append "0" bit until message length in bits ≡ 448 (mod 512)
-        var msgLength = tmpMessage.length;
-        var counter = 0;
+        var msgLength = tmpMessage.length
+        var counter = 0
+      
         while msgLength % len != (len - 8) {
             counter++
             msgLength++
         }
-        var bufZeros = UnsafeMutablePointer<UInt8>(calloc(UInt(counter), UInt(sizeof(UInt8))))
+      
+        var bufZeros = UnsafeMutablePointer<UInt8>(calloc(counter, sizeof(UInt8)))
+      
         tmpMessage.appendBytes(bufZeros, length: counter)
-        
+      
+        bufZeros.destroy()
+        bufZeros.dealloc(1)
+      
         return tmpMessage
     }
 }

+ 1 - 1
CryptoSwift/IntExtension.swift

@@ -30,7 +30,7 @@ extension Int {
         return arrayOfBytes(self, length: totalBytes)
     }
 
-    public static func withBytes(bytes: Slice<Byte>) -> Int {
+    public static func withBytes(bytes: ArraySlice<UInt8>) -> Int {
         return Int.withBytes(Array(bytes))
     }
 

+ 6 - 6
CryptoSwift/MD5.swift

@@ -8,8 +8,9 @@
 
 import Foundation
 
-class MD5 : CryptoSwift.HashBase {
-
+class MD5 : CryptoSwift.HashBase, _Hash {
+    var size:Int = 16 // 128 / 8
+    
     /** specifies the per-round shift amounts */
     private let s: [UInt32] = [7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
                        5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
@@ -56,9 +57,8 @@ class MD5 : CryptoSwift.HashBase {
             
             // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
             var M:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
-            for x in 0..<M.count {
-                chunk.getBytes(&M[x], range:NSRange(location:x * sizeofValue(M[x]), length: sizeofValue(M[x])));
-            }
+            let range = NSRange(location:0, length: M.count * sizeof(UInt32))
+            chunk.getBytes(UnsafeMutablePointer<Void>(M), range: range)
             
             // Initialize hash value for this chunk:
             var A:UInt32 = hh[0]
@@ -112,7 +112,7 @@ class MD5 : CryptoSwift.HashBase {
             buf.appendBytes(&i, length: sizeofValue(i))
         })
         
-        return buf.copy() as NSData;
+        return buf.copy() as! NSData;
     }
 }
 

+ 13 - 4
CryptoSwift/NSDataExtension.swift

@@ -61,15 +61,24 @@ extension NSData {
     }
 
     public func encrypt(cipher: Cipher) -> NSData? {
-        return cipher.encrypt(self)
+        if let encrypted = cipher.encrypt(self.bytes()) {
+            return NSData.withBytes(encrypted)
+        }
+        return nil
     }
 
     public func decrypt(cipher: Cipher) -> NSData? {
-        return cipher.decrypt(self)
+        if let decrypted = cipher.decrypt(self.bytes()) {
+            return NSData.withBytes(decrypted)
+        }
+        return nil;
     }
     
     public func authenticate(authenticator: Authenticator) -> NSData? {
-        return authenticator.authenticate(self)
+        if let result = authenticator.authenticate(self.bytes()) {
+            return NSData.withBytes(result)
+        }
+        return nil
     }
 }
 
@@ -86,7 +95,7 @@ extension NSData {
         
         var s:String = "";
         for byte in bytesArray {
-            s = s + NSString(format:"%02X", byte)
+            s = s + String(format:"%02X", byte)
         }
         return s;
     }

+ 52 - 0
CryptoSwift/PKCS5.swift

@@ -0,0 +1,52 @@
+//
+//  PKCS.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 12/03/15.
+//  Copyright (c) 2015 Marcin Krzyzanowski. All rights reserved.
+//
+//  PKCS is a group of public-key cryptography standards devised 
+//  and published by RSA Security Inc, starting in the early 1990s.
+//
+//  PKCS#5 http://tools.ietf.org/html/rfc2898
+
+import Foundation
+
+//public struct PKCS5 {
+//}
+//
+//extension PKCS5 {
+//    //
+//    // PBKDF2 - Password-Based Key Derivation Function 2. Key stretching technique.
+//    //          DK = PBKDF2(PRF, Password, Salt, c, dkLen)
+//    //
+//    struct PBKDF2 {
+//        typealias Bytes = [UInt8]
+//        private func calc(# hash:Hash,  password:Bytes, salt:Bytes, c:Int, dkLen:Int) -> [UInt8]? {
+//            if (dkLen > Int(pow(2,32) as Float - 1)) {
+//                println("ERROR: derived key too long");
+//                return nil
+//            }
+//
+//            if let prf = HMAC(password, variant: .sha256) { //FIXME: hardcoded SHA256
+//                let hLen = prf.variant.size
+//                let numBlocks = Int(ceilf(Float(dkLen) / Float(hLen)))  // l
+//                let lastBlockOctets = dkLen - (1 - numBlocks) * hLen    // r
+//                // blocks
+//                for block in 1...numBlocks {
+//                    // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
+//                    // U_1 = PRF(password, salt || uint(i))
+//                    var uinti = [UInt8](count: 4, repeatedValue: 0)
+//                    uinti[0] = UInt8(block >> 24)
+//                    uinti[1] = UInt8(block >> 16)
+//                    uinti[2] = UInt8(block >> 8)
+//                    uinti[3] = UInt8(block)
+//                    if let dk = prf.authenticate(message: salt + uinti) {
+//                        let T = dk[dk.count - hLen]
+//                    }
+//                }
+//            }
+//            return nil
+//        }
+//    }
+//}

+ 20 - 19
CryptoSwift/PKCS7.swift

@@ -2,43 +2,44 @@
 //  PKCS7.swift
 //  CryptoSwift
 //
-//  Created by Marcin Krzyzanowski on 27/12/14.
-//  Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
+//  Created by Marcin Krzyzanowski on 28/02/15.
+//  Copyright (c) 2015 Marcin Krzyzanowski. All rights reserved.
+//
+//  PKCS is a group of public-key cryptography standards devised
+//  and published by RSA Security Inc, starting in the early 1990s.
 //
 
 import Foundation
 
-public struct PKCS7 {
-    let data:NSData
+public struct PKCS7: Padding {
     
-    public init(data:NSData) {
-        self.data = data;
+    public init() {
+        
     }
     
-    public func addPadding(blockSizeBytes:UInt8) -> NSData {
-        var padding = blockSizeBytes - (data.length % Int(blockSizeBytes))
-        var withPadding = NSMutableData(data: data)
+    public func add(bytes: [UInt8] , blockSize:Int) -> [UInt8] {
+        var padding = UInt8(blockSize - (bytes.count % blockSize))
+        var withPadding = bytes
         if (padding == 0) {
             // If the original data is a multiple of N bytes, then an extra block of bytes with value N is added.
-            for i in 0..<blockSizeBytes {
-                withPadding.appendBytes([blockSizeBytes])
+            for i in 0..<blockSize {
+                withPadding.extend([UInt8(blockSize)])
             }
         } else {
             // The value of each added byte is the number of bytes that are added
             for i in 0..<padding {
-                withPadding.appendBytes([padding])
+                withPadding.extend([UInt8(padding)])
             }
         }
         return withPadding
     }
     
-    public func removePadding() -> NSData {
-        var padding:Byte = 0
-        data.subdataWithRange(NSRange(location: data.length - 1, length: 1)).getBytes(&padding, length: 1)
+    public func remove(bytes: [UInt8], blockSize:Int? = nil) -> [UInt8] {
+        var padding = Int(bytes.last!) // last byte
         
-        if padding >= 1 {
-            return data.subdataWithRange(NSRange(location: 0, length: data.length - Int(padding)))
+        if padding >= 1 { //TODO: need test for that, what about empty padding
+            return Array(bytes[0..<(bytes.count - padding)])
         }
-        return data
+        return bytes
     }
-}
+}

+ 14 - 0
CryptoSwift/Padding.swift

@@ -0,0 +1,14 @@
+//
+//  Padding.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 27/02/15.
+//  Copyright (c) 2015 Marcin Krzyzanowski. All rights reserved.
+//
+
+import Foundation
+
+public protocol Padding {
+    func add(data: [UInt8], blockSize:Int) -> [UInt8];
+    func remove(data: [UInt8], blockSize:Int?) -> [UInt8];
+}

+ 0 - 32
CryptoSwift/PaddingMode.swift

@@ -1,32 +0,0 @@
-//
-//  PaddingMode.swift
-//  CryptoSwift
-//
-//  Created by Marcin Krzyzanowski on 27/12/14.
-//  Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
-//
-
-import Foundation
-
-public enum PaddingMode:Int {
-    case None, PKCS_7
-    
-    public func addPadding(data:NSData, blockSizeBytes:Int) -> NSData {
-        switch (self) {
-        case PKCS_7:
-            return PKCS7(data: data).addPadding(UInt8(blockSizeBytes))
-        case None:
-            return data
-        }
-    }
-    
-    public func removePadding(data:NSData) -> NSData {
-        switch (self) {
-        case PKCS_7:
-            return PKCS7(data: data).removePadding()
-        case None:
-            return data
-        }
-    }
-
-}

+ 0 - 7
CryptoSwift/Playground/CryptoPlayground.playground/contents.xcplayground

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<playground version='3.0' sdk='iphonesimulator'>
-    <sections>
-        <code source-file-name='section-1.swift'/>
-    </sections>
-    <timeline fileName='timeline.xctimeline'/>
-</playground>

+ 0 - 7
CryptoSwift/Playground/CryptoPlayground.playground/section-1.swift

@@ -1,7 +0,0 @@
-// Playground - noun: a place where people can play
-
-import Foundation
-import CryptoSwift
-
-let plaintext = "Lorem ipsum"
-let MD5 = plaintext.md5()

+ 0 - 7
CryptoSwift/Poly1305.swift

@@ -88,13 +88,6 @@ public class Poly1305 {
     
     :returns: Message Authentication Code
     */
-    class internal func authenticate(# key: NSData, message: NSData) -> NSData? {
-        if let mac = Poly1305.authenticate(key: key.bytes(), message: message.bytes()) {
-            return NSData(bytes: mac, length: mac.count)
-        }
-        return nil
-    }
-
     class internal func authenticate(# key: [UInt8], message: [UInt8]) -> [UInt8]? {
         return Poly1305(key)?.authenticate(message: message)
     }

+ 9 - 5
CryptoSwift/SHA1.swift

@@ -8,7 +8,12 @@
 
 import Foundation
 
-class SHA1 : CryptoSwift.HashBase {
+class SHA1 : CryptoSwift.HashBase, _Hash {
+    var size:Int = 20 // 160 / 8
+    
+    override init(_ message: NSData) {
+        super.init(message)
+    }
     
     private let h:[UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
         
@@ -80,7 +85,6 @@ class SHA1 : CryptoSwift.HashBase {
                 C = rotateLeft(B, 30)
                 B = A
                 A = temp
-                
             }
             
             hh[0] = (hh[0] &+ A) & 0xffffffff
@@ -92,11 +96,11 @@ class SHA1 : CryptoSwift.HashBase {
         
         // Produce the final hash value (big-endian) as a 160 bit number:
         var buf: NSMutableData = NSMutableData();
-        hh.map({ (item) -> () in
+        for item in hh {
             var i:UInt32 = item.bigEndian
             buf.appendBytes(&i, length: sizeofValue(i))
-        })
+        }
         
-        return buf.copy() as NSData;
+        return buf.copy() as! NSData;
     }    
 }

+ 61 - 18
CryptoSwift/SHA2.swift

@@ -8,12 +8,50 @@
 
 import Foundation
 
-class SHA2 : CryptoSwift.HashBase {
+
+class SHA2 : HashBase, _Hash {
+    var size:Int { return variant.rawValue }
+    let variant:SHA2.Variant
     
-    enum variant {
+    enum Variant: RawRepresentable {
         case sha224, sha256, sha384, sha512
         
-        func h() -> [UInt64] {
+        typealias RawValue = Int
+        var rawValue: RawValue {
+            switch (self) {
+            case .sha224:
+                return 224
+            case .sha256:
+                return 256
+            case .sha384:
+                return 384
+            case .sha512:
+                return 512
+            }
+        }
+        
+        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
+            }
+        }
+        
+        var size:Int { return self.rawValue }
+        
+        private var h:[UInt64] {
             switch (self) {
             case .sha224:
                 return [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
@@ -26,7 +64,7 @@ class SHA2 : CryptoSwift.HashBase {
             }
         }
         
-        func k() -> [UInt64] {
+        private var k:[UInt64] {
             switch (self) {
             case .sha224, .sha256:
                 return [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
@@ -57,7 +95,7 @@ class SHA2 : CryptoSwift.HashBase {
             }
         }
         
-        func resultingArray<T>(hh:[T]) -> [T] {
+        private func resultingArray<T>(hh:[T]) -> [T] {
             var finalHH:[T] = hh;
             switch (self) {
             case .sha224:
@@ -73,13 +111,18 @@ class SHA2 : CryptoSwift.HashBase {
         }
     }
     
-    //FIXME: I can't do Generic fuct out of calculate32 and calculate64 (UInt32 vs UInt64), but if you can - please do pull request.
-    func calculate32(variant: SHA2.variant) -> NSData {
+    init(_ message:NSData, variant: SHA2.Variant) {
+        self.variant = variant
+        super.init(message)
+    }
+    
+    //FIXME: I can't do Generic func out of calculate32 and calculate64 (UInt32 vs UInt64), but if you can - please do pull request.
+    func calculate32() -> NSData {
         var tmpMessage = self.prepare()
         
         // hash values
         var hh = [UInt32]()
-        variant.h().map({(h) -> () in
+        variant.h.map({(h) -> () in
             hh.append(UInt32(h))
         })
         
@@ -93,7 +136,7 @@ class SHA2 : CryptoSwift.HashBase {
             let chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
             // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15, big-endian
             // Extend the sixteen 32-bit words into sixty-four 32-bit words:
-            var M:[UInt32] = [UInt32](count: variant.k().count, repeatedValue: 0)
+            var M:[UInt32] = [UInt32](count: variant.k.count, repeatedValue: 0)
             for x in 0..<M.count {
                 switch (x) {
                 case 0...15:
@@ -119,13 +162,13 @@ class SHA2 : CryptoSwift.HashBase {
             var H = hh[7]
             
             // Main loop
-            for j in 0..<variant.k().count {
+            for j in 0..<variant.k.count {
                 let s0 = rotateRight(A,2) ^ rotateRight(A,13) ^ rotateRight(A,22)
                 let maj = (A & B) ^ (A & C) ^ (B & C)
                 let t2 = s0 &+ maj
                 let s1 = rotateRight(E,6) ^ rotateRight(E,11) ^ rotateRight(E,25)
                 let ch = (E & F) ^ ((~E) & G)
-                let t1 = H &+ s1 &+ ch &+ UInt32(variant.k()[j]) &+ M[j]
+                let t1 = H &+ s1 &+ ch &+ UInt32(variant.k[j]) &+ M[j]
                 
                 H = G
                 G = F
@@ -155,15 +198,15 @@ class SHA2 : CryptoSwift.HashBase {
             buf.appendBytes(&i, length: sizeofValue(i))
         })
         
-        return buf.copy() as NSData;
+        return buf.copy() as! NSData;
     }
     
-    func calculate64(variant: SHA2.variant) -> NSData {
+    func calculate64() -> NSData {
         var tmpMessage = self.prepare(128)
         
         // hash values
         var hh = [UInt64]()
-        variant.h().map({(h) -> () in
+        variant.h.map({(h) -> () in
             hh.append(h)
         })
         
@@ -177,7 +220,7 @@ class SHA2 : CryptoSwift.HashBase {
             var chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
             // break chunk into sixteen 64-bit words M[j], 0 ≤ j ≤ 15, big-endian
             // Extend the sixteen 64-bit words into eighty 64-bit words:
-            var M = [UInt64](count: variant.k().count, repeatedValue: 0)
+            var M = [UInt64](count: variant.k.count, repeatedValue: 0)
             for x in 0..<M.count {
                 switch (x) {
                 case 0...15:
@@ -203,13 +246,13 @@ class SHA2 : CryptoSwift.HashBase {
             var H = hh[7]
             
             // Main loop
-            for j in 0..<variant.k().count {
+            for j in 0..<variant.k.count {
                 let s0 = rotateRight(A,28) ^ rotateRight(A,34) ^ rotateRight(A,39)
                 let maj = (A & B) ^ (A & C) ^ (B & C)
                 let t2 = s0 &+ maj
                 let s1 = rotateRight(E,14) ^ rotateRight(E,18) ^ rotateRight(E,41)
                 let ch = (E & F) ^ ((~E) & G)
-                let t1 = H &+ s1 &+ ch &+ variant.k()[j] &+ UInt64(M[j])
+                let t1 = H &+ s1 &+ ch &+ variant.k[j] &+ UInt64(M[j])
                 
                 H = G
                 G = F
@@ -239,6 +282,6 @@ class SHA2 : CryptoSwift.HashBase {
             buf.appendBytes(&i, length: sizeofValue(i))
         })
         
-        return buf.copy() as NSData;
+        return buf.copy() as! NSData;
     }
 }

+ 1 - 1
CryptoSwift/UInt32Extension.swift

@@ -14,7 +14,7 @@ extension UInt32 {
         return arrayOfBytes(self, length: totalBytes)
     }
 
-    public static func withBytes(bytes: Slice<Byte>) -> UInt32 {
+    public static func withBytes(bytes: ArraySlice<UInt8>) -> UInt32 {
         return UInt32.withBytes(Array(bytes))
     }
 

+ 1 - 1
CryptoSwift/UInt64Extension.swift

@@ -14,7 +14,7 @@ extension UInt64 {
         return arrayOfBytes(self, length: totalBytes)
     }
 
-    public static func withBytes(bytes: Slice<UInt8>) -> UInt64 {
+    public static func withBytes(bytes: ArraySlice<UInt8>) -> UInt64 {
         return UInt64.withBytes(Array(bytes))
     }
 

+ 23 - 0
CryptoSwift/Utils.swift

@@ -8,6 +8,10 @@
 
 import Foundation
 
+func rotateLeft(v:UInt8, n:UInt8) -> UInt8 {
+    return ((v << n) & 0xFF) | (v >> (8 - n))
+}
+
 func rotateLeft(v:UInt16, n:UInt16) -> UInt16 {
     return ((v << n) & 0xFFFF) | (v >> (16 - n))
 }
@@ -40,4 +44,23 @@ func reverseBytes(value: UInt32) -> UInt32 {
     var tmp1 = ((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8)
     var tmp2 = ((value & 0x00FF0000) >> 8)  | ((value & 0xFF000000) >> 24)
     return tmp1 | tmp2
+}
+
+func xor(a: [UInt8], b:[UInt8]) -> [UInt8] {
+    var xored = [UInt8](count: a.count, repeatedValue: 0)
+    for i in 0..<xored.count {
+        xored[i] = a[i] ^ b[i]
+    }
+    return xored
+}
+
+func perf(text: String, closure: () -> ()) {
+    let measurementStart = NSDate();
+    
+    closure()
+    
+    let measurementStop = NSDate();
+    let executionTime = measurementStop.timeIntervalSinceDate(measurementStart)
+    
+    println("\(text) \(executionTime)");
 }

+ 81 - 30
CryptoSwiftTests/AESTests.swift

@@ -21,11 +21,11 @@ class AESTests: XCTestCase {
         
         let expected:[UInt8] = [0xae,0x8c,0x59,0x95,0xb2,0x6f,0x8e,0x3d,0xb0,0x6f,0x0a,0xa5,0xfe,0xc4,0xf0,0xc2];
         
-        if let aes = AES(key: NSData.withBytes(key), iv: NSData.withBytes(iv), blockMode: .CBC) {
-            let encrypted = aes.encrypt(NSData.withBytes(input), addPadding: false)
-            XCTAssertEqual(encrypted!, NSData.withBytes(expected), "encryption failed")
-            let decrypted = aes.decrypt(encrypted!)
-            XCTAssertEqual(decrypted!, NSData.withBytes(input), "decryption failed")
+        if let aes = AES(key: key, iv: iv, blockMode: .CBC) {
+            let encrypted = aes.encrypt(input, padding: nil)
+            XCTAssertEqual(encrypted!, expected, "encryption failed")
+            let decrypted = aes.decrypt(encrypted!, padding: nil)
+            XCTAssertEqual(decrypted!, input, "decryption failed")
         } else {
             XCTAssert(false, "failed")
         }
@@ -42,11 +42,11 @@ class AESTests: XCTestCase {
             0xd8, 0xcd, 0xb7, 0x80,
             0x70, 0xb4, 0xc5, 0x5a];
         
-        if let aes = AES(key: NSData.withBytes(aesKey), blockMode: .ECB) {
-            let encrypted = aes.encrypt(NSData.withBytes(input), addPadding: false)
-            XCTAssertEqual(encrypted!, NSData.withBytes(expected), "encryption failed")
-            let decrypted = aes.decrypt(encrypted!, removePadding: false)
-            XCTAssertEqual(decrypted!, NSData.withBytes(input), "decryption failed")
+        if let aes = AES(key: aesKey, blockMode: .ECB) {
+            let encrypted = aes.encrypt(input, padding: nil)
+            XCTAssertEqual(encrypted!, expected, "encryption failed")
+            let decrypted = aes.decrypt(encrypted!, padding: nil)
+            XCTAssertEqual(decrypted!, input, "decryption failed")
         } else {
             XCTAssert(false, "failed")
         }
@@ -58,12 +58,12 @@ class AESTests: XCTestCase {
         let plaintext:[UInt8] = [0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a]
         let expected:[UInt8] = [0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d];
         
-        if let aes = AES(key: NSData.withBytes(key), iv:NSData.withBytes(iv), blockMode: .CBC) {
+        if let aes = AES(key: key, iv:iv, blockMode: .CBC) {
             XCTAssertTrue(aes.blockMode == .CBC, "Invalid block mode")
-            let encrypted = aes.encrypt(NSData.withBytes(plaintext), addPadding: false)
-            XCTAssertEqual(encrypted!, NSData.withBytes(expected), "encryption failed")
-            let decrypted = aes.decrypt(encrypted!, removePadding: false)
-            XCTAssertEqual(decrypted!, NSData.withBytes(plaintext), "decryption failed")
+            let encrypted = aes.encrypt(plaintext, padding: nil)
+            XCTAssertEqual(encrypted!, expected, "encryption failed")
+            let decrypted = aes.decrypt(encrypted!, padding: nil)
+            XCTAssertEqual(decrypted!, plaintext, "decryption failed")
         } else {
             XCTAssert(false, "failed")
         }
@@ -75,12 +75,12 @@ class AESTests: XCTestCase {
         let plaintext:[UInt8] = [0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a]
         let expected:[UInt8] = [0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20,0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a];
         
-        if let aes = AES(key: NSData.withBytes(key), iv:NSData.withBytes(iv), blockMode: .CFB) {
+        if let aes = AES(key: key, iv:iv, blockMode: .CFB) {
             XCTAssertTrue(aes.blockMode == .CFB, "Invalid block mode")
-            let encrypted = aes.encrypt(NSData.withBytes(plaintext), addPadding: false)
-            XCTAssertEqual(encrypted!, NSData.withBytes(expected), "encryption failed")
-            let decrypted = aes.decrypt(encrypted!, removePadding: false)
-            XCTAssertEqual(decrypted!, NSData.withBytes(plaintext), "decryption failed")
+            let encrypted = aes.encrypt(plaintext, padding: nil)
+            XCTAssertEqual(encrypted!, expected, "encryption failed")
+            let decrypted = aes.decrypt(encrypted!, padding: nil)
+            XCTAssertEqual(decrypted!, plaintext, "decryption failed")
         } else {
             XCTAssert(false, "failed")
         }
@@ -97,9 +97,10 @@ class AESTests: XCTestCase {
             [0xcd, 0x60, 0xe0, 0xe7],
             [0xba, 0x70, 0xe1, 0x8c]]
         
-        let substituted = AES(key: NSData.withBytes(aesKey), blockMode: .CBC)!.subBytes(input)
+        var substituted = input
+        AES(key: aesKey, blockMode: .CBC)!.subBytes(&substituted)
         XCTAssertTrue(compareMatrix(expected, substituted), "subBytes failed")
-        let inverted = AES(key: NSData.withBytes(aesKey), blockMode: .CBC)!.invSubBytes(substituted)
+        let inverted = AES(key: aesKey, blockMode: .CBC)!.invSubBytes(substituted)
         XCTAssertTrue(compareMatrix(input, inverted), "invSubBytes failed")
     }
     
@@ -114,21 +115,21 @@ class AESTests: XCTestCase {
             [0xe0, 0xe1, 0xb7, 0xd0],
             [0x8c, 0x4, 0x51, 0xe7]]
         
-        let shifted = AES(key: NSData.withBytes(aesKey), blockMode: .CBC)!.shiftRows(input)
+        let shifted = AES(key: aesKey, blockMode: .CBC)!.shiftRows(input)
         XCTAssertTrue(compareMatrix(expected, shifted), "shiftRows failed")
-        let inverted = AES(key: NSData.withBytes(aesKey), blockMode: .CBC)!.invShiftRows(shifted)
+        let inverted = AES(key: aesKey, blockMode: .CBC)!.invShiftRows(shifted)
         XCTAssertTrue(compareMatrix(input, inverted), "invShiftRows failed")
     }
     
     func testAES_multiply() {
-        XCTAssertTrue(AES(key: NSData.withBytes(aesKey), blockMode: .CBC)?.multiplyPolys(0x0e, 0x5f) == 0x17, "Multiplication failed")
+        XCTAssertTrue(AES(key: aesKey, blockMode: .CBC)?.multiplyPolys(0x0e, 0x5f) == 0x17, "Multiplication failed")
     }
     
     func testAES_expandKey() {
         let expected:[UInt8] = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xd6, 0xaa, 0x74, 0xfd, 0xd2, 0xaf, 0x72, 0xfa, 0xda, 0xa6, 0x78, 0xf1, 0xd6, 0xab, 0x76, 0xfe, 0xb6, 0x92, 0xcf, 0xb, 0x64, 0x3d, 0xbd, 0xf1, 0xbe, 0x9b, 0xc5, 0x0, 0x68, 0x30, 0xb3, 0xfe, 0xb6, 0xff, 0x74, 0x4e, 0xd2, 0xc2, 0xc9, 0xbf, 0x6c, 0x59, 0xc, 0xbf, 0x4, 0x69, 0xbf, 0x41, 0x47, 0xf7, 0xf7, 0xbc, 0x95, 0x35, 0x3e, 0x3, 0xf9, 0x6c, 0x32, 0xbc, 0xfd, 0x5, 0x8d, 0xfd, 0x3c, 0xaa, 0xa3, 0xe8, 0xa9, 0x9f, 0x9d, 0xeb, 0x50, 0xf3, 0xaf, 0x57, 0xad, 0xf6, 0x22, 0xaa, 0x5e, 0x39, 0xf, 0x7d, 0xf7, 0xa6, 0x92, 0x96, 0xa7, 0x55, 0x3d, 0xc1, 0xa, 0xa3, 0x1f, 0x6b, 0x14, 0xf9, 0x70, 0x1a, 0xe3, 0x5f, 0xe2, 0x8c, 0x44, 0xa, 0xdf, 0x4d, 0x4e, 0xa9, 0xc0, 0x26, 0x47, 0x43, 0x87, 0x35, 0xa4, 0x1c, 0x65, 0xb9, 0xe0, 0x16, 0xba, 0xf4, 0xae, 0xbf, 0x7a, 0xd2, 0x54, 0x99, 0x32, 0xd1, 0xf0, 0x85, 0x57, 0x68, 0x10, 0x93, 0xed, 0x9c, 0xbe, 0x2c, 0x97, 0x4e, 0x13, 0x11, 0x1d, 0x7f, 0xe3, 0x94, 0x4a, 0x17, 0xf3, 0x7, 0xa7, 0x8b, 0x4d, 0x2b, 0x30, 0xc5]
         
-        if let aes = AES(key: NSData.withBytes(aesKey), blockMode: .CBC) {
-            XCTAssertEqual(expected, aes.expandKey(), "expandKey failed")
+        if let aes = AES(key: aesKey, blockMode: .CBC) {
+            XCTAssertEqual(expected, aes.expandedKey, "expandKey failed")
         } else {
             XCTAssert(false, "")
         }
@@ -145,8 +146,8 @@ class AESTests: XCTestCase {
             [32, 96, 160, 224],
             [48, 112, 176, 240]]
         
-        if let aes = AES(key: NSData.withBytes(aesKey), blockMode: .CBC) {
-            let result = aes.addRoundKey(input, aes.expandKey(), 0)
+        if let aes = AES(key: aesKey, blockMode: .CBC) {
+            let result = aes.addRoundKey(input, aes.expandedKey, 0)
             XCTAssertTrue(compareMatrix(expected, result), "addRoundKey failed")
         } else {
             XCTAssert(false, "")
@@ -164,7 +165,7 @@ class AESTests: XCTestCase {
             [0x64, 0xbc, 0x3b, 0xf9],
             [0x15, 0x92, 0x29, 0x1a]]
         
-        if let aes = AES(key: NSData.withBytes(aesKey), blockMode: .CBC) {
+        if let aes = AES(key: aesKey, blockMode: .CBC) {
             let mixed = aes.mixColumns(input)
             XCTAssertTrue(compareMatrix(expected, mixed), "mixColumns failed")
             let inverted = aes.invMixColumns(mixed)
@@ -173,5 +174,55 @@ class AESTests: XCTestCase {
             XCTAssert(false, "")
         }
     }
+    
+    func testAESPerformance() {
+        let key:[UInt8] = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c];
+        let iv:[UInt8] = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F]
+        let message = [UInt8](count: 1024 * 1024, repeatedValue: 7)
+        self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
+            self.startMeasuring()
+            let encrypted = AES(key: key, iv: iv, blockMode: .CBC)?.encrypt(message, padding: PKCS7())
+            self.stopMeasuring()
+        })
+    }
+    
+    func testAESPerformanceCommonCrypto() {
+        let key:[UInt8] = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c];
+        let iv:[UInt8] = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F]
+        let message = [UInt8](count: 1024 * 1024, repeatedValue: 7)
+        
+        self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
+            self.startMeasuring()
+            
+            let keyData     = NSData.withBytes(key)
+            let keyBytes    = UnsafePointer<Void>(keyData.bytes)
+            let ivData      = NSData.withBytes(iv)
+            let ivBytes     = UnsafePointer<Void>(ivData.bytes)
+            
+            let data = NSData.withBytes(message)
+            let dataLength    = data.length
+            let dataBytes     = UnsafePointer<Void>(data.bytes)
+            
+            let cryptData    = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
+            var cryptPointer = UnsafeMutablePointer<Void>(cryptData!.mutableBytes)
+            let cryptLength  = cryptData!.length
+            
+            var numBytesEncrypted:Int = 0
+            
+            var cryptStatus = CCCrypt(
+                UInt32(kCCEncrypt),
+                UInt32(kCCAlgorithmAES128),
+                UInt32(kCCOptionPKCS7Padding),
+                keyBytes,
+                key.count,
+                ivBytes,
+                dataBytes,
+                dataLength,
+                cryptPointer, cryptLength,
+                &numBytesEncrypted)
+
+            self.stopMeasuring()
+        })
+    }
 
 }

+ 20 - 11
CryptoSwiftTests/ChaCha20Tests.swift

@@ -46,31 +46,40 @@ class ChaCha20Tests: XCTestCase {
         ]
         
         for (var idx = 0; idx < keys.count; idx++) {
-            let keyData = NSData(bytes: keys[idx], length: keys[idx].count)
-            let ivData = NSData(bytes: ivs[idx], length: ivs[idx].count)
             
             let expectedHex = expectedHexes[idx]
-            //println(countElements(expectedHex) / 2);
-            let message = [UInt8](count: (countElements(expectedHex) / 2), repeatedValue: 0)
-            let messageData = NSData(bytes: message, length: message.count);
+            let message = [UInt8](count: (count(expectedHex) / 2), repeatedValue: 0)
             
-            let setup = (key: keyData, iv: ivData)
-            var encrypted = Cipher.ChaCha20(setup).encrypt(messageData)
-            XCTAssertNotNil(encrypted, "")
+            let setup = (key: keys[idx], iv: ivs[idx])
+            var encrypted = Cipher.ChaCha20(setup).encrypt(message)
+            XCTAssert(encrypted != nil, "missing")
             if let encrypted = encrypted {
                 var decrypted = Cipher.ChaCha20(setup).decrypt(encrypted)
-                XCTAssertNotNil(decrypted, "")
+                XCTAssert(decrypted != nil, "missing")
                 if let decrypted = decrypted {
-                    XCTAssertEqual(messageData, decrypted, "ChaCha20 decryption failed");
+                    XCTAssertEqual(message, decrypted, "ChaCha20 decryption failed");
                 }
                 
                 // check extension
+                let messageData = NSData(bytes: message, length: message.count);
                 let encrypted2 = messageData.encrypt(Cipher.ChaCha20(setup))
                 XCTAssertNotNil(encrypted2, "")
                 if let encrypted2 = encrypted2 {
-                    XCTAssertEqual(encrypted, encrypted2, "ChaCha20 extension failed")
+                    XCTAssertEqual(NSData.withBytes(encrypted), encrypted2, "ChaCha20 extension failed")
                 }
             }
         }
     }
+    
+    func testChaCha20Performance() {
+        let key:[UInt8] = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c];
+        let iv:[UInt8] = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F]
+        let message = [UInt8](count: (1024 * 1024) * 1, repeatedValue: 7)
+        self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
+            self.startMeasuring()
+            let encrypted = ChaCha20(key: key, iv: iv)?.encrypt(message)
+            self.stopMeasuring()
+            XCTAssert(encrypted != nil, "not encrypted")
+        })
+    }
 }

+ 10 - 0
CryptoSwiftTests/ExtensionsTest.swift

@@ -20,6 +20,16 @@ class ExtensionsTest: XCTestCase {
         super.tearDown()
     }
 
+    func testArrayChunksPerformance() {
+        self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
+            let message = [UInt8](count: 1024 * 1024, repeatedValue: 7)
+            self.startMeasuring()
+            let blocks = message.chunks(AES.blockSize)
+            self.stopMeasuring()
+        })
+    }
+
+    
     func testIntExtension() {
         let i1:Int = 1024
         let i1Array = i1.bytes(32 / 8) // 32 bit

+ 24 - 6
CryptoSwiftTests/HMACTests.swift

@@ -26,8 +26,8 @@ class HMACTests: XCTestCase {
         let msg:[UInt8] = []
         let expectedMac:[UInt8] = [0x74,0xe6,0xf7,0x29,0x8a,0x9c,0x2d,0x16,0x89,0x35,0xf5,0x8c,0x00,0x1b,0xad,0x88]
         
-        let hmac = Authenticator.HMAC(key: NSData.withBytes(key), variant: .md5).authenticate(NSData.withBytes(msg))
-        XCTAssertEqual(hmac!, NSData.withBytes(expectedMac), "Invalid authentication result")
+        let hmac = Authenticator.HMAC(key: key, variant: .md5).authenticate(msg)
+        XCTAssertEqual(hmac!, expectedMac, "Invalid authentication result")
     }
     
     func testSHA1() {
@@ -35,8 +35,8 @@ class HMACTests: XCTestCase {
         let msg:[UInt8] = []
         let expectedMac:[UInt8] = [0xfb,0xdb,0x1d,0x1b,0x18,0xaa,0x6c,0x08,0x32,0x4b,0x7d,0x64,0xb7,0x1f,0xb7,0x63,0x70,0x69,0x0e,0x1d]
         
-        let hmac = Authenticator.HMAC(key: NSData.withBytes(key), variant: .sha1).authenticate(NSData.withBytes(msg))
-        XCTAssertEqual(hmac!, NSData.withBytes(expectedMac), "Invalid authentication result")
+        let hmac = Authenticator.HMAC(key: key, variant: .sha1).authenticate(msg)
+        XCTAssertEqual(hmac!, expectedMac, "Invalid authentication result")
     }
 
     func testSHA256() {
@@ -44,8 +44,26 @@ class HMACTests: XCTestCase {
         let msg:[UInt8] = []
         let expectedMac:[UInt8] = [0xb6,0x13,0x67,0x9a,0x08,0x14,0xd9,0xec,0x77,0x2f,0x95,0xd7,0x78,0xc3,0x5f,0xc5,0xff,0x16,0x97,0xc4,0x93,0x71,0x56,0x53,0xc6,0xc7,0x12,0x14,0x42,0x92,0xc5,0xad]
         
-        let hmac = Authenticator.HMAC(key: NSData.withBytes(key), variant: .sha256).authenticate(NSData.withBytes(msg))
-        XCTAssertEqual(hmac!, NSData.withBytes(expectedMac), "Invalid authentication result")
+        let hmac = Authenticator.HMAC(key: key, variant: .sha256).authenticate(msg)
+        XCTAssertEqual(hmac!, expectedMac, "Invalid authentication result")
+    }
+
+    func testSHA384() {
+        let key:[UInt8] = []
+        let msg:[UInt8] = []
+        let expectedMac:[UInt8] = [0x6c, 0x1f, 0x2e, 0xe9, 0x38, 0xfa, 0xd2, 0xe2, 0x4b, 0xd9, 0x12, 0x98, 0x47, 0x43, 0x82, 0xca, 0x21, 0x8c, 0x75, 0xdb, 0x3d, 0x83, 0xe1, 0x14, 0xb3, 0xd4, 0x36, 0x77, 0x76, 0xd1, 0x4d, 0x35, 0x51, 0x28, 0x9e, 0x75, 0xe8, 0x20, 0x9c, 0xd4, 0xb7, 0x92, 0x30, 0x28, 0x40, 0x23, 0x4a, 0xdc]
+
+        let hmac = Authenticator.HMAC(key: key, variant: .sha384).authenticate(msg)
+        XCTAssertEqual(hmac!, expectedMac, "Invalid authentication result")
+    }
+
+    func testSHA512() {
+        let key:[UInt8] = []
+        let msg:[UInt8] = []
+        let expectedMac:[UInt8] = [0xb9, 0x36, 0xce, 0xe8, 0x6c, 0x9f, 0x87, 0xaa, 0x5d, 0x3c, 0x6f, 0x2e, 0x84, 0xcb, 0x5a, 0x42, 0x39, 0xa5, 0xfe, 0x50, 0x48, 0x0a, 0x6e, 0xc6, 0x6b, 0x70, 0xab, 0x5b, 0x1f, 0x4a, 0xc6, 0x73, 0x0c, 0x6c, 0x51, 0x54, 0x21, 0xb3, 0x27, 0xec, 0x1d, 0x69, 0x40, 0x2e, 0x53, 0xdf, 0xb4, 0x9a, 0xd7, 0x38, 0x1e, 0xb0, 0x67, 0xb3, 0x38, 0xfd, 0x7b, 0x0c, 0xb2, 0x22, 0x47, 0x22, 0x5d, 0x47]
+
+        let hmac = Authenticator.HMAC(key: key, variant: .sha512).authenticate(msg)
+        XCTAssertEqual(hmac!, expectedMac, "Invalid authentication result")
     }
 
     func testSHA384() {

+ 8 - 12
CryptoSwiftTests/HashTests.swift

@@ -76,12 +76,10 @@ class CryptoSwiftTests: XCTestCase {
     
     func testMD5PerformanceSwift() {
         self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
-            let buf = UnsafeMutablePointer<Byte>(calloc(2048, UInt(sizeof(UInt8))))
+            let buf = UnsafeMutablePointer<UInt8>(calloc(2048, sizeof(UInt8)))
             let data = NSData(bytes: buf, length: 2048)
             self.startMeasuring()
-            for _ in [0...1000] {
-                Hash.md5(data).calculate()
-            }
+            Hash.md5(data).calculate()
             self.stopMeasuring()
             buf.dealloc(1024)
             buf.destroy()
@@ -90,16 +88,14 @@ class CryptoSwiftTests: XCTestCase {
     
     func testMD5PerformanceCommonCrypto() {
         self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
-            let buf = UnsafeMutablePointer<Byte>(calloc(2048, UInt(sizeof(UInt8))))
+            let buf = UnsafeMutablePointer<UInt8>(calloc(2048, sizeof(UInt8)))
             let data = NSData(bytes: buf, length: 2048)
             self.startMeasuring()
-            for _ in [0...1000] {
-                var outbuf = UnsafeMutablePointer<UInt8>.alloc(Int(CC_MD5_DIGEST_LENGTH))
-                CC_MD5(data.bytes, CC_LONG(data.length), outbuf)
-                let output = NSData(bytes: outbuf, length: Int(CC_MD5_DIGEST_LENGTH));
-                outbuf.dealloc(Int(CC_MD5_DIGEST_LENGTH))
-                outbuf.destroy()
-            }
+            var outbuf = UnsafeMutablePointer<UInt8>.alloc(Int(CC_MD5_DIGEST_LENGTH))
+            CC_MD5(data.bytes, CC_LONG(data.length), outbuf)
+            let output = NSData(bytes: outbuf, length: Int(CC_MD5_DIGEST_LENGTH));
+            outbuf.dealloc(Int(CC_MD5_DIGEST_LENGTH))
+            outbuf.destroy()
             self.stopMeasuring()
             buf.dealloc(1024)
             buf.destroy()

+ 12 - 12
CryptoSwiftTests/PaddingTests.swift

@@ -14,27 +14,27 @@ class PaddingTests: XCTestCase {
     func testPKCS7_0() {
         let input:[UInt8]    = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]
         let expected:[UInt8] = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16]
-        let padded = PKCS7(data: NSData.withBytes(input)).addPadding(16)
-        XCTAssertEqual(padded, NSData.withBytes(expected), "PKCS7 failed")
-        let clean = PKCS7(data: padded).removePadding()
-        XCTAssertEqual(clean, NSData.withBytes(input), "PKCS7 failed")
+        let padded = PKCS7().add(input, blockSize: 16)
+        XCTAssertEqual(padded, expected, "PKCS7 failed")
+        let clean = PKCS7().remove(padded)
+        XCTAssertEqual(clean, input, "PKCS7 failed")
     }
     
     func testPKCS7_1() {
         let input:[UInt8]    = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]
         let expected:[UInt8] = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,1]
-        let padded = PKCS7(data: NSData.withBytes(input)).addPadding(16)
-        XCTAssertEqual(padded, NSData.withBytes(expected), "PKCS7 failed")
-        let clean = PKCS7(data: padded).removePadding()
-        XCTAssertEqual(clean, NSData.withBytes(input), "PKCS7 failed")
+        let padded = PKCS7().add(input, blockSize: 16)
+        XCTAssertEqual(padded, expected, "PKCS7 failed")
+        let clean = PKCS7().remove(padded)
+        XCTAssertEqual(clean, input, "PKCS7 failed")
     }
     
     func testPKCS7_2() {
         let input:[UInt8]    = [1,2,3,4,5,6,7,8,9,0,1,2,3,4]
         let expected:[UInt8] = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,2,2]
-        let padded = PKCS7(data: NSData.withBytes(input)).addPadding(16)
-        XCTAssertEqual(padded, NSData.withBytes(expected), "PKCS7 failed")
-        let clean = PKCS7(data: padded).removePadding()
-        XCTAssertEqual(clean, NSData.withBytes(input), "PKCS7 failed")
+        let padded = PKCS7().add(input, blockSize: 16)
+        XCTAssertEqual(padded, expected, "PKCS7 failed")
+        let clean = PKCS7().remove(padded)
+        XCTAssertEqual(clean, input, "PKCS7 failed")
     }
 }

+ 10 - 5
CryptoSwiftTests/Poly1305Tests.swift

@@ -26,13 +26,18 @@ class Poly1305Tests: XCTestCase {
         let msg:[UInt8] = [0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1]
         let expectedMac:[UInt8] = [0xdd,0xb9,0xda,0x7d,0xdd,0x5e,0x52,0x79,0x27,0x30,0xed,0x5c,0xda,0x5f,0x90,0xa4]
         
-        let mac = Authenticator.Poly1305(key: NSData.withBytes(key)).authenticate(NSData.withBytes(msg))
-        XCTAssertEqual(mac!, NSData.withBytes(expectedMac), "Invalid authentication result")
+        if let mac = Authenticator.Poly1305(key: key).authenticate(msg) {
+            XCTAssertEqual(mac, expectedMac, "Invalid authentication result")
+        } else {
+            XCTFail("Missing MAC")
+        }
         
         // extensions
         let msgData = NSData.withBytes(msg)
-        let mac2 = msgData.authenticate(Authenticator.Poly1305(key: NSData.withBytes(key)))
-        XCTAssertNotNil(mac2, "")
-        XCTAssertEqual(mac2!, NSData.withBytes(expectedMac), "Invalid authentication result")
+        if let mac2 = msgData.authenticate(Authenticator.Poly1305(key: key)) {
+            XCTAssertEqual(mac2, NSData.withBytes(expectedMac), "Invalid authentication result")
+        } else {
+            XCTFail("Missing MAC")
+        }
     }
 }

+ 29 - 22
README.md

@@ -56,12 +56,18 @@ By default project is setup for iOS. You need to switch to OSX SDK manually [see
 
 ####CocoaPods
 
-You can use [CocoaPods](http://cocoapods.org/?q=cryptoSwift). You need version 0.36 or newer to use Swift framework.
+You can use [CocoaPods](http://cocoapods.org/?q=cryptoSwift).
 
 ```ruby
 pod 'CryptoSwift'
 ```
 
+or for newest version from specified branch of code:
+
+```ruby
+pod 'CryptoSwift', :git => "https://github.com/krzyzanowskim/CryptoSwift", :branch => "master"
+```
+ 
 ##Usage
 
 ```swift
@@ -105,7 +111,7 @@ if let hash = "123".md5() {
 Some content-encryption algorithms assume the input length is a multiple of k octets, where k is greater than one. For such algorithms, the input shall be padded.
 
 ```swift
-let paddedData = PKCS7(data: dataToEncrypt).addPadding(AES.blockSizeBytes())
+let paddedData = PKCS7().add(bytes, AES.blockSize)
 ```
 
 Working with Ciphers
@@ -113,8 +119,8 @@ Working with Ciphers
 ChaCha20
 
 ```swift
-let chacha20Encrypted = Cipher.ChaCha20(key: keyData, iv: ivData).encrypt(dataToEncrypt)
-let decryptedChaCha20 = Cipher.ChaCha20(key: keyData, iv: ivData).decrypt(encryptedData)
+let encrypted = Cipher.ChaCha20(key: key, iv: iv).encrypt(message)
+let decrypted = Cipher.ChaCha20(key: key, iv: iv).decrypt(encrypted)
 ```
 
 AES
@@ -122,38 +128,30 @@ AES
 Notice regarding padding: *Manual padding of data is optional and CryptoSwift by default always will add PKCS7 padding before encryption, and remove after decryption when __Cipher__ enum is used. If you need manually disable/enable padding, you can do this by setting parameter for encrypt()/decrypt() on class __AES__.*
 
 ```swift
-// 1. Add padding (Optional)
-let plaintextData = PKCS7(data: plaintextData).addPadding(AES.blockSizeBytes())
 
-// 2. Encrypt with key and random IV
-let keyData = NSData.withBytes([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
-let ivData:NSData = Cipher.randomIV(keyData)
+// 1. set key and random IV
+let key = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] as [UInt8]
+let iv = Cipher.randomIV(AES.blockSize)
 
-let encryptedData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).encrypt(plaintextData)
+// 2. encrypt
+let encrypted = AES(key: key, iv: iv, blockMode: .CBC)?.encrypt(message, padding: PKCS7())
 	
-// 3. decrypt with key and IV
-let decryptedData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).decrypt(encryptedData)
+// 3. decrypt with the same key and IV
+let decrypted = AES(key: key, iv: iv, blockMode: .CBC)?.decrypt(encryptedData, padding: PKCS7())
 	
-// 4. remove padding ONLY IF applied earlier (Optional)
-let plaintextData = PKCS7(data: decryptedData).removePadding()	
 ```
 	
 AES without data padding
 
 ```swift
-let aes = AES(key: keyData, iv: ivData, blockMode: .CBC) // CBC is default
-let encryptedData = aes?.encrypt(plaintextData, addPadding: false)
-let decryptedData = aes?.decrypt(encryptedData, removePadding: false)
+let encrypted = Cipher.AES(key: key, iv: iv, blockMode: .CBC).encrypt(plaintext)
 ```
 
 Using extensions
 	
 ```swift
-// convenience setup tuple
-let setup = (key: keyData, iv: ivData)
-
-let encrypted = dataToEncrypt.encrypt(Cipher.ChaCha20(setup))
-let decrypted = encrypted.decrypt(Cipher.ChaCha20(setup))
+let encrypted = dataToEncrypt.encrypt(Cipher.ChaCha20(key: key, iv: iv))
+let decrypted = encrypted.decrypt(Cipher.ChaCha20(key: key, iv: iv))
 ```
 	
 Message authenticators
@@ -163,6 +161,15 @@ Message authenticators
 let mac = Authenticator.Poly1305(key: key).authenticate(message)
 ```
 
+#####Conversion between NSData and [UInt8]
+
+For you convenience CryptoSwift provide two function to easily convert array of bytes to NSData and other way around:
+
+```swift
+let data  = NSData.withBytes([0x01,0x02,0x03])
+let bytes = data.bytes()
+```
+
 ##Contact
 Marcin Krzyżanowski [@krzyzanowskim](http://twitter.com/krzyzanowskim)