Procházet zdrojové kódy

Merge branch 'develop'

Marcin Krzyżanowski před 10 roky
rodič
revize
30a1e3d721
38 změnil soubory, kde provedl 796 přidání a 547 odebrání
  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|
 Pod::Spec.new do |s|
   s.name         = "CryptoSwift"
   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.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.description  = "Cryptography functions and helpers for Swift implemented in Swift. SHA, MD5, CRC, Poly1305, HMAC, ChaCha20, AES."
   s.homepage     = "https://github.com/krzyzanowskim/CryptoSwift"
   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 */; };
 		751C5C3D19B26B000094C75D /* Poly1305.swift in Sources */ = {isa = PBXBuildFile; fileRef = 751C5C3C19B26B000094C75D /* Poly1305.swift */; };
 		752DEF7719693EA000E17557 /* NSDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEF7619693EA000E17557 /* NSDataExtension.swift */; };
 		752DEF7719693EA000E17557 /* NSDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEF7619693EA000E17557 /* NSDataExtension.swift */; };
 		752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752E087A199FF27C005B0EA0 /* SHA1.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, ); }; };
 		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 */; };
 		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, ); }; };
 		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 */; };
 		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 */; };
 		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 */; };
 		755111E819B7B7DF00C2AD86 /* Authenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755111E719B7B7DF00C2AD86 /* Authenticator.swift */; };
 		7552614E1993051E000D2B20 /* Hash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7552614D1993051E000D2B20 /* Hash.swift */; };
 		7552614E1993051E000D2B20 /* Hash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7552614D1993051E000D2B20 /* Hash.swift */; };
 		755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755FB1D9199E347D00475437 /* ExtensionsTest.swift */; };
 		755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755FB1D9199E347D00475437 /* ExtensionsTest.swift */; };
 		7563B2E819B14D4300B152CD /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7563B2E719B14D4300B152CD /* Cipher.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 */; };
 		757DA2531A4ED0A4002BA3EF /* PaddingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */; };
 		757DA2551A4ED408002BA3EF /* AESTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2541A4ED408002BA3EF /* AESTests.swift */; };
 		757DA2551A4ED408002BA3EF /* AESTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2541A4ED408002BA3EF /* AESTests.swift */; };
 		757DA2571A4ED47B002BA3EF /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757DA2561A4ED47B002BA3EF /* Helpers.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 */; };
 		758A94291A65C67400E46135 /* HMACTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758A94271A65C59200E46135 /* HMACTests.swift */; };
 		758C764119B61AE500653BC6 /* Generics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758C764019B61AE500653BC6 /* Generics.swift */; };
 		758C764119B61AE500653BC6 /* Generics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758C764019B61AE500653BC6 /* Generics.swift */; };
 		758C764319B61DE900653BC6 /* UInt16Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758C764219B61DE900653BC6 /* UInt16Extension.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 */; };
 		758F3F781992F6CE0014BBDA /* UInt8Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758F3F771992F6CE0014BBDA /* UInt8Extension.swift */; };
 		7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7599C9C5199EA28700A3988B /* StringExtension.swift */; };
 		7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7599C9C5199EA28700A3988B /* StringExtension.swift */; };
 		759D481119B517BC005FF7FC /* BitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759D481019B517BC005FF7FC /* BitExtension.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 */; };
 		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 */; };
 		75B601EB197D6A6C0009B53D /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 754BE45519693E190098E6F3 /* CryptoSwift.framework */; };
 		75BC3AE31A4E412000ADF343 /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */; };
 		75BC3AE31A4E412000ADF343 /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */; };
 		75D94E2419B60C08007CB2A4 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D94E2319B60C08007CB2A4 /* Operators.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; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		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>"; };
 		75D94E2519B60C4F007CB2A4 /* UInt32Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UInt32Extension.swift; sourceTree = "<group>"; };
@@ -190,7 +191,6 @@
 		754BE44B19693E190098E6F3 = {
 		754BE44B19693E190098E6F3 = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				758F3F751992E57D0014BBDA /* Playground */,
 				754BE45719693E190098E6F3 /* CryptoSwift */,
 				754BE45719693E190098E6F3 /* CryptoSwift */,
 				754BE46419693E190098E6F3 /* CryptoSwiftTests */,
 				754BE46419693E190098E6F3 /* CryptoSwiftTests */,
 				754BE45619693E190098E6F3 /* Products */,
 				754BE45619693E190098E6F3 /* Products */,
@@ -214,9 +214,11 @@
 				7552614D1993051E000D2B20 /* Hash.swift */,
 				7552614D1993051E000D2B20 /* Hash.swift */,
 				7563B2E719B14D4300B152CD /* Cipher.swift */,
 				7563B2E719B14D4300B152CD /* Cipher.swift */,
 				75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */,
 				75BC3AE21A4E412000ADF343 /* CipherBlockMode.swift */,
-				757DA2501A4E5E95002BA3EF /* PaddingMode.swift */,
+				75A663A51AA0CAD00052110B /* Padding.swift */,
+				75B0A56F1AB1A1BB000BD8D2 /* PKCS5.swift */,
+				754C30B61AA13BC000E6FFA4 /* PKCS7.swift */,
 				755111E719B7B7DF00C2AD86 /* Authenticator.swift */,
 				755111E719B7B7DF00C2AD86 /* Authenticator.swift */,
-				754DD76D19A149AF00E52288 /* CryptoHashBase.swift */,
+				754DD76D19A149AF00E52288 /* HashBase.swift */,
 				750A545F1992D2680017DA75 /* MD5.swift */,
 				750A545F1992D2680017DA75 /* MD5.swift */,
 				752E087A199FF27C005B0EA0 /* SHA1.swift */,
 				752E087A199FF27C005B0EA0 /* SHA1.swift */,
 				75153D4119AA3C7900750381 /* SHA2.swift */,
 				75153D4119AA3C7900750381 /* SHA2.swift */,
@@ -225,7 +227,6 @@
 				751C5C3C19B26B000094C75D /* Poly1305.swift */,
 				751C5C3C19B26B000094C75D /* Poly1305.swift */,
 				758A94251A65AEB100E46135 /* HMAC.swift */,
 				758A94251A65AEB100E46135 /* HMAC.swift */,
 				75A74B261A1FF6B2004419F1 /* AES.swift */,
 				75A74B261A1FF6B2004419F1 /* AES.swift */,
-				757DA24E1A4E59F2002BA3EF /* PKCS7.swift */,
 				759D481019B517BC005FF7FC /* BitExtension.swift */,
 				759D481019B517BC005FF7FC /* BitExtension.swift */,
 				758F3F771992F6CE0014BBDA /* UInt8Extension.swift */,
 				758F3F771992F6CE0014BBDA /* UInt8Extension.swift */,
 				7547195019931802002FA5F1 /* IntExtension.swift */,
 				7547195019931802002FA5F1 /* IntExtension.swift */,
@@ -374,7 +375,6 @@
 			isa = PBXResourcesBuildPhase;
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				758F3F761992E57D0014BBDA /* Playground in Resources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -395,13 +395,13 @@
 			files = (
 			files = (
 				75D94E2819B60DDE007CB2A4 /* UInt64Extension.swift in Sources */,
 				75D94E2819B60DDE007CB2A4 /* UInt64Extension.swift in Sources */,
 				751C5C3D19B26B000094C75D /* Poly1305.swift in Sources */,
 				751C5C3D19B26B000094C75D /* Poly1305.swift in Sources */,
-				757DA2511A4E5E95002BA3EF /* PaddingMode.swift in Sources */,
 				7552614E1993051E000D2B20 /* Hash.swift in Sources */,
 				7552614E1993051E000D2B20 /* Hash.swift in Sources */,
 				75BC3AE31A4E412000ADF343 /* CipherBlockMode.swift in Sources */,
 				75BC3AE31A4E412000ADF343 /* CipherBlockMode.swift in Sources */,
 				7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */,
 				7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */,
 				7563B2E819B14D4300B152CD /* Cipher.swift in Sources */,
 				7563B2E819B14D4300B152CD /* Cipher.swift in Sources */,
 				752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */,
 				752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */,
 				75EB380119ABDD710002375A /* ChaCha20.swift in Sources */,
 				75EB380119ABDD710002375A /* ChaCha20.swift in Sources */,
+				75A663A61AA0CAD00052110B /* Padding.swift in Sources */,
 				750A54601992D2680017DA75 /* MD5.swift in Sources */,
 				750A54601992D2680017DA75 /* MD5.swift in Sources */,
 				75164E4919AD30AC00737F30 /* Utils.swift in Sources */,
 				75164E4919AD30AC00737F30 /* Utils.swift in Sources */,
 				758A94261A65AEB100E46135 /* HMAC.swift in Sources */,
 				758A94261A65AEB100E46135 /* HMAC.swift in Sources */,
@@ -411,12 +411,13 @@
 				7547195119931802002FA5F1 /* IntExtension.swift in Sources */,
 				7547195119931802002FA5F1 /* IntExtension.swift in Sources */,
 				758C764319B61DE900653BC6 /* UInt16Extension.swift in Sources */,
 				758C764319B61DE900653BC6 /* UInt16Extension.swift in Sources */,
 				75D94E2419B60C08007CB2A4 /* Operators.swift in Sources */,
 				75D94E2419B60C08007CB2A4 /* Operators.swift in Sources */,
+				75B0A5701AB1A1BB000BD8D2 /* PKCS5.swift in Sources */,
 				757EF7F519AAA82400586276 /* CRC.swift in Sources */,
 				757EF7F519AAA82400586276 /* CRC.swift in Sources */,
 				75D94E2619B60C4F007CB2A4 /* UInt32Extension.swift in Sources */,
 				75D94E2619B60C4F007CB2A4 /* UInt32Extension.swift in Sources */,
 				75A74B271A1FF6B2004419F1 /* AES.swift in Sources */,
 				75A74B271A1FF6B2004419F1 /* AES.swift in Sources */,
+				754C30B71AA13BC000E6FFA4 /* PKCS7.swift in Sources */,
 				755111E819B7B7DF00C2AD86 /* Authenticator.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 */,
 				758C764119B61AE500653BC6 /* Generics.swift in Sources */,
 				758F3F781992F6CE0014BBDA /* UInt8Extension.swift in Sources */,
 				758F3F781992F6CE0014BBDA /* UInt8Extension.swift in Sources */,
 				75153D4219AA3C7900750381 /* SHA2.swift in Sources */,
 				75153D4219AA3C7900750381 /* SHA2.swift in Sources */,
@@ -430,6 +431,7 @@
 				758A94291A65C67400E46135 /* HMACTests.swift in Sources */,
 				758A94291A65C67400E46135 /* HMACTests.swift in Sources */,
 				75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */,
 				75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */,
 				757DA2571A4ED47B002BA3EF /* Helpers.swift in Sources */,
 				757DA2571A4ED47B002BA3EF /* Helpers.swift in Sources */,
+				753988211AB72E4100FAF3FC /* ArrayExtension.swift in Sources */,
 				754BE46819693E190098E6F3 /* HashTests.swift in Sources */,
 				754BE46819693E190098E6F3 /* HashTests.swift in Sources */,
 				757DA2591A4ED4D7002BA3EF /* ChaCha20Tests.swift in Sources */,
 				757DA2591A4ED4D7002BA3EF /* ChaCha20Tests.swift in Sources */,
 				755FB1DA199E347D00475437 /* ExtensionsTest.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"
    LastUpgradeVersion = "0610"
    version = "1.3">
    version = "1.3">
    <BuildAction
    <BuildAction
-      parallelizeBuildables = "YES"
+      parallelizeBuildables = "NO"
       buildImplicitDependencies = "YES">
       buildImplicitDependencies = "YES">
       <BuildActionEntries>
       <BuildActionEntries>
          <BuildActionEntry
          <BuildActionEntry
@@ -51,6 +51,20 @@
                BlueprintName = "CryptoSwiftTests"
                BlueprintName = "CryptoSwiftTests"
                ReferencedContainer = "container:CryptoSwift.xcodeproj">
                ReferencedContainer = "container:CryptoSwift.xcodeproj">
             </BuildableReference>
             </BuildableReference>
+            <SkippedTests>
+               <Test
+                  Identifier = "AESTests/testAESPerformance()">
+               </Test>
+               <Test
+                  Identifier = "AESTests/testAESPerformanceCommonCrypto()">
+               </Test>
+               <Test
+                  Identifier = "ChaCha20Tests/testChaCha20Performance()">
+               </Test>
+               <Test
+                  Identifier = "RaufelderTests">
+               </Test>
+            </SkippedTests>
          </TestableReference>
          </TestableReference>
       </Testables>
       </Testables>
       <MacroExpansion>
       <MacroExpansion>

+ 116 - 117
CryptoSwift/AES.swift

@@ -8,29 +8,44 @@
 
 
 import Foundation
 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, 
         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, 
         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, 
         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, 
         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]
         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,
         0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
         0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
         0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
         0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54,
         0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54,
@@ -75,7 +90,7 @@ public class AES {
         0x21, 0x0c, 0x7d]
         0x21, 0x0c, 0x7d]
     
     
     // Parameters for Linear Congruence Generators
     // 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,
         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,
         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,
         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,
         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]
         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.key = key
-        self.blockMode = blockMode
         self.iv = iv
         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
             return nil
         }
         }
     }
     }
     
     
-    convenience public init?(key:NSData, blockMode:CipherBlockMode = .CBC) {
+    convenience public init?(key:[UInt8], blockMode:CipherBlockMode = .CBC) {
         // default IV is all 0x00...
         // 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)
         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.
     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
     :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
             // 128 bit block exceeded, need padding
-            assertionFailure("AES 128-bit block exceeded!")
+            assert(false, "AES 128-bit block exceeded!");
             return nil
             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 = 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
         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
             // 128 bit block exceeded
-            assertionFailure("AES 128-bit block exceeded!")
+            assert(false,"AES 128-bit block exceeded!")
             return nil
             return nil
         }
         }
         
         
-        let blocks = message.bytes().chunks(AES.blockSizeBytes())
-        var out:[UInt8]?
+        let blocks = bytes.chunks(AES.blockSize)
+        let out:[UInt8]?
         if (blockMode == .CFB) {
         if (blockMode == .CFB) {
             // CFB uses encryptBlock to decrypt
             // 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 {
         } 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))
         var state:[[UInt8]] = [[UInt8]](count: variant.Nb, repeatedValue: [UInt8](count: variant.Nb, repeatedValue: 0))
         for (i, row) in enumerate(state) {
         for (i, row) in enumerate(state) {
             for (j, val) in enumerate(row) {
             for (j, val) in enumerate(row) {
@@ -245,7 +246,7 @@ public class AES {
         return out
         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
         * Function used in the Key Expansion routine that takes a four-byte
@@ -255,22 +256,22 @@ public class AES {
         func subWord(word:[UInt8]) -> [UInt8] {
         func subWord(word:[UInt8]) -> [UInt8] {
             var result = word
             var result = word
             for i in 0..<4 {
             for i in 0..<4 {
-                result[i] = sBox[Int(word[i])]
+                result[i] = self.sBox[Int(word[i])]
             }
             }
             return result
             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 i in 0..<variant.Nk {
             for wordIdx in 0..<4 {
             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 {
             for wordIdx in 0..<4 {
                 tmp[wordIdx] = w[4*(i-1)+wordIdx]
                 tmp[wordIdx] = w[4*(i-1)+wordIdx]
             }
             }
@@ -286,8 +287,6 @@ public class AES {
             for wordIdx in 0..<4 {
             for wordIdx in 0..<4 {
                 w[4*i+wordIdx] = w[4*(i-variant.Nk)+wordIdx]^tmp[wordIdx];
                 w[4*i+wordIdx] = w[4*(i-variant.Nk)+wordIdx]^tmp[wordIdx];
             }
             }
-            
-            i++
         }
         }
         return w;
         return w;
     }
     }
@@ -296,21 +295,19 @@ public class AES {
 extension AES {
 extension AES {
     
     
     // byte substitution with table (S-box)
     // 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 (i,row) in enumerate(state) {
             for (j,value) in enumerate(row) {
             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]] {
     public func invSubBytes(state:[[UInt8]]) -> [[UInt8]] {
         var result = state
         var result = state
         for (i,row) in enumerate(state) {
         for (i,row) in enumerate(state) {
             for (j,value) in enumerate(row) {
             for (j,value) in enumerate(row) {
-                result[i][j] = invSBox[Int(value)]
+                result[i][j] = AES.invSBox[Int(value)]
             }
             }
         }
         }
         return result
         return result
@@ -357,7 +354,7 @@ extension AES {
     }
     }
     
     
     public func matrixMultiplyPolys(matrix:[[UInt8]], _ array:[UInt8]) -> [UInt8] {
     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 (i, row) in enumerate(matrix) {
             for (j, boxVal) in enumerate(row) {
             for (j, boxVal) in enumerate(row) {
                 returnArray[i] = multiplyPolys(boxVal, array[j]) ^ returnArray[i]
                 returnArray[i] = multiplyPolys(boxVal, array[j]) ^ returnArray[i]
@@ -367,11 +364,14 @@ extension AES {
     }
     }
 
 
     public func addRoundKey(state:[[UInt8]], _ expandedKeyW:[UInt8], _ round:Int) -> [[UInt8]] {
     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 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
         return newState
     }
     }
@@ -381,7 +381,8 @@ extension AES {
         var state = state
         var state = state
         var colBox:[[UInt8]] = [[2,3,1,1],[1,2,3,1],[1,1,2,3],[3,1,1,2]]
         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 i in 0..<state.count {
             for j in 0..<state[0].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) {
         for (i, row) in enumerate(rowMajorState) {
             newRowMajorState[i] = matrixMultiplyPolys(colBox, row)
             newRowMajorState[i] = matrixMultiplyPolys(colBox, row)
         }
         }

+ 4 - 3
CryptoSwift/ArrayExtension.swift

@@ -11,10 +11,11 @@ import Foundation
 extension Array {
 extension Array {
     
     
     /** split in chunks with given chunk size */
     /** 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 {
         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)
             words.append(word)
         }
         }
         let reminder = Array(suffix(self, self.count % chunksize))
         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
     :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
     Generates an authenticator for message using a one-time key and returns the 16-byte result
     
     
     :returns: 16-byte message authentication code
     :returns: 16-byte message authentication code
     */
     */
-    public func authenticate(message: NSData) -> NSData? {
+    public func authenticate(message: [UInt8]) -> [UInt8]? {
         switch (self) {
         switch (self) {
         case .Poly1305(let key):
         case .Poly1305(let key):
             return CryptoSwift.Poly1305.authenticate(key: key, message: message)
             return CryptoSwift.Poly1305.authenticate(key: key, message: message)

+ 48 - 28
CryptoSwift/ChaCha20.swift

@@ -10,7 +10,7 @@ import Foundation
 
 
 public class ChaCha20 {
 public class ChaCha20 {
     
     
-    private let blockSizeBytes = 512 / 8
+    static let blockSize = 64 // 512 / 8
     private let stateSize = 16
     private let stateSize = 16
     private var context:Context?
     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) {
         if let c = contextSetup(iv: iv, key: key) {
             context = c
             context = c
         } else {
         } 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
             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) {
         if (input.count != stateSize) {
             return nil;
             return nil;
         }
         }
@@ -69,19 +75,19 @@ public class ChaCha20 {
         }
         }
 
 
         var output = [UInt8]()
         var output = [UInt8]()
+        output.reserveCapacity(16)
 
 
         for i in 0..<16 {
         for i in 0..<16 {
             x[i] = x[i] &+ input[i]
             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;
         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? {
     private func contextSetup(# iv:[UInt8], key:[UInt8]) -> Context? {
         var ctx = Context()
         var ctx = Context()
         let kbits = key.count * 8
         let kbits = key.count * 8
@@ -93,7 +99,7 @@ public class ChaCha20 {
         // 4 - 8
         // 4 - 8
         for (var i = 0; i < 4; i++) {
         for (var i = 0; i < 4; i++) {
             let start = i * 4
             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;
         var addPos = 0;
@@ -117,19 +123,21 @@ public class ChaCha20 {
         // 8 - 11
         // 8 - 11
         for (var i = 0; i < 4; i++) {
         for (var i = 0; i < 4; i++) {
             let start = addPos + (i*4)
             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
         // iv
         ctx.input[12] = 0
         ctx.input[12] = 0
         ctx.input[13] = 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
         return ctx
     }
     }
     
     
-    private func encryptBytes(message:[UInt8]) -> [UInt8]? {
+    private final func encryptBytes(message:[UInt8]) -> [UInt8]? {
         
         
         if let ctx = context {
         if let ctx = context {
             var c:[UInt8] = [UInt8](count: message.count, repeatedValue: 0)
             var c:[UInt8] = [UInt8](count: message.count, repeatedValue: 0)
@@ -145,25 +153,25 @@ public class ChaCha20 {
                         ctx.input[13] = ctx.input[13] &+ 1
                         ctx.input[13] = ctx.input[13] &+ 1
                         /* stopping at 2^70 bytes per nonce is user's responsibility */
                         /* 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++) {
                         for (var i = 0; i < bytes; i++) {
                             c[i + cPos] = message[i + mPos] ^ output[i]
                             c[i + cPos] = message[i + mPos] ^ output[i]
                         }
                         }
                         return c
                         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]
                         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;
         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
         a = a &+ b
         d = rotateLeft((d ^ a), 16)
         d = rotateLeft((d ^ a), 16)
         
         
@@ -177,3 +185,15 @@ public class ChaCha20 {
         b = rotateLeft((b ^ c), 7);
         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
     :returns: Value of Cipher
     */
     */
-    case ChaCha20(key: NSData, iv: NSData)
+    case ChaCha20(key: [UInt8], iv: [UInt8])
     /**
     /**
     AES
     AES
     
     
@@ -27,7 +27,7 @@ public enum Cipher {
     
     
     :returns: Value of Cipher
     :returns: Value of Cipher
     */
     */
-    case AES(key: NSData, iv: NSData, blockMode: CipherBlockMode)
+    case AES(key: [UInt8], iv: [UInt8], blockMode: CipherBlockMode)
     
     
     /**
     /**
     Encrypt message
     Encrypt message
@@ -36,14 +36,14 @@ public enum Cipher {
     
     
     :returns: encrypted message
     :returns: encrypted message
     */
     */
-    public func encrypt(message: NSData) -> NSData? {
+    public func encrypt(bytes: [UInt8]) -> [UInt8]? {
         switch (self) {
         switch (self) {
             case .ChaCha20(let key, let iv):
             case .ChaCha20(let key, let iv):
                 var chacha = CryptoSwift.ChaCha20(key: key, iv: 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):
             case .AES(let key, let iv, let blockMode):
                 var aes = CryptoSwift.AES(key: key, iv: iv, blockMode: 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
     :returns: Plaintext message
     */
     */
-    public func decrypt(message: NSData) -> NSData? {
+    public func decrypt(bytes: [UInt8]) -> [UInt8]? {
         switch (self) {
         switch (self) {
             case .ChaCha20(let key, let iv):
             case .ChaCha20(let key, let iv):
                 var chacha = CryptoSwift.ChaCha20(key: key, iv: 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):
             case .AES(let key, let iv, let blockMode):
                 var aes = CryptoSwift.AES(key: key, iv: iv, blockMode: 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]();
         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)));
             randomIV.append(UInt8(truncatingBitPattern: arc4random_uniform(256)));
         }
         }
         return randomIV
         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
 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 {
 public enum CipherBlockMode {
     case ECB, CBC, CFB
     case ECB, CBC, CFB
     
     
-    func requireIV() -> Bool {
+    private var mode:BlockMode {
         switch (self) {
         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.
     Process input blocks with given block cipher mode. With fallback to plain mode.
     
     
@@ -29,7 +44,7 @@ public enum CipherBlockMode {
     
     
     :returns: encrypted bytes
     :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
         // if IV is not available, fallback to plain
         var finalBlockMode:CipherBlockMode = self
         var finalBlockMode:CipherBlockMode = self
@@ -37,91 +52,61 @@ public enum CipherBlockMode {
             finalBlockMode = .ECB
             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
         // if IV is not available, fallback to plain
         var finalBlockMode:CipherBlockMode = self
         var finalBlockMode:CipherBlockMode = self
         if (iv == nil) {
         if (iv == nil) {
             finalBlockMode = .ECB
             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)
 *  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) {
         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;
         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) {
         if (iv == nil) {
-            assertionFailure("CBC require IV")
             return nil
             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
         return out
@@ -131,85 +116,51 @@ private struct CBCMode {
 /**
 /**
 *  Cipher feedback (CFB)
 *  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) {
         if (iv == nil) {
-            assertionFailure("CFB require IV")
             return nil
             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;
         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)
 *  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
         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
     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 {
 func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
     var totalBytes = Swift.min(bytes.count, sizeof(T))
     var totalBytes = Swift.min(bytes.count, sizeof(T))
     // get slice of Int
     // get slice of Int
@@ -53,15 +55,16 @@ func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
     return i
     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] {
 func arrayOfBytes<T>(value:T, length:Int? = nil) -> [UInt8] {
-    let totalBytes = length ?? (sizeofValue(value) * 8)
+    let totalBytes = length ?? sizeof(T)
     var v = value
     var v = value
     
     
     var valuePointer = UnsafeMutablePointer<T>.alloc(1)
     var valuePointer = UnsafeMutablePointer<T>.alloc(1)
     valuePointer.memory = value
     valuePointer.memory = value
     
     
-    var bytesPointer = UnsafeMutablePointer<Byte>(valuePointer)
+    var bytesPointer = UnsafeMutablePointer<UInt8>(valuePointer)
     var bytes = [UInt8](count: totalBytes, repeatedValue: 0)
     var bytes = [UInt8](count: totalBytes, repeatedValue: 0)
     for j in 0..<min(sizeof(T),totalBytes) {
     for j in 0..<min(sizeof(T),totalBytes) {
         bytes[totalBytes - 1 - j] = (bytesPointer + j).memory
         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
 // helper to be able tomake shift operation on T
 func <<<T:SignedIntegerType>(lhs: T, rhs: Int) -> Int {
 func <<<T:SignedIntegerType>(lhs: T, rhs: Int) -> Int {
-    let a = lhs as Int
+    let a = lhs as! Int
     let b = rhs
     let b = rhs
     return a << b
     return a << b
 }
 }
 
 
 func <<<T:UnsignedIntegerType>(lhs: T, rhs: Int) -> UInt {
 func <<<T:UnsignedIntegerType>(lhs: T, rhs: Int) -> UInt {
-    let a = lhs as UInt
+    let a = lhs as! UInt
     let b = rhs
     let b = rhs
     return a << b
     return a << b
 }
 }

+ 18 - 10
CryptoSwift/HMAC.swift

@@ -13,6 +13,21 @@ public class HMAC {
     public enum Variant {
     public enum Variant {
         case sha1, sha256, sha384, sha512, md5
         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]? {
         func calculateHash(# bytes:[UInt8]) -> [UInt8]? {
             switch (self) {
             switch (self) {
             case .sha1:
             case .sha1:
@@ -38,23 +53,16 @@ public class HMAC {
         }
         }
     }
     }
     
     
-    let key:[UInt8]
+    var key:[UInt8]
     let variant:Variant
     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]? {
     class internal func authenticate(# key: [UInt8], message: [UInt8], variant:HMAC.Variant = .md5) -> [UInt8]? {
         return HMAC(key, variant: variant)?.authenticate(message: message)
         return HMAC(key, variant: variant)?.authenticate(message: message)
     }
     }
 
 
     // MARK: - Private
     // MARK: - Private
     
     
-    private init? (_ key: [UInt8], variant:HMAC.Variant = .md5) {
+    internal init? (_ key: [UInt8], variant:HMAC.Variant = .md5) {
         self.variant = variant
         self.variant = variant
         self.key = key
         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)
         var opad = [UInt8](count: variant.blockSize(), repeatedValue: 0x5c)
         for (idx, val) in enumerate(key) {
         for (idx, val) in enumerate(key) {
             opad[idx] = key[idx] ^ opad[idx]
             opad[idx] = key[idx] ^ opad[idx]

+ 4 - 4
CryptoSwift/Hash.swift

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

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

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

+ 1 - 1
CryptoSwift/IntExtension.swift

@@ -30,7 +30,7 @@ extension Int {
         return arrayOfBytes(self, length: totalBytes)
         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))
         return Int.withBytes(Array(bytes))
     }
     }
 
 

+ 6 - 6
CryptoSwift/MD5.swift

@@ -8,8 +8,9 @@
 
 
 import Foundation
 import Foundation
 
 
-class MD5 : CryptoSwift.HashBase {
-
+class MD5 : CryptoSwift.HashBase, _Hash {
+    var size:Int = 16 // 128 / 8
+    
     /** specifies the per-round shift amounts */
     /** 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,
     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,
                        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
             // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
             var M:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
             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:
             // Initialize hash value for this chunk:
             var A:UInt32 = hh[0]
             var A:UInt32 = hh[0]
@@ -112,7 +112,7 @@ class MD5 : CryptoSwift.HashBase {
             buf.appendBytes(&i, length: sizeofValue(i))
             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? {
     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? {
     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? {
     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 = "";
         var s:String = "";
         for byte in bytesArray {
         for byte in bytesArray {
-            s = s + NSString(format:"%02X", byte)
+            s = s + String(format:"%02X", byte)
         }
         }
         return s;
         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
 //  PKCS7.swift
 //  CryptoSwift
 //  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
 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 (padding == 0) {
             // If the original data is a multiple of N bytes, then an extra block of bytes with value N is added.
             // 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 {
         } else {
             // The value of each added byte is the number of bytes that are added
             // The value of each added byte is the number of bytes that are added
             for i in 0..<padding {
             for i in 0..<padding {
-                withPadding.appendBytes([padding])
+                withPadding.extend([UInt8(padding)])
             }
             }
         }
         }
         return withPadding
         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
     :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]? {
     class internal func authenticate(# key: [UInt8], message: [UInt8]) -> [UInt8]? {
         return Poly1305(key)?.authenticate(message: message)
         return Poly1305(key)?.authenticate(message: message)
     }
     }

+ 9 - 5
CryptoSwift/SHA1.swift

@@ -8,7 +8,12 @@
 
 
 import Foundation
 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]
     private let h:[UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
         
         
@@ -80,7 +85,6 @@ class SHA1 : CryptoSwift.HashBase {
                 C = rotateLeft(B, 30)
                 C = rotateLeft(B, 30)
                 B = A
                 B = A
                 A = temp
                 A = temp
-                
             }
             }
             
             
             hh[0] = (hh[0] &+ A) & 0xffffffff
             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:
         // Produce the final hash value (big-endian) as a 160 bit number:
         var buf: NSMutableData = NSMutableData();
         var buf: NSMutableData = NSMutableData();
-        hh.map({ (item) -> () in
+        for item in hh {
             var i:UInt32 = item.bigEndian
             var i:UInt32 = item.bigEndian
             buf.appendBytes(&i, length: sizeofValue(i))
             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
 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
         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) {
             switch (self) {
             case .sha224:
             case .sha224:
                 return [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
                 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) {
             switch (self) {
             case .sha224, .sha256:
             case .sha224, .sha256:
                 return [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                 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;
             var finalHH:[T] = hh;
             switch (self) {
             switch (self) {
             case .sha224:
             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()
         var tmpMessage = self.prepare()
         
         
         // hash values
         // hash values
         var hh = [UInt32]()
         var hh = [UInt32]()
-        variant.h().map({(h) -> () in
+        variant.h.map({(h) -> () in
             hh.append(UInt32(h))
             hh.append(UInt32(h))
         })
         })
         
         
@@ -93,7 +136,7 @@ class SHA2 : CryptoSwift.HashBase {
             let chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
             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
             // 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:
             // 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 {
             for x in 0..<M.count {
                 switch (x) {
                 switch (x) {
                 case 0...15:
                 case 0...15:
@@ -119,13 +162,13 @@ class SHA2 : CryptoSwift.HashBase {
             var H = hh[7]
             var H = hh[7]
             
             
             // Main loop
             // 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 s0 = rotateRight(A,2) ^ rotateRight(A,13) ^ rotateRight(A,22)
                 let maj = (A & B) ^ (A & C) ^ (B & C)
                 let maj = (A & B) ^ (A & C) ^ (B & C)
                 let t2 = s0 &+ maj
                 let t2 = s0 &+ maj
                 let s1 = rotateRight(E,6) ^ rotateRight(E,11) ^ rotateRight(E,25)
                 let s1 = rotateRight(E,6) ^ rotateRight(E,11) ^ rotateRight(E,25)
                 let ch = (E & F) ^ ((~E) & G)
                 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
                 H = G
                 G = F
                 G = F
@@ -155,15 +198,15 @@ class SHA2 : CryptoSwift.HashBase {
             buf.appendBytes(&i, length: sizeofValue(i))
             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)
         var tmpMessage = self.prepare(128)
         
         
         // hash values
         // hash values
         var hh = [UInt64]()
         var hh = [UInt64]()
-        variant.h().map({(h) -> () in
+        variant.h.map({(h) -> () in
             hh.append(h)
             hh.append(h)
         })
         })
         
         
@@ -177,7 +220,7 @@ class SHA2 : CryptoSwift.HashBase {
             var chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
             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
             // 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:
             // 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 {
             for x in 0..<M.count {
                 switch (x) {
                 switch (x) {
                 case 0...15:
                 case 0...15:
@@ -203,13 +246,13 @@ class SHA2 : CryptoSwift.HashBase {
             var H = hh[7]
             var H = hh[7]
             
             
             // Main loop
             // 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 s0 = rotateRight(A,28) ^ rotateRight(A,34) ^ rotateRight(A,39)
                 let maj = (A & B) ^ (A & C) ^ (B & C)
                 let maj = (A & B) ^ (A & C) ^ (B & C)
                 let t2 = s0 &+ maj
                 let t2 = s0 &+ maj
                 let s1 = rotateRight(E,14) ^ rotateRight(E,18) ^ rotateRight(E,41)
                 let s1 = rotateRight(E,14) ^ rotateRight(E,18) ^ rotateRight(E,41)
                 let ch = (E & F) ^ ((~E) & G)
                 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
                 H = G
                 G = F
                 G = F
@@ -239,6 +282,6 @@ class SHA2 : CryptoSwift.HashBase {
             buf.appendBytes(&i, length: sizeofValue(i))
             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)
         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))
         return UInt32.withBytes(Array(bytes))
     }
     }
 
 

+ 1 - 1
CryptoSwift/UInt64Extension.swift

@@ -14,7 +14,7 @@ extension UInt64 {
         return arrayOfBytes(self, length: totalBytes)
         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))
         return UInt64.withBytes(Array(bytes))
     }
     }
 
 

+ 23 - 0
CryptoSwift/Utils.swift

@@ -8,6 +8,10 @@
 
 
 import Foundation
 import Foundation
 
 
+func rotateLeft(v:UInt8, n:UInt8) -> UInt8 {
+    return ((v << n) & 0xFF) | (v >> (8 - n))
+}
+
 func rotateLeft(v:UInt16, n:UInt16) -> UInt16 {
 func rotateLeft(v:UInt16, n:UInt16) -> UInt16 {
     return ((v << n) & 0xFFFF) | (v >> (16 - n))
     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 tmp1 = ((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8)
     var tmp2 = ((value & 0x00FF0000) >> 8)  | ((value & 0xFF000000) >> 24)
     var tmp2 = ((value & 0x00FF0000) >> 8)  | ((value & 0xFF000000) >> 24)
     return tmp1 | tmp2
     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];
         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 {
         } else {
             XCTAssert(false, "failed")
             XCTAssert(false, "failed")
         }
         }
@@ -42,11 +42,11 @@ class AESTests: XCTestCase {
             0xd8, 0xcd, 0xb7, 0x80,
             0xd8, 0xcd, 0xb7, 0x80,
             0x70, 0xb4, 0xc5, 0x5a];
             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 {
         } else {
             XCTAssert(false, "failed")
             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 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];
         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")
             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 {
         } else {
             XCTAssert(false, "failed")
             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 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];
         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")
             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 {
         } else {
             XCTAssert(false, "failed")
             XCTAssert(false, "failed")
         }
         }
@@ -97,9 +97,10 @@ class AESTests: XCTestCase {
             [0xcd, 0x60, 0xe0, 0xe7],
             [0xcd, 0x60, 0xe0, 0xe7],
             [0xba, 0x70, 0xe1, 0x8c]]
             [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")
         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")
         XCTAssertTrue(compareMatrix(input, inverted), "invSubBytes failed")
     }
     }
     
     
@@ -114,21 +115,21 @@ class AESTests: XCTestCase {
             [0xe0, 0xe1, 0xb7, 0xd0],
             [0xe0, 0xe1, 0xb7, 0xd0],
             [0x8c, 0x4, 0x51, 0xe7]]
             [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")
         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")
         XCTAssertTrue(compareMatrix(input, inverted), "invShiftRows failed")
     }
     }
     
     
     func testAES_multiply() {
     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() {
     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]
         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 {
         } else {
             XCTAssert(false, "")
             XCTAssert(false, "")
         }
         }
@@ -145,8 +146,8 @@ class AESTests: XCTestCase {
             [32, 96, 160, 224],
             [32, 96, 160, 224],
             [48, 112, 176, 240]]
             [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")
             XCTAssertTrue(compareMatrix(expected, result), "addRoundKey failed")
         } else {
         } else {
             XCTAssert(false, "")
             XCTAssert(false, "")
@@ -164,7 +165,7 @@ class AESTests: XCTestCase {
             [0x64, 0xbc, 0x3b, 0xf9],
             [0x64, 0xbc, 0x3b, 0xf9],
             [0x15, 0x92, 0x29, 0x1a]]
             [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)
             let mixed = aes.mixColumns(input)
             XCTAssertTrue(compareMatrix(expected, mixed), "mixColumns failed")
             XCTAssertTrue(compareMatrix(expected, mixed), "mixColumns failed")
             let inverted = aes.invMixColumns(mixed)
             let inverted = aes.invMixColumns(mixed)
@@ -173,5 +174,55 @@ class AESTests: XCTestCase {
             XCTAssert(false, "")
             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++) {
         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]
             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 {
             if let encrypted = encrypted {
                 var decrypted = Cipher.ChaCha20(setup).decrypt(encrypted)
                 var decrypted = Cipher.ChaCha20(setup).decrypt(encrypted)
-                XCTAssertNotNil(decrypted, "")
+                XCTAssert(decrypted != nil, "missing")
                 if let decrypted = decrypted {
                 if let decrypted = decrypted {
-                    XCTAssertEqual(messageData, decrypted, "ChaCha20 decryption failed");
+                    XCTAssertEqual(message, decrypted, "ChaCha20 decryption failed");
                 }
                 }
                 
                 
                 // check extension
                 // check extension
+                let messageData = NSData(bytes: message, length: message.count);
                 let encrypted2 = messageData.encrypt(Cipher.ChaCha20(setup))
                 let encrypted2 = messageData.encrypt(Cipher.ChaCha20(setup))
                 XCTAssertNotNil(encrypted2, "")
                 XCTAssertNotNil(encrypted2, "")
                 if let encrypted2 = 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()
         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() {
     func testIntExtension() {
         let i1:Int = 1024
         let i1:Int = 1024
         let i1Array = i1.bytes(32 / 8) // 32 bit
         let i1Array = i1.bytes(32 / 8) // 32 bit

+ 24 - 6
CryptoSwiftTests/HMACTests.swift

@@ -26,8 +26,8 @@ class HMACTests: XCTestCase {
         let msg:[UInt8] = []
         let msg:[UInt8] = []
         let expectedMac:[UInt8] = [0x74,0xe6,0xf7,0x29,0x8a,0x9c,0x2d,0x16,0x89,0x35,0xf5,0x8c,0x00,0x1b,0xad,0x88]
         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() {
     func testSHA1() {
@@ -35,8 +35,8 @@ class HMACTests: XCTestCase {
         let msg:[UInt8] = []
         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 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() {
     func testSHA256() {
@@ -44,8 +44,26 @@ class HMACTests: XCTestCase {
         let msg:[UInt8] = []
         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 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() {
     func testSHA384() {

+ 8 - 12
CryptoSwiftTests/HashTests.swift

@@ -76,12 +76,10 @@ class CryptoSwiftTests: XCTestCase {
     
     
     func testMD5PerformanceSwift() {
     func testMD5PerformanceSwift() {
         self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
         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)
             let data = NSData(bytes: buf, length: 2048)
             self.startMeasuring()
             self.startMeasuring()
-            for _ in [0...1000] {
-                Hash.md5(data).calculate()
-            }
+            Hash.md5(data).calculate()
             self.stopMeasuring()
             self.stopMeasuring()
             buf.dealloc(1024)
             buf.dealloc(1024)
             buf.destroy()
             buf.destroy()
@@ -90,16 +88,14 @@ class CryptoSwiftTests: XCTestCase {
     
     
     func testMD5PerformanceCommonCrypto() {
     func testMD5PerformanceCommonCrypto() {
         self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
         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)
             let data = NSData(bytes: buf, length: 2048)
             self.startMeasuring()
             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()
             self.stopMeasuring()
             buf.dealloc(1024)
             buf.dealloc(1024)
             buf.destroy()
             buf.destroy()

+ 12 - 12
CryptoSwiftTests/PaddingTests.swift

@@ -14,27 +14,27 @@ class PaddingTests: XCTestCase {
     func testPKCS7_0() {
     func testPKCS7_0() {
         let input:[UInt8]    = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]
         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 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() {
     func testPKCS7_1() {
         let input:[UInt8]    = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]
         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 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() {
     func testPKCS7_2() {
         let input:[UInt8]    = [1,2,3,4,5,6,7,8,9,0,1,2,3,4]
         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 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 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 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
         // extensions
         let msgData = NSData.withBytes(msg)
         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
 ####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
 ```ruby
 pod 'CryptoSwift'
 pod 'CryptoSwift'
 ```
 ```
 
 
+or for newest version from specified branch of code:
+
+```ruby
+pod 'CryptoSwift', :git => "https://github.com/krzyzanowskim/CryptoSwift", :branch => "master"
+```
+ 
 ##Usage
 ##Usage
 
 
 ```swift
 ```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.
 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
 ```swift
-let paddedData = PKCS7(data: dataToEncrypt).addPadding(AES.blockSizeBytes())
+let paddedData = PKCS7().add(bytes, AES.blockSize)
 ```
 ```
 
 
 Working with Ciphers
 Working with Ciphers
@@ -113,8 +119,8 @@ Working with Ciphers
 ChaCha20
 ChaCha20
 
 
 ```swift
 ```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
 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__.*
 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
 ```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
 AES without data padding
 
 
 ```swift
 ```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
 Using extensions
 	
 	
 ```swift
 ```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
 Message authenticators
@@ -163,6 +161,15 @@ Message authenticators
 let mac = Authenticator.Poly1305(key: key).authenticate(message)
 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
 ##Contact
 Marcin Krzyżanowski [@krzyzanowskim](http://twitter.com/krzyzanowskim)
 Marcin Krzyżanowski [@krzyzanowskim](http://twitter.com/krzyzanowskim)