Pārlūkot izejas kodu

Merge branch 'develop'

Marcin Krzyżanowski 9 gadi atpakaļ
vecāks
revīzija
f03b37259c
41 mainītis faili ar 729 papildinājumiem un 534 dzēšanām
  1. 9 0
      CHANGELOG
  2. 85 0
      CryptoSwift.playground/Contents.swift
  3. 4 0
      CryptoSwift.playground/contents.xcplayground
  4. 80 40
      CryptoSwift.xcodeproj/project.pbxproj
  5. 0 0
      CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint
  6. 7 0
      CryptoSwift.xcworkspace/contents.xcworkspacedata
  7. 0 0
      CryptoSwift.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint
  8. 48 20
      CryptoSwiftTests/AESTests.swift
  9. 10 0
      CryptoSwiftTests/HashTests.swift
  10. 11 4
      CryptoSwiftTests/PBKDF.swift
  11. 67 46
      README.md
  12. 4 4
      Sources/CryptoSwift/AES.swift
  13. 1 1
      Sources/CryptoSwift/Array+Extension.swift
  14. 47 0
      Sources/CryptoSwift/BlockMode/BlockMode.swift
  15. 0 19
      Sources/CryptoSwift/BlockMode/BlockModeGenerator.swift
  16. 13 0
      Sources/CryptoSwift/BlockMode/BlockModeWorker.swift
  17. 14 39
      Sources/CryptoSwift/BlockMode/CBC.swift
  18. 15 40
      Sources/CryptoSwift/BlockMode/CFB.swift
  19. 12 39
      Sources/CryptoSwift/BlockMode/CTR.swift
  20. 0 92
      Sources/CryptoSwift/BlockMode/CipherBlockMode.swift
  21. 11 18
      Sources/CryptoSwift/BlockMode/ECB.swift
  22. 12 37
      Sources/CryptoSwift/BlockMode/OFB.swift
  23. 15 40
      Sources/CryptoSwift/BlockMode/PCBC.swift
  24. 1 1
      Sources/CryptoSwift/BytesSequence.swift
  25. 3 4
      Sources/CryptoSwift/CRC.swift
  26. 6 6
      Sources/CryptoSwift/CSArrayType+Extensions.swift
  27. 12 20
      Sources/CryptoSwift/ChaCha20.swift
  28. 26 0
      Sources/CryptoSwift/Cipher.swift
  29. 12 10
      Sources/CryptoSwift/Cryptors.swift
  30. 1 1
      Sources/CryptoSwift/Foundation/AES+Foundation.swift
  31. 6 6
      Sources/CryptoSwift/Foundation/NSData+Extension.swift
  32. 2 2
      Sources/CryptoSwift/Foundation/String+FoundationExtension.swift
  33. 2 2
      Sources/CryptoSwift/Hash.swift
  34. 2 2
      Sources/CryptoSwift/Info.plist
  35. 82 0
      Sources/CryptoSwift/PKCS5/PBKDF1.swift
  36. 25 15
      Sources/CryptoSwift/PKCS5/PBKDF2.swift
  37. 2 2
      Sources/CryptoSwift/PKCS7.swift
  38. 7 18
      Sources/CryptoSwift/Rabbit.swift
  39. 4 4
      Sources/CryptoSwift/String+Extension.swift
  40. 55 0
      Sources/CryptoSwift/UpdatableCryptor.swift
  41. 16 2
      Sources/CryptoSwift/Utils.swift

+ 9 - 0
CHANGELOG

@@ -1,3 +1,12 @@
+0.5
+- Added PBKDF1 https://tools.ietf.org/html/rfc2898#section-5.1
+- Added PBKDF2 https://tools.ietf.org/html/rfc2898#section-5.2
+- UpdatableCryptor protocol allows incremental encryption stream of data
+- CryptoSwift.playground
+- Docs update
+- Added reflection control to CRC-32 (Luís Silva)
+- Fix AES.init() (Pascal Pfiffner)
+
 0.4.1
 - fix NoPadding()
 

+ 85 - 0
CryptoSwift.playground/Contents.swift

@@ -0,0 +1,85 @@
+/*:
+ To whom may be concerned: I offer professional support to all my open source projects.
+ 
+ Contact: [marcin@krzyzanowskim.com](http://krzyzanowskim.com)
+*/
+import CryptoSwift
+import Foundation
+import XCPlayground
+
+//: # AES
+//: One-time shot
+do {
+    let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap")
+    let ciphertext = try aes.encrypt("Nullam quis risus eget urna mollis ornare vel eu leo.".utf8.map({$0}))
+    print(ciphertext.toHexString())
+} catch {
+    print(error)
+}
+
+//: Incremental encryption
+do {
+    let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap")
+    var encryptor = aes.makeEncryptor()
+
+    var ciphertext = Array<UInt8>()
+    ciphertext += try encryptor.update(withBytes: "Nullam quis risus ".utf8.map({$0}))
+    ciphertext += try encryptor.update(withBytes: "eget urna mollis ".utf8.map({$0}))
+    ciphertext += try encryptor.update(withBytes: "ornare vel eu leo.".utf8.map({$0}))
+    ciphertext += try encryptor.finish()
+
+    print(ciphertext.toHexString())
+} catch {
+    print(error)
+}
+
+//: Encrypt stream incrementally
+do {
+    // write until all is written
+    func writeToStream(stream: NSOutputStream, bytes: [UInt8]) {
+        var writtenCount = 0
+        while stream.hasSpaceAvailable && writtenCount < bytes.count {
+            let c = stream.write(bytes, maxLength: bytes.count)
+            if c <= 0 {
+                break;
+            }
+
+            writtenCount += stream.write(bytes, maxLength: bytes.count)
+        }
+    }
+
+    let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap")
+    var encryptor = aes.makeEncryptor()
+
+    // prepare streams
+    let data = NSData(bytes: (0..<100).map { $0 })
+    let inputStream = NSInputStream(data: data)
+    let outputStream = NSOutputStream(toMemory: ())
+    inputStream.open()
+    outputStream.open()
+
+    var buffer = [UInt8](count: 2, repeatedValue: 0)
+
+    // encrypt input stream data and write encrypted result to output stream
+    while (inputStream.hasBytesAvailable) {
+        let readCount = inputStream.read(&buffer, maxLength: buffer.count)
+        if (readCount > 0) {
+            try encryptor.update(withBytes: Array(buffer[0..<readCount])) { (bytes) in
+                writeToStream(outputStream, bytes: bytes)
+            }
+        }
+    }
+
+    // finalize encryption
+    try encryptor.finish { (bytes) in
+        writeToStream(outputStream, bytes: bytes)
+    }
+
+    // print result
+    if let ciphertext = outputStream.propertyForKey(NSStreamDataWrittenToMemoryStreamKey) as? NSData {
+        print("Encrypted stream data: \(ciphertext.toHexString())")
+    }
+
+} catch {
+    print(error)
+}

+ 4 - 0
CryptoSwift.playground/contents.xcplayground

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<playground version='5.0' target-platform='ios' display-mode='rendered'>
+    <timeline fileName='timeline.xctimeline'/>
+</playground>

+ 80 - 40
CryptoSwift.xcodeproj/project.pbxproj

@@ -17,7 +17,7 @@
 		753881EC1CB06E390089101D /* NoPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753881EA1CB06E390089101D /* NoPadding.swift */; };
 		753881ED1CB06E390089101D /* NoPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753881EA1CB06E390089101D /* NoPadding.swift */; };
 		753881EE1CB06E390089101D /* NoPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753881EA1CB06E390089101D /* NoPadding.swift */; };
-		75482EA41CB310B7001F66A5 /* PBKDF2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA31CB310B7001F66A5 /* PBKDF2Tests.swift */; };
+		75482EA41CB310B7001F66A5 /* PBKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA31CB310B7001F66A5 /* PBKDF.swift */; };
 		75482EA71CB329C1001F66A5 /* PBKDF2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA61CB329C1001F66A5 /* PBKDF2.swift */; };
 		75482EA81CB329C1001F66A5 /* PBKDF2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA61CB329C1001F66A5 /* PBKDF2.swift */; };
 		75482EA91CB329C1001F66A5 /* PBKDF2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75482EA61CB329C1001F66A5 /* PBKDF2.swift */; };
@@ -31,6 +31,10 @@
 		754C9D1C1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C9D1A1C30800A0003D5FE /* String+LinuxFoundation.swift */; };
 		754C9D1D1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C9D1A1C30800A0003D5FE /* String+LinuxFoundation.swift */; };
 		754C9D1E1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C9D1A1C30800A0003D5FE /* String+LinuxFoundation.swift */; };
+		755655C71D080E3F00F004E7 /* Cryptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755655C61D080E3F00F004E7 /* Cryptors.swift */; };
+		755655C81D080E3F00F004E7 /* Cryptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755655C61D080E3F00F004E7 /* Cryptors.swift */; };
+		755655C91D080E3F00F004E7 /* Cryptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755655C61D080E3F00F004E7 /* Cryptors.swift */; };
+		755655CA1D080E3F00F004E7 /* Cryptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755655C61D080E3F00F004E7 /* Cryptors.swift */; };
 		755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755FB1D9199E347D00475437 /* ExtensionsTest.swift */; };
 		7574E5FE1CD02C8B00E96346 /* CSArrayType+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7574E5FD1CD02C8B00E96346 /* CSArrayType+Foundation.swift */; };
 		7574E5FF1CD02C9300E96346 /* CSArrayType+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7574E5FD1CD02C8B00E96346 /* CSArrayType+Foundation.swift */; };
@@ -84,10 +88,6 @@
 		757BC9551C1CA5790093AAA9 /* ChaCha20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9201C1CA5790093AAA9 /* ChaCha20.swift */; };
 		757BC9561C1CA5790093AAA9 /* ChaCha20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9201C1CA5790093AAA9 /* ChaCha20.swift */; };
 		757BC9571C1CA5790093AAA9 /* ChaCha20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9201C1CA5790093AAA9 /* ChaCha20.swift */; };
-		757BC9581C1CA5790093AAA9 /* CipherProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9211C1CA5790093AAA9 /* CipherProtocol.swift */; };
-		757BC9591C1CA5790093AAA9 /* CipherProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9211C1CA5790093AAA9 /* CipherProtocol.swift */; };
-		757BC95A1C1CA5790093AAA9 /* CipherProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9211C1CA5790093AAA9 /* CipherProtocol.swift */; };
-		757BC95B1C1CA5790093AAA9 /* CipherProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9211C1CA5790093AAA9 /* CipherProtocol.swift */; };
 		757BC9601C1CA5790093AAA9 /* CRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9231C1CA5790093AAA9 /* CRC.swift */; };
 		757BC9611C1CA5790093AAA9 /* CRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9231C1CA5790093AAA9 /* CRC.swift */; };
 		757BC9621C1CA5790093AAA9 /* CRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9231C1CA5790093AAA9 /* CRC.swift */; };
@@ -188,10 +188,6 @@
 		757F440F1CC1822B002B1F85 /* SecureBytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757F440D1CC1822A002B1F85 /* SecureBytes.swift */; };
 		757F44101CC1822B002B1F85 /* SecureBytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757F440D1CC1822A002B1F85 /* SecureBytes.swift */; };
 		757F44111CC1822B002B1F85 /* SecureBytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757F440D1CC1822A002B1F85 /* SecureBytes.swift */; };
-		7588034C1C8F8C33008C1576 /* BlockModeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7588034B1C8F8C33008C1576 /* BlockModeGenerator.swift */; };
-		7588034D1C8F8C42008C1576 /* BlockModeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7588034B1C8F8C33008C1576 /* BlockModeGenerator.swift */; };
-		7588034E1C8F8C42008C1576 /* BlockModeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7588034B1C8F8C33008C1576 /* BlockModeGenerator.swift */; };
-		7588034F1C8F8C43008C1576 /* BlockModeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7588034B1C8F8C33008C1576 /* BlockModeGenerator.swift */; };
 		758A94281A65C59200E46135 /* HMACTests.swift in Resources */ = {isa = PBXBuildFile; fileRef = 758A94271A65C59200E46135 /* HMACTests.swift */; };
 		758A94291A65C67400E46135 /* HMACTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758A94271A65C59200E46135 /* HMACTests.swift */; };
 		758F58F11C8FB6E20054C377 /* OFB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758F58F01C8FB6E20054C377 /* OFB.swift */; };
@@ -203,10 +199,10 @@
 		75CB93261C8F5EC10087740D /* CBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB93241C8F5EC10087740D /* CBC.swift */; };
 		75CB93271C8F5EC10087740D /* CBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB93241C8F5EC10087740D /* CBC.swift */; };
 		75CB93281C8F5EC10087740D /* CBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB93241C8F5EC10087740D /* CBC.swift */; };
-		75CB93301C8F5F580087740D /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* CipherBlockMode.swift */; };
-		75CB93311C8F5F580087740D /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* CipherBlockMode.swift */; };
-		75CB93321C8F5F580087740D /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* CipherBlockMode.swift */; };
-		75CB93331C8F5F580087740D /* CipherBlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* CipherBlockMode.swift */; };
+		75CB93301C8F5F580087740D /* BlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* BlockMode.swift */; };
+		75CB93311C8F5F580087740D /* BlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* BlockMode.swift */; };
+		75CB93321C8F5F580087740D /* BlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* BlockMode.swift */; };
+		75CB93331C8F5F580087740D /* BlockMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB932F1C8F5F580087740D /* BlockMode.swift */; };
 		75CB93351C8F5FCE0087740D /* PCBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB93341C8F5FCE0087740D /* PCBC.swift */; };
 		75CB93361C8F5FCE0087740D /* PCBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB93341C8F5FCE0087740D /* PCBC.swift */; };
 		75CB93371C8F5FCE0087740D /* PCBC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB93341C8F5FCE0087740D /* PCBC.swift */; };
@@ -227,6 +223,22 @@
 		75CB934F1C8F609D0087740D /* BlockModeOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB934D1C8F609D0087740D /* BlockModeOptions.swift */; };
 		75CB93501C8F609D0087740D /* BlockModeOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB934D1C8F609D0087740D /* BlockModeOptions.swift */; };
 		75CB93511C8F609D0087740D /* BlockModeOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CB934D1C8F609D0087740D /* BlockModeOptions.swift */; };
+		75D0E05C1CFB9B9400FCEA0E /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D0E05B1CFB9B9400FCEA0E /* Cipher.swift */; };
+		75D0E05D1CFB9B9400FCEA0E /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D0E05B1CFB9B9400FCEA0E /* Cipher.swift */; };
+		75D0E05E1CFB9B9400FCEA0E /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D0E05B1CFB9B9400FCEA0E /* Cipher.swift */; };
+		75D0E05F1CFB9B9400FCEA0E /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D0E05B1CFB9B9400FCEA0E /* Cipher.swift */; };
+		75D1F1F41D06B98B005A87A2 /* PBKDF1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D1F1F31D06B98B005A87A2 /* PBKDF1.swift */; };
+		75D1F1F51D06B98B005A87A2 /* PBKDF1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D1F1F31D06B98B005A87A2 /* PBKDF1.swift */; };
+		75D1F1F61D06B98B005A87A2 /* PBKDF1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D1F1F31D06B98B005A87A2 /* PBKDF1.swift */; };
+		75D1F1F71D06B98B005A87A2 /* PBKDF1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D1F1F31D06B98B005A87A2 /* PBKDF1.swift */; };
+		75DB81A31CDBFDC700ED181A /* BlockModeWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A21CDBFDC700ED181A /* BlockModeWorker.swift */; };
+		75DB81A41CDBFDC700ED181A /* BlockModeWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A21CDBFDC700ED181A /* BlockModeWorker.swift */; };
+		75DB81A51CDBFDC700ED181A /* BlockModeWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A21CDBFDC700ED181A /* BlockModeWorker.swift */; };
+		75DB81A61CDBFDC700ED181A /* BlockModeWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A21CDBFDC700ED181A /* BlockModeWorker.swift */; };
+		75DB81A81CDC06B100ED181A /* UpdatableCryptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A71CDC06B100ED181A /* UpdatableCryptor.swift */; };
+		75DB81A91CDC06B100ED181A /* UpdatableCryptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A71CDC06B100ED181A /* UpdatableCryptor.swift */; };
+		75DB81AA1CDC06B100ED181A /* UpdatableCryptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A71CDC06B100ED181A /* UpdatableCryptor.swift */; };
+		75DB81AB1CDC06B100ED181A /* UpdatableCryptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DB81A71CDC06B100ED181A /* UpdatableCryptor.swift */; };
 		80545D131CA9FECD00474A99 /* Bit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80545D121CA9FECD00474A99 /* Bit.swift */; };
 		80545D141CA9FECD00474A99 /* Bit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80545D121CA9FECD00474A99 /* Bit.swift */; };
 		80545D151CA9FECD00474A99 /* Bit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80545D121CA9FECD00474A99 /* Bit.swift */; };
@@ -321,7 +333,7 @@
 		674A736E1BF5D85B00866C5B /* RabbitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RabbitTests.swift; sourceTree = "<group>"; };
 		75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poly1305Tests.swift; sourceTree = "<group>"; };
 		753881EA1CB06E390089101D /* NoPadding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NoPadding.swift; path = Sources/CryptoSwift/NoPadding.swift; sourceTree = SOURCE_ROOT; };
-		75482EA31CB310B7001F66A5 /* PBKDF2Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PBKDF2Tests.swift; sourceTree = "<group>"; };
+		75482EA31CB310B7001F66A5 /* PBKDF.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PBKDF.swift; sourceTree = "<group>"; };
 		75482EA61CB329C1001F66A5 /* PBKDF2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PBKDF2.swift; path = Sources/CryptoSwift/PKCS5/PBKDF2.swift; sourceTree = SOURCE_ROOT; };
 		75482EAB1CB329DF001F66A5 /* PKCS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PKCS5.swift; path = Sources/CryptoSwift/PKCS5/PKCS5.swift; sourceTree = SOURCE_ROOT; };
 		754BE45519693E190098E6F3 /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -329,6 +341,8 @@
 		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>"; };
 		754C9D1A1C30800A0003D5FE /* String+LinuxFoundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+LinuxFoundation.swift"; sourceTree = "<group>"; };
+		755655C61D080E3F00F004E7 /* Cryptors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Cryptors.swift; path = Sources/CryptoSwift/Cryptors.swift; sourceTree = SOURCE_ROOT; };
+		755D27BC1D06DE6400C41692 /* CryptoSwift.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = CryptoSwift.playground; sourceTree = "<group>"; };
 		755FB1D9199E347D00475437 /* ExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionsTest.swift; sourceTree = "<group>"; };
 		756BFDCA1A82B87300B9D9A4 /* Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bridging.h; sourceTree = "<group>"; };
 		7574E5FD1CD02C8B00E96346 /* CSArrayType+Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSArrayType+Foundation.swift"; sourceTree = "<group>"; };
@@ -344,7 +358,6 @@
 		757BC91D1C1CA5790093AAA9 /* Authenticator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Authenticator.swift; path = Sources/CryptoSwift/Authenticator.swift; sourceTree = SOURCE_ROOT; };
 		757BC91F1C1CA5790093AAA9 /* BytesSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BytesSequence.swift; path = Sources/CryptoSwift/BytesSequence.swift; sourceTree = SOURCE_ROOT; };
 		757BC9201C1CA5790093AAA9 /* ChaCha20.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChaCha20.swift; path = Sources/CryptoSwift/ChaCha20.swift; sourceTree = SOURCE_ROOT; };
-		757BC9211C1CA5790093AAA9 /* CipherProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CipherProtocol.swift; path = Sources/CryptoSwift/CipherProtocol.swift; sourceTree = SOURCE_ROOT; };
 		757BC9231C1CA5790093AAA9 /* CRC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CRC.swift; path = Sources/CryptoSwift/CRC.swift; sourceTree = SOURCE_ROOT; };
 		757BC9251C1CA5790093AAA9 /* CSArrayType+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "CSArrayType+Extensions.swift"; path = "Sources/CryptoSwift/CSArrayType+Extensions.swift"; sourceTree = SOURCE_ROOT; };
 		757BC9261C1CA5790093AAA9 /* Generics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Generics.swift; path = Sources/CryptoSwift/Generics.swift; sourceTree = SOURCE_ROOT; };
@@ -374,17 +387,20 @@
 		757DA2581A4ED4D7002BA3EF /* ChaCha20Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChaCha20Tests.swift; sourceTree = "<group>"; };
 		757F44081CC172B6002B1F85 /* BlockCipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BlockCipher.swift; path = Sources/CryptoSwift/BlockCipher.swift; sourceTree = SOURCE_ROOT; };
 		757F440D1CC1822A002B1F85 /* SecureBytes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SecureBytes.swift; path = Sources/CryptoSwift/SecureBytes.swift; sourceTree = SOURCE_ROOT; };
-		7588034B1C8F8C33008C1576 /* BlockModeGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BlockModeGenerator.swift; path = Sources/CryptoSwift/BlockMode/BlockModeGenerator.swift; sourceTree = SOURCE_ROOT; };
 		758A94271A65C59200E46135 /* HMACTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMACTests.swift; sourceTree = "<group>"; };
 		758F58F01C8FB6E20054C377 /* OFB.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OFB.swift; path = Sources/CryptoSwift/BlockMode/OFB.swift; sourceTree = SOURCE_ROOT; };
 		75CB93241C8F5EC10087740D /* CBC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CBC.swift; path = Sources/CryptoSwift/BlockMode/CBC.swift; sourceTree = SOURCE_ROOT; };
-		75CB932F1C8F5F580087740D /* CipherBlockMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CipherBlockMode.swift; path = Sources/CryptoSwift/BlockMode/CipherBlockMode.swift; sourceTree = SOURCE_ROOT; };
+		75CB932F1C8F5F580087740D /* BlockMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BlockMode.swift; path = Sources/CryptoSwift/BlockMode/BlockMode.swift; sourceTree = SOURCE_ROOT; };
 		75CB93341C8F5FCE0087740D /* PCBC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PCBC.swift; path = Sources/CryptoSwift/BlockMode/PCBC.swift; sourceTree = SOURCE_ROOT; };
 		75CB93391C8F5FFD0087740D /* CFB.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CFB.swift; path = Sources/CryptoSwift/BlockMode/CFB.swift; sourceTree = SOURCE_ROOT; };
 		75CB93431C8F603C0087740D /* CTR.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CTR.swift; path = Sources/CryptoSwift/BlockMode/CTR.swift; sourceTree = SOURCE_ROOT; };
 		75CB93481C8F60700087740D /* ECB.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ECB.swift; path = Sources/CryptoSwift/BlockMode/ECB.swift; sourceTree = SOURCE_ROOT; };
 		75CB934D1C8F609D0087740D /* BlockModeOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BlockModeOptions.swift; path = Sources/CryptoSwift/BlockMode/BlockModeOptions.swift; sourceTree = SOURCE_ROOT; };
+		75D0E05B1CFB9B9400FCEA0E /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Cipher.swift; path = Sources/CryptoSwift/Cipher.swift; sourceTree = SOURCE_ROOT; };
+		75D1F1F31D06B98B005A87A2 /* PBKDF1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PBKDF1.swift; path = Sources/CryptoSwift/PKCS5/PBKDF1.swift; sourceTree = SOURCE_ROOT; };
 		75D614BF1BD844F2001358B2 /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		75DB81A21CDBFDC700ED181A /* BlockModeWorker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BlockModeWorker.swift; path = Sources/CryptoSwift/BlockMode/BlockModeWorker.swift; sourceTree = SOURCE_ROOT; };
+		75DB81A71CDC06B100ED181A /* UpdatableCryptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UpdatableCryptor.swift; path = Sources/CryptoSwift/UpdatableCryptor.swift; sourceTree = SOURCE_ROOT; };
 		75DF77721BC8EB59006E9520 /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		80545D121CA9FECD00474A99 /* Bit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Bit.swift; path = Sources/CryptoSwift/Bit.swift; sourceTree = SOURCE_ROOT; };
 /* End PBXFileReference section */
@@ -440,6 +456,7 @@
 			isa = PBXGroup;
 			children = (
 				75482EAB1CB329DF001F66A5 /* PKCS5.swift */,
+				75D1F1F31D06B98B005A87A2 /* PBKDF1.swift */,
 				75482EA61CB329C1001F66A5 /* PBKDF2.swift */,
 			);
 			name = PKCS5;
@@ -448,6 +465,7 @@
 		754BE44B19693E190098E6F3 = {
 			isa = PBXGroup;
 			children = (
+				755D27BC1D06DE6400C41692 /* CryptoSwift.playground */,
 				754BE45719693E190098E6F3 /* CryptoSwift */,
 				754BE46419693E190098E6F3 /* CryptoSwiftTests */,
 				754BE45619693E190098E6F3 /* Products */,
@@ -470,15 +488,14 @@
 		754BE45719693E190098E6F3 /* CryptoSwift */ = {
 			isa = PBXGroup;
 			children = (
-				757BC91A1C1CA5790093AAA9 /* AES.swift */,
+				75DB81B11CDC0E4100ED181A /* Ciphers */,
 				757BC91B1C1CA5790093AAA9 /* Array+Extension.swift */,
 				757BC91D1C1CA5790093AAA9 /* Authenticator.swift */,
 				80545D121CA9FECD00474A99 /* Bit.swift */,
 				757F440D1CC1822A002B1F85 /* SecureBytes.swift */,
 				757BC91F1C1CA5790093AAA9 /* BytesSequence.swift */,
-				757BC9201C1CA5790093AAA9 /* ChaCha20.swift */,
-				757BC9211C1CA5790093AAA9 /* CipherProtocol.swift */,
-				757F44081CC172B6002B1F85 /* BlockCipher.swift */,
+				755655C61D080E3F00F004E7 /* Cryptors.swift */,
+				75DB81A71CDC06B100ED181A /* UpdatableCryptor.swift */,
 				75CB93291C8F5EC60087740D /* BlockMode */,
 				757BC9231C1CA5790093AAA9 /* CRC.swift */,
 				757BC9251C1CA5790093AAA9 /* CSArrayType+Extensions.swift */,
@@ -496,7 +513,6 @@
 				757BC9321C1CA5790093AAA9 /* PKCS7.swift */,
 				753881EA1CB06E390089101D /* NoPadding.swift */,
 				757BC9331C1CA5790093AAA9 /* Poly1305.swift */,
-				757BC9341C1CA5790093AAA9 /* Rabbit.swift */,
 				757BC9351C1CA5790093AAA9 /* SHA1.swift */,
 				757BC9361C1CA5790093AAA9 /* SHA2.swift */,
 				757BC9371C1CA5790093AAA9 /* String+Extension.swift */,
@@ -531,7 +547,7 @@
 				674A736E1BF5D85B00866C5B /* RabbitTests.swift */,
 				755FB1D9199E347D00475437 /* ExtensionsTest.swift */,
 				757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */,
-				75482EA31CB310B7001F66A5 /* PBKDF2Tests.swift */,
+				75482EA31CB310B7001F66A5 /* PBKDF.swift */,
 				756BFDCA1A82B87300B9D9A4 /* Bridging.h */,
 				754BE46519693E190098E6F3 /* Supporting Files */,
 			);
@@ -566,9 +582,9 @@
 		75CB93291C8F5EC60087740D /* BlockMode */ = {
 			isa = PBXGroup;
 			children = (
-				7588034B1C8F8C33008C1576 /* BlockModeGenerator.swift */,
 				75CB934D1C8F609D0087740D /* BlockModeOptions.swift */,
-				75CB932F1C8F5F580087740D /* CipherBlockMode.swift */,
+				75CB932F1C8F5F580087740D /* BlockMode.swift */,
+				75DB81A21CDBFDC700ED181A /* BlockModeWorker.swift */,
 				75CB93241C8F5EC10087740D /* CBC.swift */,
 				75CB93341C8F5FCE0087740D /* PCBC.swift */,
 				75CB93391C8F5FFD0087740D /* CFB.swift */,
@@ -579,6 +595,18 @@
 			name = BlockMode;
 			sourceTree = "<group>";
 		};
+		75DB81B11CDC0E4100ED181A /* Ciphers */ = {
+			isa = PBXGroup;
+			children = (
+				757F44081CC172B6002B1F85 /* BlockCipher.swift */,
+				75D0E05B1CFB9B9400FCEA0E /* Cipher.swift */,
+				757BC91A1C1CA5790093AAA9 /* AES.swift */,
+				757BC9201C1CA5790093AAA9 /* ChaCha20.swift */,
+				757BC9341C1CA5790093AAA9 /* Rabbit.swift */,
+			);
+			name = Ciphers;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
@@ -806,6 +834,7 @@
 				754C9D1C1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */,
 				757BC99D1C1CA5790093AAA9 /* PKCS7.swift in Sources */,
 				757BC9AD1C1CA5790093AAA9 /* SHA2.swift in Sources */,
+				75DB81A41CDBFDC700ED181A /* BlockModeWorker.swift in Sources */,
 				757BC8FF1C1CA56A0093AAA9 /* AES+Foundation.swift in Sources */,
 				7574E5FF1CD02C9300E96346 /* CSArrayType+Foundation.swift in Sources */,
 				757BC9491C1CA5790093AAA9 /* Authenticator.swift in Sources */,
@@ -814,6 +843,7 @@
 				757F440F1CC1822B002B1F85 /* SecureBytes.swift in Sources */,
 				757BC9751C1CA5790093AAA9 /* HashProtocol.swift in Sources */,
 				757BC9071C1CA56A0093AAA9 /* ChaCha20+Foundation.swift in Sources */,
+				75D0E05D1CFB9B9400FCEA0E /* Cipher.swift in Sources */,
 				757BC9851C1CA5790093AAA9 /* IntExtension.swift in Sources */,
 				757BC9B11C1CA5790093AAA9 /* String+Extension.swift in Sources */,
 				757BC96D1C1CA5790093AAA9 /* Generics.swift in Sources */,
@@ -821,8 +851,7 @@
 				75CB93261C8F5EC10087740D /* CBC.swift in Sources */,
 				757BC9711C1CA5790093AAA9 /* Hash.swift in Sources */,
 				75CB93361C8F5FCE0087740D /* PCBC.swift in Sources */,
-				7588034D1C8F8C42008C1576 /* BlockModeGenerator.swift in Sources */,
-				75CB93311C8F5F580087740D /* CipherBlockMode.swift in Sources */,
+				75CB93311C8F5F580087740D /* BlockMode.swift in Sources */,
 				757BC9171C1CA56A0093AAA9 /* Utils+Foundation.swift in Sources */,
 				757BC9B51C1CA5790093AAA9 /* UInt8Extension.swift in Sources */,
 				757BC9411C1CA5790093AAA9 /* Array+Extension.swift in Sources */,
@@ -839,7 +868,10 @@
 				757BC9811C1CA5790093AAA9 /* IntegerConvertible.swift in Sources */,
 				757BC9511C1CA5790093AAA9 /* BytesSequence.swift in Sources */,
 				757BC9891C1CA5790093AAA9 /* MD5.swift in Sources */,
+				75DB81A91CDC06B100ED181A /* UpdatableCryptor.swift in Sources */,
 				757BC9A91C1CA5790093AAA9 /* SHA1.swift in Sources */,
+				75D1F1F51D06B98B005A87A2 /* PBKDF1.swift in Sources */,
+				755655C81D080E3F00F004E7 /* Cryptors.swift in Sources */,
 				757BC9911C1CA5790093AAA9 /* Operators.swift in Sources */,
 				75CB933B1C8F5FFD0087740D /* CFB.swift in Sources */,
 				757BC9B91C1CA5790093AAA9 /* UInt32Extension.swift in Sources */,
@@ -850,7 +882,6 @@
 				757BC9951C1CA5790093AAA9 /* Padding.swift in Sources */,
 				80545D141CA9FECD00474A99 /* Bit.swift in Sources */,
 				757BC9A51C1CA5790093AAA9 /* Rabbit.swift in Sources */,
-				757BC9591C1CA5790093AAA9 /* CipherProtocol.swift in Sources */,
 				757BC90B1C1CA56A0093AAA9 /* NSData+Extension.swift in Sources */,
 				757BC9791C1CA5790093AAA9 /* HMAC.swift in Sources */,
 				75482EAD1CB329DF001F66A5 /* PKCS5.swift in Sources */,
@@ -865,6 +896,7 @@
 				754C9D1B1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */,
 				757BC99C1C1CA5790093AAA9 /* PKCS7.swift in Sources */,
 				757BC9AC1C1CA5790093AAA9 /* SHA2.swift in Sources */,
+				75DB81A31CDBFDC700ED181A /* BlockModeWorker.swift in Sources */,
 				757BC9161C1CA56A0093AAA9 /* Utils+Foundation.swift in Sources */,
 				7574E5FE1CD02C8B00E96346 /* CSArrayType+Foundation.swift in Sources */,
 				757BC9481C1CA5790093AAA9 /* Authenticator.swift in Sources */,
@@ -873,6 +905,7 @@
 				757F440E1CC1822B002B1F85 /* SecureBytes.swift in Sources */,
 				757BC9741C1CA5790093AAA9 /* HashProtocol.swift in Sources */,
 				757BC90E1C1CA56A0093AAA9 /* Rabbit+Foundation.swift in Sources */,
+				75D0E05C1CFB9B9400FCEA0E /* Cipher.swift in Sources */,
 				757BC9841C1CA5790093AAA9 /* IntExtension.swift in Sources */,
 				757BC9B01C1CA5790093AAA9 /* String+Extension.swift in Sources */,
 				757BC96C1C1CA5790093AAA9 /* Generics.swift in Sources */,
@@ -880,7 +913,7 @@
 				75CB93251C8F5EC10087740D /* CBC.swift in Sources */,
 				757BC9701C1CA5790093AAA9 /* Hash.swift in Sources */,
 				75CB93351C8F5FCE0087740D /* PCBC.swift in Sources */,
-				75CB93301C8F5F580087740D /* CipherBlockMode.swift in Sources */,
+				75CB93301C8F5F580087740D /* BlockMode.swift in Sources */,
 				757BC9121C1CA56A0093AAA9 /* String+FoundationExtension.swift in Sources */,
 				757BC9B41C1CA5790093AAA9 /* UInt8Extension.swift in Sources */,
 				757BC9401C1CA5790093AAA9 /* Array+Extension.swift in Sources */,
@@ -898,9 +931,11 @@
 				757BC9501C1CA5790093AAA9 /* BytesSequence.swift in Sources */,
 				757BC9881C1CA5790093AAA9 /* MD5.swift in Sources */,
 				757BC9A81C1CA5790093AAA9 /* SHA1.swift in Sources */,
+				75DB81A81CDC06B100ED181A /* UpdatableCryptor.swift in Sources */,
+				75D1F1F41D06B98B005A87A2 /* PBKDF1.swift in Sources */,
+				755655C71D080E3F00F004E7 /* Cryptors.swift in Sources */,
 				757BC9901C1CA5790093AAA9 /* Operators.swift in Sources */,
 				75CB933A1C8F5FFD0087740D /* CFB.swift in Sources */,
-				7588034C1C8F8C33008C1576 /* BlockModeGenerator.swift in Sources */,
 				757BC9B81C1CA5790093AAA9 /* UInt32Extension.swift in Sources */,
 				757BC8FE1C1CA56A0093AAA9 /* AES+Foundation.swift in Sources */,
 				757BC98C1C1CA5790093AAA9 /* Multiplatform.swift in Sources */,
@@ -909,7 +944,6 @@
 				757BC9941C1CA5790093AAA9 /* Padding.swift in Sources */,
 				80545D131CA9FECD00474A99 /* Bit.swift in Sources */,
 				757BC9A41C1CA5790093AAA9 /* Rabbit.swift in Sources */,
-				757BC9581C1CA5790093AAA9 /* CipherProtocol.swift in Sources */,
 				757BC9021C1CA56A0093AAA9 /* ArrayUInt8+Foundation.swift in Sources */,
 				757BC9781C1CA5790093AAA9 /* HMAC.swift in Sources */,
 				75482EAC1CB329DF001F66A5 /* PKCS5.swift in Sources */,
@@ -921,7 +955,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				75482EA41CB310B7001F66A5 /* PBKDF2Tests.swift in Sources */,
+				75482EA41CB310B7001F66A5 /* PBKDF.swift in Sources */,
 				758A94291A65C67400E46135 /* HMACTests.swift in Sources */,
 				75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */,
 				757DA2571A4ED47B002BA3EF /* Helpers.swift in Sources */,
@@ -941,6 +975,7 @@
 				754C9D1D1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */,
 				757BC99E1C1CA5790093AAA9 /* PKCS7.swift in Sources */,
 				757BC9AE1C1CA5790093AAA9 /* SHA2.swift in Sources */,
+				75DB81A61CDBFDC700ED181A /* BlockModeWorker.swift in Sources */,
 				757BC9181C1CA56A0093AAA9 /* Utils+Foundation.swift in Sources */,
 				7574E6011CD02C9400E96346 /* CSArrayType+Foundation.swift in Sources */,
 				757BC94A1C1CA5790093AAA9 /* Authenticator.swift in Sources */,
@@ -949,6 +984,7 @@
 				757F44111CC1822B002B1F85 /* SecureBytes.swift in Sources */,
 				757BC9761C1CA5790093AAA9 /* HashProtocol.swift in Sources */,
 				757BC9101C1CA56A0093AAA9 /* Rabbit+Foundation.swift in Sources */,
+				75D0E05F1CFB9B9400FCEA0E /* Cipher.swift in Sources */,
 				757BC9861C1CA5790093AAA9 /* IntExtension.swift in Sources */,
 				757BC9B21C1CA5790093AAA9 /* String+Extension.swift in Sources */,
 				757BC96E1C1CA5790093AAA9 /* Generics.swift in Sources */,
@@ -956,8 +992,7 @@
 				75CB93271C8F5EC10087740D /* CBC.swift in Sources */,
 				757BC9721C1CA5790093AAA9 /* Hash.swift in Sources */,
 				75CB93371C8F5FCE0087740D /* PCBC.swift in Sources */,
-				7588034E1C8F8C42008C1576 /* BlockModeGenerator.swift in Sources */,
-				75CB93321C8F5F580087740D /* CipherBlockMode.swift in Sources */,
+				75CB93321C8F5F580087740D /* BlockMode.swift in Sources */,
 				757BC9141C1CA56A0093AAA9 /* String+FoundationExtension.swift in Sources */,
 				757BC9B61C1CA5790093AAA9 /* UInt8Extension.swift in Sources */,
 				757BC9421C1CA5790093AAA9 /* Array+Extension.swift in Sources */,
@@ -974,7 +1009,10 @@
 				757BC9821C1CA5790093AAA9 /* IntegerConvertible.swift in Sources */,
 				757BC9521C1CA5790093AAA9 /* BytesSequence.swift in Sources */,
 				757BC98A1C1CA5790093AAA9 /* MD5.swift in Sources */,
+				75DB81AB1CDC06B100ED181A /* UpdatableCryptor.swift in Sources */,
 				757BC9AA1C1CA5790093AAA9 /* SHA1.swift in Sources */,
+				75D1F1F71D06B98B005A87A2 /* PBKDF1.swift in Sources */,
+				755655CA1D080E3F00F004E7 /* Cryptors.swift in Sources */,
 				757BC9921C1CA5790093AAA9 /* Operators.swift in Sources */,
 				75CB933C1C8F5FFD0087740D /* CFB.swift in Sources */,
 				757BC9BA1C1CA5790093AAA9 /* UInt32Extension.swift in Sources */,
@@ -985,7 +1023,6 @@
 				757BC9961C1CA5790093AAA9 /* Padding.swift in Sources */,
 				80545D161CA9FECD00474A99 /* Bit.swift in Sources */,
 				757BC9A61C1CA5790093AAA9 /* Rabbit.swift in Sources */,
-				757BC95A1C1CA5790093AAA9 /* CipherProtocol.swift in Sources */,
 				757BC9041C1CA56A0093AAA9 /* ArrayUInt8+Foundation.swift in Sources */,
 				757BC97A1C1CA5790093AAA9 /* HMAC.swift in Sources */,
 				75482EAF1CB329DF001F66A5 /* PKCS5.swift in Sources */,
@@ -1000,6 +1037,7 @@
 				754C9D1E1C30800A0003D5FE /* String+LinuxFoundation.swift in Sources */,
 				757BC99F1C1CA5790093AAA9 /* PKCS7.swift in Sources */,
 				757BC9AF1C1CA5790093AAA9 /* SHA2.swift in Sources */,
+				75DB81A51CDBFDC700ED181A /* BlockModeWorker.swift in Sources */,
 				757BC9011C1CA56A0093AAA9 /* AES+Foundation.swift in Sources */,
 				7574E6001CD02C9300E96346 /* CSArrayType+Foundation.swift in Sources */,
 				757BC94B1C1CA5790093AAA9 /* Authenticator.swift in Sources */,
@@ -1008,6 +1046,7 @@
 				757F44101CC1822B002B1F85 /* SecureBytes.swift in Sources */,
 				757BC9771C1CA5790093AAA9 /* HashProtocol.swift in Sources */,
 				757BC9091C1CA56A0093AAA9 /* ChaCha20+Foundation.swift in Sources */,
+				75D0E05E1CFB9B9400FCEA0E /* Cipher.swift in Sources */,
 				757BC9871C1CA5790093AAA9 /* IntExtension.swift in Sources */,
 				757BC9B31C1CA5790093AAA9 /* String+Extension.swift in Sources */,
 				757BC96F1C1CA5790093AAA9 /* Generics.swift in Sources */,
@@ -1015,8 +1054,7 @@
 				75CB93281C8F5EC10087740D /* CBC.swift in Sources */,
 				757BC9731C1CA5790093AAA9 /* Hash.swift in Sources */,
 				75CB93381C8F5FCE0087740D /* PCBC.swift in Sources */,
-				7588034F1C8F8C43008C1576 /* BlockModeGenerator.swift in Sources */,
-				75CB93331C8F5F580087740D /* CipherBlockMode.swift in Sources */,
+				75CB93331C8F5F580087740D /* BlockMode.swift in Sources */,
 				757BC9191C1CA56A0093AAA9 /* Utils+Foundation.swift in Sources */,
 				757BC9B71C1CA5790093AAA9 /* UInt8Extension.swift in Sources */,
 				757BC9431C1CA5790093AAA9 /* Array+Extension.swift in Sources */,
@@ -1033,7 +1071,10 @@
 				757BC9831C1CA5790093AAA9 /* IntegerConvertible.swift in Sources */,
 				757BC9531C1CA5790093AAA9 /* BytesSequence.swift in Sources */,
 				757BC98B1C1CA5790093AAA9 /* MD5.swift in Sources */,
+				75DB81AA1CDC06B100ED181A /* UpdatableCryptor.swift in Sources */,
 				757BC9AB1C1CA5790093AAA9 /* SHA1.swift in Sources */,
+				75D1F1F61D06B98B005A87A2 /* PBKDF1.swift in Sources */,
+				755655C91D080E3F00F004E7 /* Cryptors.swift in Sources */,
 				757BC9931C1CA5790093AAA9 /* Operators.swift in Sources */,
 				75CB933D1C8F5FFD0087740D /* CFB.swift in Sources */,
 				757BC9BB1C1CA5790093AAA9 /* UInt32Extension.swift in Sources */,
@@ -1044,7 +1085,6 @@
 				757BC9971C1CA5790093AAA9 /* Padding.swift in Sources */,
 				80545D151CA9FECD00474A99 /* Bit.swift in Sources */,
 				757BC9A71C1CA5790093AAA9 /* Rabbit.swift in Sources */,
-				757BC95B1C1CA5790093AAA9 /* CipherProtocol.swift in Sources */,
 				757BC90D1C1CA56A0093AAA9 /* NSData+Extension.swift in Sources */,
 				757BC97B1C1CA5790093AAA9 /* HMAC.swift in Sources */,
 				75482EAE1CB329DF001F66A5 /* PKCS5.swift in Sources */,
@@ -1244,7 +1284,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				PRODUCT_BUNDLE_IDENTIFIER = "com.hakore.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_BUNDLE_IDENTIFIER = com.krzyzanowskim.CryptoSwift;
 				PRODUCT_NAME = CryptoSwift;
 				SKIP_INSTALL = YES;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -1268,7 +1308,7 @@
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LLVM_LTO = YES;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.hakore.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_BUNDLE_IDENTIFIER = com.krzyzanowskim.CryptoSwift;
 				PRODUCT_NAME = CryptoSwift;
 				SKIP_INSTALL = YES;
 				SWIFT_DISABLE_SAFETY_CHECKS = YES;

+ 0 - 0
CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint


+ 7 - 0
CryptoSwift.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "container:CryptoSwift.xcodeproj">
+   </FileRef>
+</Workspace>

+ 0 - 0
CryptoSwift.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint


+ 48 - 20
CryptoSwiftTests/AESTests.swift

@@ -30,7 +30,6 @@ final class AESTests: XCTestCase {
         let key = "679fb1ddf7d81bee"
         let iv = "kdf67398DF7383fd"
         let input:[UInt8] = [0x62, 0x72, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
-        
         let expected:[UInt8] = [0xae,0x8c,0x59,0x95,0xb2,0x6f,0x8e,0x3d,0xb0,0x6f,0x0a,0xa5,0xfe,0xc4,0xf0,0xc2];
         
         let aes = try! AES(key: key, iv: iv, blockMode: .CBC, padding: NoPadding())
@@ -41,15 +40,8 @@ final class AESTests: XCTestCase {
     }
     
     func testAES_encrypt() {
-        let input:[UInt8] = [0x00, 0x11, 0x22, 0x33,
-            0x44, 0x55, 0x66, 0x77,
-            0x88, 0x99, 0xaa, 0xbb,
-            0xcc, 0xdd, 0xee, 0xff];
-        
-        let expected:[UInt8] = [0x69, 0xc4, 0xe0, 0xd8,
-            0x6a, 0x7b, 0x4, 0x30,
-            0xd8, 0xcd, 0xb7, 0x80,
-            0x70, 0xb4, 0xc5, 0x5a];
+        let input:[UInt8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff];
+        let expected:[UInt8] = [0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x4, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a];
         
         let aes = try! AES(key: aesKey, blockMode: .ECB, padding: NoPadding())
         let encrypted = try! aes.encrypt(input)
@@ -65,7 +57,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d];
 
         let aes = try! AES(key: key, iv:iv, blockMode: .CBC, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .CBC, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -79,13 +70,57 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d,0x89,0x64,0xe0,0xb1,0x49,0xc1,0x0b,0x7b,0x68,0x2e,0x6e,0x39,0xaa,0xeb,0x73,0x1c]
         
         let aes = try! AES(key: key, iv:iv, blockMode: .CBC, padding: PKCS7())
-        XCTAssertTrue(aes.blockMode == .CBC, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
         XCTAssertEqual(decrypted, plaintext, "decryption failed")
     }
-    
+
+    func testAES_encrypt_cbc_with_padding_partial() {
+        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 plaintext:[UInt8] = [0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a]
+
+        let aes = try! AES(key: key, iv:iv, blockMode: .CBC, padding: PKCS7())
+
+        var ciphertext = [UInt8]()
+        var encryptor = aes.makeEncryptor()
+        ciphertext += try! encryptor.update(withBytes: Array(plaintext[0..<8]))
+        ciphertext += try! encryptor.update(withBytes: Array(plaintext[8..<16]))
+        ciphertext += try! encryptor.update(withBytes: Array(plaintext[16..<32]))
+        ciphertext += try! encryptor.finish()
+        XCTAssertEqual(try! aes.encrypt(plaintext), ciphertext, "encryption failed")
+    }
+
+    func testAES_encrypt_incremental() {
+        do {
+            var ciphertext = Array<UInt8>()
+            let plaintext = "Today Apple launched the open source Swift community, as well as amazing new tools and resources."
+            let aes = try AES(key: "passwordpassword".utf8.map({$0}), iv: "drowssapdrowssap".utf8.map({$0}))
+            var encryptor = aes.makeEncryptor()
+
+            ciphertext += try encryptor.update(withBytes: plaintext.utf8.map({$0}))
+            ciphertext += try encryptor.finish()
+        } catch {
+            XCTAssert(false, "\(error)")
+        }
+    }
+
+    func testAES_decrypt_cbc_with_padding_partial() {
+        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 ciphertext:[UInt8] = [118, 73, 171, 172, 129, 25, 178, 70, 206, 233, 142, 155, 18, 233, 25, 125, 76, 187, 200, 88, 117, 107, 53, 129, 37, 82, 158, 150, 152, 163, 143, 68, 169, 105, 137, 234, 93, 98, 239, 215, 41, 45, 51, 254, 138, 92, 251, 17]
+
+        let aes = try! AES(key: key, iv:iv, blockMode: .CBC, padding: PKCS7())
+        var plaintext = [UInt8]()
+        var decryptor = aes.makeDecryptor()
+        plaintext += try! decryptor.update(withBytes: Array(ciphertext[0..<8]))
+        plaintext += try! decryptor.update(withBytes: Array(ciphertext[8..<16]))
+        plaintext += try! decryptor.update(withBytes: Array(ciphertext[16..<32]))
+        plaintext += try! decryptor.finish()
+        XCTAssertEqual(try! aes.decrypt(ciphertext), plaintext, "encryption failed")
+    }
+
     func testAES_encrypt_cfb() {
         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]
@@ -93,7 +128,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20,0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a];
         
         let aes = try! AES(key: key, iv:iv, blockMode: .CFB, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .CFB, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -117,7 +151,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20,0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a];
 
         let aes = try! AES(key: key, iv:iv, blockMode: .OFB, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .OFB, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -131,7 +164,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0xdc,0x7e,0x84,0xbf,0xda,0x79,0x16,0x4b,0x7e,0xcd,0x84,0x86,0x98,0x5d,0x38,0x60];
 
         let aes = try! AES(key: key, iv:iv, blockMode: .OFB, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .OFB, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -145,7 +177,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba,0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6];
 
         let aes = try! AES(key: key, iv:iv, blockMode: .PCBC, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .PCBC, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         print(encrypted.toHexString())
         XCTAssertEqual(encrypted, expected, "encryption failed")
@@ -160,7 +191,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26,0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce]
         
         let aes = try! AES(key: key, iv:iv, blockMode: .CTR, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .CTR, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -174,7 +204,6 @@ final class AESTests: XCTestCase {
         let expected:[UInt8] = [0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26,0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce,0x37]
 
         let aes = try! AES(key: key, iv:iv, blockMode: .CTR, padding: NoPadding())
-        XCTAssertTrue(aes.blockMode == .CTR, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         XCTAssertEqual(encrypted, expected, "encryption failed")
         let decrypted = try! aes.decrypt(encrypted)
@@ -248,7 +277,6 @@ final class AESTests: XCTestCase {
 
         let aes = try! AES(key: key, iv:iv, blockMode: .CBC, padding: PKCS7())
         let aes2 = try! AES(key: key2, iv:iv, blockMode: .CBC, padding: PKCS7())
-        XCTAssertTrue(aes.blockMode == .CBC, "Invalid block mode")
         let encrypted = try! aes.encrypt(plaintext)
         let decrypted = try? aes2.decrypt(encrypted)
         XCTAssertTrue(decrypted! != plaintext, "failed")

+ 10 - 0
CryptoSwiftTests/HashTests.swift

@@ -126,6 +126,16 @@ final class CryptoSwiftTests: XCTestCase {
         XCTAssertEqual("".crc32(nil), "00000000", "CRC32 calculation failed");
     }
     
+    func testCRC32NotReflected() {
+        let bytes : [UInt8] = [0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]
+        let data:NSData = NSData(bytes: bytes, length: bytes.count)
+        if let crc = data.crc32(nil, reflect: false) {
+            XCTAssertEqual(crc.toHexString(), "fc891918", "CRC32 (with reflection) calculation failed");
+        }
+        
+        XCTAssertEqual("".crc32(nil, reflect: false), "00000000", "CRC32 (with reflection) calculation failed");
+    }
+    
     func testCRC16() {
         let result = CRC().crc16([49,50,51,52,53,54,55,56,57] as [UInt8])
         XCTAssert(result == 0xBB3D, "CRC16 failed")

+ 11 - 4
CryptoSwiftTests/PBKDF2Tests.swift → CryptoSwiftTests/PBKDF.swift

@@ -1,5 +1,5 @@
 //
-//  PBKDF2Tests.swift
+//  PBKDF.swift
 //  CryptoSwift
 //
 //  Created by Marcin Krzyzanowski on 04/04/16.
@@ -9,7 +9,7 @@
 import XCTest
 @testable import CryptoSwift
 
-class PBKDF2Tests: XCTestCase {
+class PBKDF: XCTestCase {
 
     override func setUp() {
         super.setUp()
@@ -19,10 +19,17 @@ class PBKDF2Tests: XCTestCase {
         super.tearDown()
     }
 
-    func test1() {
+    func test_pbkdf1() {
+        let password: [UInt8] = [0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64]
+        let salt: [UInt8] = [0x78,0x57,0x8E,0x5A,0x5D,0x63,0xCB,0x06]
+        let value = try! PKCS5.PBKDF1(password: password, salt: salt, iterations: 1000, keyLength: 16, variant: .sha1).calculate()
+        XCTAssertEqual(value.toHexString(), "dc19847e05c64d2faf10ebfb4a3d2a20")
+    }
+
+    func test_pbkdf2() {
         let password: [UInt8] = "s33krit".utf8.map {$0}
         let salt: [UInt8] = "nacl".utf8.map {$0}
-        let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 2, keyLength: 123, hashVariant: .sha1).calculate()
+        let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 2, keyLength: 123, variant: .sha1).calculate()
         XCTAssert(value.toHexString() == "a53cf3df485e5cd91c17c4978048e3ca86e03cced5f748fb55eff9c1edfce7f9f490c0beee768b85c1ba14ec5750cf059fea52565ffd9e4f9dba01c5c953955e7f1012b6a9eb40629ce767982e598df9081048e22781b35187c16d61ac43f69b88630a9e80233b4c58bdc74ea5c06b5bb1b2c2a86e3ddc2775b852c4508ac85a6a47c0e23a3d8dc6e4dca583", "PBKDF2 fail")
     }
 

+ 67 - 46
README.md

@@ -2,16 +2,15 @@
 
 Crypto related functions and helpers for [Swift](https://developer.apple.com/swift/) implemented in Swift. ([#PureSwift](https://twitter.com/hashtag/pureswift))
 
--------
-<p align="center">
-    <a href="#features">Features</a> &bull;
-    <a href="#contribution">Contribution</a> &bull;
-    <a href="#installation">Installation</a> &bull;
-    <a href="#usage">Usage</a> &bull; 
-    <a href="#author">Author</a> &bull;
-    <a href="#changelog">Changelog</a>
-</p>
--------
+#Table of Contents
+- [Requirements](#requirements)
+- [Features](#features)
+- [Contribution](#contribution)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Author](#author)
+- [License](#license)
+- [Changelog](#changelog)
 
 ##Requirements
 Good mood
@@ -22,9 +21,7 @@ Good mood
 - Convenient extensions for String and NSData
 - iOS, OSX, AppleTV, watchOS, Linux support
 
-##What implemented?
-
-#### Hash
+#### Hash (Digest)
 - [MD5](http://tools.ietf.org/html/rfc1321)
 - [SHA1](http://tools.ietf.org/html/rfc3174)
 - [SHA224](http://tools.ietf.org/html/rfc6234)
@@ -36,16 +33,16 @@ Good mood
 - [CRC32](http://en.wikipedia.org/wiki/Cyclic_redundancy_check)
 - [CRC16](http://en.wikipedia.org/wiki/Cyclic_redundancy_check)
 
-#####Cipher
+#### Cipher
 - [AES-128, AES-192, AES-256](http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf)
 - [ChaCha20](http://cr.yp.to/chacha/chacha-20080128.pdf)
 - [Rabbit](https://tools.ietf.org/html/rfc4503)
 
-#####Message authenticators
+#### Message authenticators
 - [Poly1305](http://cr.yp.to/mac/poly1305-20050329.pdf)
 - [HMAC](https://www.ietf.org/rfc/rfc2104.txt) MD5, SHA1, SHA256
 
-#####Cipher block mode
+#### Cipher block mode
 - Electronic codebook ([ECB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29))
 - Cipher-block chaining ([CBC](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29))
 - Propagating Cipher Block Chaining ([PCBC](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Propagating_Cipher_Block_Chaining_.28PCBC.29))
@@ -53,10 +50,11 @@ Good mood
 - Output Feedback ([OFB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_Feedback_.28OFB.29))
 - Counter ([CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29))
 
-#####Password-Based Key Derivation Function
+#### Password-Based Key Derivation Function
+- [PBKDF1](http://tools.ietf.org/html/rfc2898#section-5.1) (Password-Based Key Derivation Function 1)
 - [PBKDF2](http://tools.ietf.org/html/rfc2898#section-5.2) (Password-Based Key Derivation Function 2)
 
-#####Data padding
+#### Data padding
 - [PKCS#7](http://tools.ietf.org/html/rfc5652#section-6.3)
 - NoPadding
 
@@ -137,11 +135,27 @@ You can use [Swift Package Manager](https://swift.org/package-manager/) and spec
  
 ##Usage
 
+* [Basics (data types, conversion, ...)](#basics)
+* [Calculate Hash (MD5, SHA...)](#calculate-hash)
+* [Message authenticators (HMAC...)](#message-authenticators)
+* [Password-Based Key Derivation Function (PBKDF2, ...)](password-based-key-derivation-function)
+* [Data Padding](#data-padding)
+* [ChaCha20](#chacha20)
+* [Rabbit](#rabbit)
+* [Advanced Encryption Standard (AES)](#aes)
+
+
+also check [Playground](/CryptoSwift.playground/Contents.swift)
+
+#####Basics
+
 ```swift
 import CryptoSwift
 ```
 
-#####Conversion between NSData and [UInt8]
+CryptoSwift use array of bytes aka `Array<UInt8>` as base type for all operations. Every data can be converted to stream of bytes. you will find convenience functions that accept String or NSData, and it will be internally converted to array of bytes anyway.
+
+#####Data conversions
 
 For you convenience CryptoSwift provide two function to easily convert array of bytes to NSData and other way around:
 
@@ -150,9 +164,12 @@ let data: NSData = NSData(bytes: [0x01, 0x02, 0x03])
 let bytes:[UInt8] = data.arrayOfBytes()
 ```
 
-#####Calculate Hash
+Make bytes out of `String`:
+```swift
+let bytes = "string".utf8.map({$0})
+```
 
-For your convenience you should use extensions methods like encrypt(), decrypt(), md5(), sha1() and so on.
+#####Calculate Hash
 
 Hashing a data or array of bytes (aka `Array<UInt8>`)
 ```swift
@@ -201,7 +218,10 @@ let hmac: [UInt8] = try! Authenticator.HMAC(key: key, variant: .sha256).authenti
 let password: [UInt8] = "s33krit".utf8.map {$0}
 let salt: [UInt8] = "nacl".utf8.map {$0}
 
-let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, hashVariant: .sha256).calculate()
+let value = try! PKCS5.PBKDF1(password: password, salt: salt, iterations: 4096, variant: .sha1).calculate()
+
+let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, variant: .sha256).calculate()
+
 value.toHexString() // print Hex representation
 ```
 
@@ -232,7 +252,7 @@ let decrypted = Rabbit(key: key, iv: iv)?.decrypt(encrypted!)
 
 Notice regarding padding: *Manual padding of data is optional and CryptoSwift is using PKCS7 padding by default. If you need manually disable/enable padding, you can do this by setting parameter for __AES__ class*
 
-Basic:
+######All at once
 ```swift
 let input = NSData()
 let encrypted = try! input.encrypt(AES(key: "secret0key000000", iv:"0123456789012345"))
@@ -241,25 +261,28 @@ let input: [UInt8] = [0,1,2,3,4,5,6,7,8,9]
 input.encrypt(AES(key: "secret0key000000", iv:"0123456789012345", blockMode: .CBC))
 ```
 
-Encrypt/Decrypt String to Base64 encoded string:
+######Incremental updates
 
-```swift
-// Encrypt string and get Base64 representation of result
-let base64String = try! "my secret string".encrypt(AES(key: "secret0key000000", iv: "0123456789012345")).toBase64()
+Incremental operations uses instance of Cryptor and encrypt/decrypt one part at time, this way you can save on memory for large files. 
 
-// Decrypt Base64 encrypted message with helper function:
-let decrypted = try! encryptedBase64.decryptBase64ToString(AES(key: "secret0key000000", iv: "0123456789012345"))
+```swift
+let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap")
+var encryptor = aes.makeEncryptor()
+
+var ciphertext = Array<UInt8>()
+ciphertext += try encryptor.update(withBytes: "Nullam quis risus ".utf8.map({$0}))
+ciphertext += try encryptor.update(withBytes: "eget urna mollis ".utf8.map({$0}))
+ciphertext += try encryptor.update(withBytes: "ornare vel eu leo.".utf8.map({$0}))
+ciphertext += try encryptor.finish()
 ```
 
-...under the hood, this is [UInt8] converted to NSData converted to Base64 string representation:
-
-```swift
-let encryptedBytes: [UInt8] = try! "my secret string".encrypt(AES(key: "secret0key000000", iv: "0123456789012345"))
+See [Playground](/CryptoSwift.playground/Contents.swift) for sample code to work with streams.
 
-let base64 = NSData(bytes: encryptedBytes).base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
-```
+Check this helper functions to work with **Base64** encoded data directly:
+- .decryptBase64ToString()
+- .toBase64()
 
-Advanced:
+######AES Advanced usage
 ```swift
 let input: [UInt8] = [0,1,2,3,4,5,6,7,8,9]
 
@@ -267,12 +290,10 @@ let key: [UInt8] = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 let iv: [UInt8] = AES.randomIV(AES.blockSize)
 
 do {
-    let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC, padding: PKCS7()).encrypt(input)
-    let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC, padding: PKCS7()).decrypt(encrypted)
-} catch AES.Error.BlockSizeExceeded {
-    // block size exceeded
+    let encrypted = try AES(key: key, iv: iv, blockMode: .CBC, padding: PKCS7()).encrypt(input)
+    let decrypted = try AES(key: key, iv: iv, blockMode: .CBC, padding: PKCS7()).decrypt(encrypted)
 } catch {
-    // some error
+	print(error)
 }	
 ```
 	
@@ -283,7 +304,7 @@ let input: [UInt8] = [0,1,2,3,4,5,6,7,8,9]
 let encrypted: [UInt8] = try! AES(key: "secret0key000000", iv:"0123456789012345", blockMode: .CBC, padding: NoPadding()).encrypt(input)
 ```
 
-Using extensions
+Using convenience extensions
 	
 ```swift
 let plain = NSData()
@@ -294,20 +315,20 @@ let decrypted: NSData = try! encrypted.decrypt(ChaCha20(key: key, iv: iv))
 
 ##Author
 
-CryptoSwift is owned and maintained by Marcin Krzyżanowski. You can follow me on Twitter at [@krzyzanowskim](http://twitter.com/krzyzanowskim) for project updates and releases.
+CryptoSwift is owned and maintained by [Marcin Krzyżanowski](http://www.krzyzanowskim.com)
 
-[Marcin Krzyżanowski](http://www.krzyzanowskim.com)
+You can follow me on Twitter at [@krzyzanowskim](http://twitter.com/krzyzanowskim) for project updates and releases.
 
 ##License
 
-Copyright (C) 2014 Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com>
+Copyright (C) 2014-2016 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
 This software is provided 'as-is', without any express or implied warranty. 
 
 In no event will the authors be held liable for any damages arising from the use of this software. 
 
 Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
 
-- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, **an acknowledgment in the product documentation is required**.
 - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
 - This notice may not be removed or altered from any source or binary distribution.
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4 - 4
Sources/CryptoSwift/AES.swift


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

@@ -17,7 +17,7 @@ extension Array {
             words.append(word)
         }
         let reminder = Array(self.suffix(self.count % chunksize))
-        if (reminder.count > 0) {
+        if !reminder.isEmpty {
             words.append(reminder)
         }
         return words

+ 47 - 0
Sources/CryptoSwift/BlockMode/BlockMode.swift

@@ -0,0 +1,47 @@
+//
+//  BlockMode.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 08/03/16.
+//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
+//
+
+typealias CipherOperationOnBlock = (block: [UInt8]) -> [UInt8]?
+
+public enum BlockMode {
+    case ECB, CBC, PCBC, CFB, OFB, CTR
+
+    func worker(iv: Array<UInt8>?, cipherOperation: CipherOperationOnBlock) -> BlockModeWorker {
+        switch (self) {
+        case ECB:
+            return ECBModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+        case CBC:
+            return CBCModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+        case PCBC:
+            return PCBCModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+        case CFB:
+            return CFBModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+        case OFB:
+            return OFBModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+        case CTR:
+            return CTRModeWorker(iv: iv ?? [], cipherOperation: cipherOperation)
+        }
+    }
+
+    var options: BlockModeOptions {
+        switch (self) {
+        case .ECB:
+            return .PaddingRequired
+        case .CBC:
+            return [.InitializationVectorRequired, .PaddingRequired]
+        case .CFB:
+            return .InitializationVectorRequired
+        case .CTR:
+            return .InitializationVectorRequired
+        case .OFB:
+            return .InitializationVectorRequired
+        case .PCBC:
+            return [.InitializationVectorRequired, .PaddingRequired]
+        }
+    }
+}

+ 0 - 19
Sources/CryptoSwift/BlockMode/BlockModeGenerator.swift

@@ -1,19 +0,0 @@
-//
-//  BlockModeGenerator.swift
-//  CryptoSwift
-//
-//  Created by Marcin Krzyzanowski on 08/03/16.
-//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
-//
-
-// I have no better name for that
-
-enum BlockError: ErrorType {
-    case MissingInitializationVector
-}
-
-typealias CipherOperationOnBlock = (block: [UInt8]) -> [UInt8]?
-
-protocol BlockModeGenerator: GeneratorType {
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>)
-}

+ 13 - 0
Sources/CryptoSwift/BlockMode/BlockModeWorker.swift

@@ -0,0 +1,13 @@
+//
+//  BlockModeWorker.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 06/05/16.
+//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
+//
+
+protocol BlockModeWorker {
+    var cipherOperation: CipherOperationOnBlock { get }
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8]
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8]
+}

+ 14 - 39
Sources/CryptoSwift/BlockMode/CBC.swift

@@ -8,57 +8,32 @@
 //  Cipher-block chaining (CBC)
 //
 
-struct CBCModeEncryptGenerator: BlockModeGenerator {
+struct CBCModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
 
+    let cipherOperation: CipherOperationOnBlock
     private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
+    private var prev: Element?
 
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
+    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
     }
 
-    mutating func next() -> Element? {
-        guard let plaintext = inputGenerator.next(),
-              let encrypted = cipherOperation(block: xor(prevCiphertext ?? iv, plaintext))
-        else {
-            return nil
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8] {
+        guard let ciphertext = cipherOperation(block: xor(prev ?? iv, plaintext)) else {
+            return plaintext
         }
-
-        self.prevCiphertext = encrypted
-        return encrypted
+        prev = ciphertext
+        return ciphertext ?? []
     }
-}
-
-struct CBCModeDecryptGenerator: BlockModeGenerator {
-    typealias Element = Array<UInt8>
-
-    private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
 
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
-        self.iv = iv
-        self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
-    }
-
-    mutating func next() -> Element? {
-        guard let ciphertext = inputGenerator.next(),
-              let decrypted = cipherOperation(block: ciphertext)
-        else {
-            return nil
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8] {
+        guard let plaintext = cipherOperation(block: ciphertext) else {
+            return ciphertext
         }
-
-        let result = xor(prevCiphertext ?? iv, decrypted)
-        self.prevCiphertext = ciphertext
+        let result = xor(prev ?? iv, plaintext)
+        self.prev = ciphertext
         return result
     }
 }

+ 15 - 40
Sources/CryptoSwift/BlockMode/CFB.swift

@@ -8,57 +8,32 @@
 //  Cipher feedback (CFB)
 //
 
-struct CFBModeEncryptGenerator: BlockModeGenerator {
+struct CFBModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
 
+    let cipherOperation: CipherOperationOnBlock
     private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
+    private var prev: Element?
 
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) {
+    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
     }
 
-    mutating func next() -> Element? {
-        guard let plaintext = inputGenerator.next(),
-            let ciphertext = cipherOperation(block: prevCiphertext ?? iv)
-            else {
-                return nil
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8] {
+        guard let ciphertext = cipherOperation(block: prev ?? iv) else {
+            return plaintext
         }
-
-        self.prevCiphertext = xor(plaintext, ciphertext)
-        return self.prevCiphertext
-    }
-}
-
-struct CFBModeDecryptGenerator: BlockModeGenerator {
-    typealias Element = Array<UInt8>
-
-    private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
-
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
-        self.iv = iv
-        self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
+        prev = xor(plaintext, ciphertext)
+        return prev ?? []
     }
 
-    mutating func next() -> Element? {
-        guard let ciphertext = inputGenerator.next(),
-            let decrypted = cipherOperation(block: self.prevCiphertext ?? iv)
-            else {
-                return nil
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8] {
+        guard let plaintext = cipherOperation(block: prev ?? iv) else {
+            return ciphertext
         }
-
-        let result = xor(decrypted, ciphertext)
-        self.prevCiphertext = ciphertext
+        let result = xor(plaintext, ciphertext)
+        self.prev = ciphertext
         return result
     }
-}
+}

+ 12 - 39
Sources/CryptoSwift/BlockMode/CTR.swift

@@ -8,64 +8,37 @@
 //  Counter (CTR)
 //
 
-struct CTRModeEncryptGenerator: BlockModeGenerator {
+struct CTRModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
 
+    let cipherOperation: CipherOperationOnBlock
     private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
-
-    private let cipherOperation: CipherOperationOnBlock
     private var counter: UInt = 0
 
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) {
+    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
     }
 
-    mutating func next() -> Element? {
-        guard let plaintext = inputGenerator.next() else {
-            return nil
-        }
-
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8] {
         let nonce = buildNonce(iv, counter: UInt64(counter))
         counter = counter + 1
-        if let encrypted = cipherOperation(block: nonce) {
-            return xor(plaintext, encrypted)
-        }
-
-        return nil
-    }
-}
-
-struct CTRModeDecryptGenerator: BlockModeGenerator {
-    typealias Element = Array<UInt8>
 
-    private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
-
-    private let cipherOperation: CipherOperationOnBlock
-    private var counter: UInt = 0
+        guard let ciphertext = cipherOperation(block: nonce) else {
+            return plaintext
+        }
 
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
-        self.iv = iv
-        self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
+        return xor(plaintext, ciphertext)
     }
 
-    mutating func next() -> Element? {
-        guard let ciphertext = inputGenerator.next() else {
-            return nil
-        }
-
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8] {
         let nonce = buildNonce(iv, counter: UInt64(counter))
         counter = counter + 1
 
-        if let decrypted = cipherOperation(block: nonce) {
-            return xor(decrypted, ciphertext)
+        guard let plaintext = cipherOperation(block: nonce) else {
+            return ciphertext
         }
-
-        return nil
+        return xor(plaintext, ciphertext)
     }
 }
 

+ 0 - 92
Sources/CryptoSwift/BlockMode/CipherBlockMode.swift

@@ -1,92 +0,0 @@
-//
-//  CipherBlockMode.swift
-//  CryptoSwift
-//
-//  Created by Marcin Krzyzanowski on 08/03/16.
-//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
-//
-
-public enum CipherBlockMode {
-    case ECB, CBC, PCBC, CFB, OFB, CTR
-
-    func encryptGenerator(iv: Array<UInt8>?, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) -> AnyGenerator<Array<UInt8>> {
-        switch (self) {
-        case CBC:
-            return AnyGenerator<Array<UInt8>>(CBCModeEncryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case CFB:
-            return AnyGenerator<Array<UInt8>>(CFBModeEncryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case OFB:
-            return AnyGenerator<Array<UInt8>>(OFBModeEncryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case CTR:
-            return AnyGenerator<Array<UInt8>>(CTRModeEncryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case PCBC:
-            return AnyGenerator<Array<UInt8>>(PCBCModeEncryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case ECB:
-            return AnyGenerator<Array<UInt8>>(ECBModeEncryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        }
-    }
-
-    func decryptGenerator(iv: Array<UInt8>?, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) -> AnyGenerator<Array<UInt8>> {
-        switch (self) {
-        case CBC:
-            return AnyGenerator<Array<UInt8>>(CBCModeDecryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case CFB:
-            return AnyGenerator<Array<UInt8>>(CFBModeDecryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case OFB:
-            return AnyGenerator<Array<UInt8>>(OFBModeDecryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case CTR:
-            return AnyGenerator<Array<UInt8>>(CTRModeDecryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case PCBC:
-            return AnyGenerator<Array<UInt8>>(PCBCModeDecryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        case ECB:
-            return AnyGenerator<Array<UInt8>>(ECBModeDecryptGenerator(iv: iv ?? [], cipherOperation: cipherOperation, inputGenerator: inputGenerator))
-        }
-    }
-
-    var options: BlockModeOptions {
-        switch (self) {
-        case .CBC:
-            return [.InitializationVectorRequired, .PaddingRequired]
-        case .CFB:
-            return .InitializationVectorRequired
-        case .CTR:
-            return .InitializationVectorRequired
-        case .ECB:
-            return .PaddingRequired
-        case .OFB:
-            return .InitializationVectorRequired
-        case .PCBC:
-            return [.InitializationVectorRequired, .PaddingRequired]
-        }
-    }
-
-    /**
-     Process input blocks with given block cipher mode. With fallback to plain mode.
-
-     - parameter blocks: cipher block size blocks
-     - parameter iv:     IV
-     - parameter cipher: single block encryption closure
-
-     - returns: encrypted bytes
-     */
-//    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
-//
-//        // if IV is not available, fallback to plain
-//        var finalBlockMode:CipherBlockMode = self
-//        if (iv == nil) {
-//            finalBlockMode = .ECB
-//        }
-//
-//        return try finalBlockMode.mode.encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
-//    }
-//
-//    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
-//        // if IV is not available, fallback to plain
-//        var finalBlockMode:CipherBlockMode = self
-//        if (iv == nil) {
-//            finalBlockMode = .ECB
-//        }
-//
-//        return try finalBlockMode.mode.decryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
-//    }
-}

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

@@ -1,5 +1,5 @@
 //
-//  CipherBlockMode.swift
+//  BlockMode.swift
 //  CryptoSwift
 //
 //  Created by Marcin Krzyzanowski on 27/12/14.
@@ -8,29 +8,22 @@
 //  Electronic codebook (ECB)
 //
 
-struct ECBModeEncryptGenerator: BlockModeGenerator {
+struct ECBModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
+    let cipherOperation: CipherOperationOnBlock
 
-    private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
-
-    private let cipherOperation: CipherOperationOnBlock
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) {
-        self.iv = iv
+    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock) {
         self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
     }
 
-    mutating func next() -> Element? {
-        guard let plaintext = inputGenerator.next(),
-              let encrypted = cipherOperation(block: plaintext)
-        else {
-            return nil
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8] {
+        guard let ciphertext = cipherOperation(block: plaintext) else {
+            return plaintext
         }
+        return ciphertext
+    }
 
-        return encrypted
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8] {
+        return encrypt(ciphertext)
     }
 }
-
-typealias ECBModeDecryptGenerator = ECBModeEncryptGenerator

+ 12 - 37
Sources/CryptoSwift/BlockMode/OFB.swift

@@ -8,57 +8,32 @@
 // Output Feedback (OFB)
 //
 
-struct OFBModeEncryptGenerator: BlockModeGenerator {
+struct OFBModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
 
+    let cipherOperation: CipherOperationOnBlock
     private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
+    private var prev: Element?
 
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) {
+    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
     }
 
-    mutating func next() -> Element? {
-        guard let plaintext = inputGenerator.next(),
-            let ciphertext = cipherOperation(block: prevCiphertext ?? iv)
-            else {
-                return nil
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8] {
+        guard let ciphertext = cipherOperation(block: prev ?? iv) else {
+            return plaintext
         }
-
-        self.prevCiphertext = ciphertext
+        prev = ciphertext
         return xor(plaintext, ciphertext)
     }
-}
-
-struct OFBModeDecryptGenerator: BlockModeGenerator {
-    typealias Element = Array<UInt8>
-
-    private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
-
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
-        self.iv = iv
-        self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
-    }
 
-    mutating func next() -> Element? {
-        guard let ciphertext = inputGenerator.next(),
-            let decrypted = cipherOperation(block: self.prevCiphertext ?? iv)
-            else {
-                return nil
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8] {
+        guard let decrypted = cipherOperation(block: prev ?? iv) else {
+            return ciphertext
         }
-
         let plaintext = xor(decrypted, ciphertext)
-        self.prevCiphertext = decrypted
+        self.prev = decrypted
         return plaintext
     }
 }

+ 15 - 40
Sources/CryptoSwift/BlockMode/PCBC.swift

@@ -8,57 +8,32 @@
 //  Propagating Cipher Block Chaining (PCBC)
 //
 
-struct PCBCModeEncryptGenerator: BlockModeGenerator {
+struct PCBCModeWorker: BlockModeWorker {
     typealias Element = Array<UInt8>
 
+    let cipherOperation: CipherOperationOnBlock
     private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
+    private var prev: Element?
 
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) {
+    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock) {
         self.iv = iv
         self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
     }
 
-    mutating func next() -> Element? {
-        guard let plaintext = inputGenerator.next(),
-              let encrypted = cipherOperation(block: xor(prevCiphertext ?? iv, plaintext))
-        else {
-            return nil
+    mutating func encrypt(plaintext: Array<UInt8>) -> [UInt8] {
+        guard let ciphertext = cipherOperation(block: xor(prev ?? iv, plaintext)) else {
+            return plaintext
         }
-
-        self.prevCiphertext = xor(plaintext, encrypted)
-        return encrypted
-    }
-}
-
-struct PCBCModeDecryptGenerator: BlockModeGenerator {
-    typealias Element = Array<UInt8>
-
-    private let iv: Element
-    private let inputGenerator: AnyGenerator<Element>
-
-    private let cipherOperation: CipherOperationOnBlock
-    private var prevCiphertext: Element?
-
-    init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
-        self.iv = iv
-        self.cipherOperation = cipherOperation
-        self.inputGenerator = inputGenerator
+        prev = xor(plaintext, ciphertext)
+        return ciphertext ?? []
     }
 
-    mutating func next() -> Element? {
-        guard let ciphertext = inputGenerator.next(),
-              let decrypted = cipherOperation(block: ciphertext)
-        else {
-            return nil
+    mutating func decrypt(ciphertext: Array<UInt8>) -> [UInt8] {
+        guard let plaintext = cipherOperation(block: ciphertext) else {
+            return ciphertext
         }
-
-        let plaintext = xor(prevCiphertext ?? iv, decrypted)
-        self.prevCiphertext = xor(plaintext, ciphertext)
-        return plaintext
+        let result = xor(prev ?? iv, plaintext)
+        self.prev = xor(plaintext, ciphertext)
+        return result
     }
 }

+ 1 - 1
Sources/CryptoSwift/BytesSequence.swift

@@ -18,7 +18,7 @@ struct BytesSequence: SequenceType {
             let end = min(self.chunkSize, self.data.count - offset)
             let result = self.data[offset..<offset + end]
             offset += result.count
-            return result.count > 0 ? result : nil
+            return !result.isEmpty ? result : nil
         }
     }
 }

+ 3 - 4
Sources/CryptoSwift/CRC.swift

@@ -74,16 +74,15 @@ final class CRC {
         0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
         0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040]
     
-    func crc32(message:[UInt8], seed: UInt32? = nil) -> UInt32 {
+    func crc32(message:[UInt8], seed: UInt32? = nil, reflect : Bool = true) -> UInt32 {
         var crc:UInt32 = seed != nil ? seed! : 0xffffffff
-        
         for chunk in BytesSequence(chunkSize: 256, data: message) {
             for b in chunk {
-                let idx = Int((crc ^ UInt32(b)) & 0xff)
+                let idx = Int((crc ^ UInt32(reflect ? b : reverseUInt8(b))) & 0xff)
                 crc = (crc >> 8) ^ CRC.table32[idx]
             }
         }
-        return crc ^ 0xffffffff
+        return (reflect ? crc : reverseUInt32(crc)) ^ 0xffffffff
     }
     
     func crc16(message:[UInt8], seed: UInt16? = nil) -> UInt16 {

+ 6 - 6
Sources/CryptoSwift/CSArrayType+Extensions.swift

@@ -47,20 +47,20 @@ public extension CSArrayType where Generator.Element == UInt8 {
         return Hash.sha512(cs_arrayValue()).calculate()
     }
     
-    public func crc32(seed: UInt32? = nil) -> [Generator.Element] {
-        return Hash.crc32(cs_arrayValue(), seed: seed).calculate()
+    public func crc32(seed: UInt32? = nil, reflect : Bool = true) -> [Generator.Element] {
+        return Hash.crc32(cs_arrayValue(), seed: seed, reflect: reflect).calculate()
     }
     
     public func crc16(seed: UInt16? = nil) -> [Generator.Element] {
         return Hash.crc16(cs_arrayValue(), seed: seed).calculate()
     }
     
-    public func encrypt(cipher: CipherProtocol) throws -> [Generator.Element] {
-        return try cipher.cipherEncrypt(cs_arrayValue())
+    public func encrypt(cipher: Cipher) throws -> [Generator.Element] {
+        return try cipher.encrypt(cs_arrayValue())
     }
 
-    public func decrypt(cipher: CipherProtocol) throws -> [Generator.Element] {
-        return try cipher.cipherDecrypt(cs_arrayValue())
+    public func decrypt(cipher: Cipher) throws -> [Generator.Element] {
+        return try cipher.decrypt(cs_arrayValue())
     }
     
     public func authenticate(authenticator: Authenticator) throws -> [Generator.Element] {

+ 12 - 20
Sources/CryptoSwift/ChaCha20.swift

@@ -34,18 +34,6 @@ final public class ChaCha20: BlockCipher {
         }
     }
     
-    public func encrypt(bytes:[UInt8]) throws -> [UInt8] {
-        guard context != nil else {
-            throw Error.MissingContext
-        }
-        
-        return try encryptBytes(bytes)
-    }
-    
-    public func decrypt(bytes:[UInt8]) throws -> [UInt8] {
-        return try encrypt(bytes)
-    }
-    
     private final func wordToByte(input:[UInt32] /* 64 */) -> [UInt8]? /* 16 */ {
         if (input.count != stateSize) {
             return nil;
@@ -174,15 +162,18 @@ final public class ChaCha20: BlockCipher {
     }
 }
 
-// MARK: - Cipher
+// MARK: Cipher
+extension ChaCha20: Cipher {
+    public func encrypt(bytes:[UInt8]) throws -> [UInt8] {
+        guard context != nil else {
+            throw Error.MissingContext
+        }
 
-extension ChaCha20: CipherProtocol {
-    public func cipherEncrypt(bytes:[UInt8]) throws -> [UInt8] {
-        return try self.encrypt(bytes)
+        return try encryptBytes(bytes)
     }
-    
-    public func cipherDecrypt(bytes: [UInt8]) throws -> [UInt8] {
-        return try self.decrypt(bytes)
+
+    public func decrypt(bytes:[UInt8]) throws -> [UInt8] {
+        return try encrypt(bytes)
     }
 }
 
@@ -196,5 +187,6 @@ private func wordNumber(bytes:ArraySlice<UInt8>) -> UInt32 {
         value = value | UInt32(bytes[j]) << (8 * i)
     }
 
-    return value}
+    return value
+}
 

+ 26 - 0
Sources/CryptoSwift/Cipher.swift

@@ -0,0 +1,26 @@
+//
+//  Cipher.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 29/05/16.
+//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
+//
+
+public enum CipherError: ErrorType {
+    case Encrypt
+    case Decrypt
+}
+
+public protocol Cipher {
+    /// Encrypt given bytes at once
+    ///
+    /// - parameter bytes: Plaintext data
+    /// - returns: Encrypted data
+    func encrypt(bytes: [UInt8]) throws -> [UInt8]
+
+    /// Decrypt given bytes at once
+    ///
+    /// - parameter bytes: Ciphertext data
+    /// - returns: Plaintext data
+    func decrypt(bytes: [UInt8]) throws -> [UInt8]
+}

+ 12 - 10
Sources/CryptoSwift/CipherProtocol.swift → Sources/CryptoSwift/Cryptors.swift

@@ -1,5 +1,5 @@
 //
-//  CipherProtocol.swift
+//  Cryptors.swift
 //  CryptoSwift
 //
 //  Created by Marcin Krzyzanowski on 30/08/14.
@@ -12,19 +12,21 @@
     import Darwin
 #endif
 
-public enum CipherError: ErrorType {
-    case Encrypt
-    case Decrypt
-}
+public protocol Cryptors {
+    associatedtype EncryptorType: UpdatableCryptor
+    associatedtype DecryptorType: UpdatableCryptor
+
+    /// Cryptor suitable for encryption
+    func makeEncryptor() -> EncryptorType
+
+    /// Cryptor suitable for decryption
+    func makeDecryptor() -> DecryptorType
 
-public protocol CipherProtocol {
-    func cipherEncrypt(bytes: [UInt8]) throws -> [UInt8]
-    func cipherDecrypt(bytes: [UInt8]) throws -> [UInt8]
-    
+    /// Generate array of random bytes. Helper function.
     static func randomIV(blockSize:Int) -> [UInt8]
 }
 
-extension CipherProtocol {
+extension Cryptors {
     static public func randomIV(blockSize:Int) -> [UInt8] {
         var randomIV:[UInt8] = [UInt8]();
         for _ in 0..<blockSize {

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

@@ -9,7 +9,7 @@
 import Foundation
 
 extension AES {
-    convenience public init(key:String, iv:String, blockMode:CipherBlockMode = .CBC, padding: Padding = PKCS7()) throws {
+    convenience public init(key:String, iv:String, blockMode:BlockMode = .CBC, padding: Padding = PKCS7()) throws {
         guard let kkey = key.bridge().dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.arrayOfBytes(), let iiv = iv.bridge().dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.arrayOfBytes() else {
             throw Error.InvalidKeyOrInitializationVector
         }

+ 6 - 6
Sources/CryptoSwift/Foundation/NSData+Extension.swift

@@ -60,8 +60,8 @@ extension NSData {
         return NSData.withBytes(result)
     }
 
-    public func crc32(seed: UInt32? = nil) -> NSData? {
-        let result = Hash.crc32(self.arrayOfBytes(), seed: seed).calculate()
+    public func crc32(seed: UInt32? = nil, reflect : Bool = true) -> NSData? {
+        let result = Hash.crc32(self.arrayOfBytes(), seed: seed, reflect: reflect).calculate()
         return NSData.withBytes(result)
     }
 
@@ -70,13 +70,13 @@ extension NSData {
         return NSData.withBytes(result)
     }
 
-    public func encrypt(cipher: CipherProtocol) throws -> NSData {
-        let encrypted = try cipher.cipherEncrypt(self.arrayOfBytes())
+    public func encrypt(cipher: Cipher) throws -> NSData {
+        let encrypted = try cipher.encrypt(self.arrayOfBytes())
         return NSData.withBytes(encrypted)
     }
 
-    public func decrypt(cipher: CipherProtocol) throws -> NSData {
-        let decrypted = try cipher.cipherDecrypt(self.arrayOfBytes())
+    public func decrypt(cipher: Cipher) throws -> NSData {
+        let decrypted = try cipher.decrypt(self.arrayOfBytes())
         return NSData.withBytes(decrypted)
     }
     

+ 2 - 2
Sources/CryptoSwift/Foundation/String+FoundationExtension.swift

@@ -11,7 +11,7 @@ import Foundation
 extension String {
 
     /// Return Base64 back to String
-    public func decryptBase64ToString(cipher: CipherProtocol) throws -> String {
+    public func decryptBase64ToString(cipher: Cipher) throws -> String {
         guard let decodedData = NSData(base64EncodedString: self, options: []) else {
             throw CipherError.Decrypt
         }
@@ -25,7 +25,7 @@ extension String {
         throw CipherError.Decrypt
     }
 
-    public func decryptBase64(cipher: CipherProtocol) throws -> [UInt8] {
+    public func decryptBase64(cipher: Cipher) throws -> [UInt8] {
         guard let decodedData = NSData(base64EncodedString: self, options: []) else {
             throw CipherError.Decrypt
         }

+ 2 - 2
Sources/CryptoSwift/Hash.swift

@@ -10,7 +10,7 @@ public enum Hash {
     case md5(Array<UInt8>)
     case sha1(Array<UInt8>)
     case sha224(Array<UInt8>), sha256(Array<UInt8>), sha384(Array<UInt8>), sha512(Array<UInt8>)
-    case crc32(Array<UInt8>, seed: UInt32?)
+    case crc32(Array<UInt8>, seed: UInt32?, reflect: Bool)
     case crc16(Array<UInt8>, seed: UInt16?)
     
     public func calculate() -> [UInt8] {
@@ -28,7 +28,7 @@ public enum Hash {
         case sha512(let bytes):
             return SHA2(bytes, variant: .sha512).calculate64()
         case crc32(let bytes):
-            return CRC().crc32(bytes.0, seed: bytes.seed).bytes()
+            return CRC().crc32(bytes.0, seed: bytes.seed, reflect: bytes.reflect).bytes()
         case crc16(let bytes):
             return UInt32(CRC().crc16(bytes.0, seed: bytes.seed)).bytes(2)
         }

+ 2 - 2
Sources/CryptoSwift/Info.plist

@@ -7,7 +7,7 @@
 	<key>CFBundleExecutable</key>
 	<string>${EXECUTABLE_NAME}</string>
 	<key>CFBundleIdentifier</key>
-	<string>com.hakore.${PRODUCT_NAME:rfc1034identifier}</string>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.4.1</string>
+	<string>0.5</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 82 - 0
Sources/CryptoSwift/PKCS5/PBKDF1.swift

@@ -0,0 +1,82 @@
+//
+//  PBKDF1.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 07/06/16.
+//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
+//
+
+public extension PKCS5 {
+
+    /// A key derivation function.
+    ///
+    /// PBKDF1 is recommended only for compatibility with existing
+    /// applications since the keys it produces may not be large enough for
+    /// some applications.
+    public struct PBKDF1 {
+
+        public enum Error: ErrorType {
+            case InvalidInput
+            case DerivedKeyTooLong
+        }
+
+        public enum Variant {
+            case md5, sha1
+
+            var size:Int {
+                switch (self) {
+                case .md5:
+                    return MD5.size
+                case .sha1:
+                    return SHA1.size
+                }
+            }
+
+            private func calculateHash(bytes bytes:[UInt8]) -> [UInt8]? {
+                switch (self) {
+                case .sha1:
+                    return Hash.sha1(bytes).calculate()
+                case .md5:
+                    return Hash.md5(bytes).calculate()
+                }
+            }
+        }
+
+        private let iterations: Int // c
+        private let variant: Variant
+        private let keyLength: Int
+        private let t1: [UInt8]
+
+        /// - parameters:
+        ///   - salt: salt, an eight-bytes
+        ///   - variant: hash variant
+        ///   - iterations: iteration count, a positive integer
+        ///   - keyLength: intended length of derived key
+        public init(password: [UInt8], salt: [UInt8], variant: Variant = .sha1, iterations: Int = 4096 /* c */, keyLength: Int? = nil /* dkLen */) throws {
+            precondition(iterations > 0)
+            precondition(salt.count == 8)
+
+            if (keyLength > variant.size) {
+                throw Error.DerivedKeyTooLong
+            }
+
+            guard let t1 = variant.calculateHash(bytes: password + salt) else {
+                throw Error.InvalidInput
+            }
+
+            self.iterations = iterations
+            self.variant = variant
+            self.keyLength = keyLength ?? variant.size
+            self.t1 = t1
+        }
+
+        /// Apply the underlying hash function Hash for c iterations
+        public func calculate() -> [UInt8] {
+            var t = t1
+            for _ in 2...self.iterations {
+                t = self.variant.calculateHash(bytes: t)!
+            }
+            return Array(t[0..<self.keyLength])
+        }
+    }
+}

+ 25 - 15
Sources/CryptoSwift/PKCS5/PBKDF2.swift

@@ -6,35 +6,45 @@
 //  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
 //
 
+#if os(Linux)
+    import Glibc
+#else
+    import Darwin
+#endif
+
 public extension PKCS5 {
-    // PBKDF2 - Password-Based Key Derivation Function 2. Key stretching technique.
-    //          DK = PBKDF2(PRF, Password, Salt, c, dkLen)
+    /// A key derivation function.
+    ///
+    /// PBKDF2 - Password-Based Key Derivation Function 2. Key stretching technique.
+    ///          DK = PBKDF2(PRF, Password, Salt, c, dkLen)
     public struct PBKDF2 {
 
         public enum Error: ErrorType {
             case InvalidInput
+            case DerivedKeyTooLong
         }
 
-        private let salt: [UInt8]
+        private let salt: [UInt8]   // S
         private let iterations: Int // c
-        private let numBlocks: UInt  // l
+        private let numBlocks: UInt // l
         private let prf: HMAC
 
-        public init(password: [UInt8], salt: [UInt8], iterations: Int = 4096 /* c */, keyLength: Int? = nil /* dkLen */ , hashVariant: HMAC.Variant = .sha256) throws {
-            guard let prf = HMAC(key: password, variant: hashVariant) where (iterations > 0) && (password.count > 0) && (salt.count > 0) else {
+        /// - parameters:
+        ///   - salt: salt
+        ///   - variant: hash variant
+        ///   - iterations: iteration count, a positive integer
+        ///   - keyLength: intended length of derived key
+        public init(password: [UInt8], salt: [UInt8], iterations: Int = 4096 /* c */, keyLength: Int? = nil /* dkLen */, variant: HMAC.Variant = .sha256) throws {
+            precondition(iterations > 0)
+            
+            guard let prf = HMAC(key: password, variant: variant) where iterations > 0 && !password.isEmpty && !salt.isEmpty else {
                 throw Error.InvalidInput
             }
 
-            let keyLengthFinal: Int
-            if let kl = keyLength {
-                keyLengthFinal = kl
-            } else {
-                keyLengthFinal = hashVariant.size
-            }
-
+            let keyLengthFinal = Double(keyLength ?? variant.size)
             let hLen = Double(prf.variant.size)
-            if keyLength > Int(((pow(2,32) as Double) - 1) * hLen) {
-                throw Error.InvalidInput
+            if keyLengthFinal > (pow(2,32) - 1) * hLen {
+                throw Error.DerivedKeyTooLong
             }
 
             self.salt = salt

+ 2 - 2
Sources/CryptoSwift/PKCS7.swift

@@ -37,8 +37,8 @@ public struct PKCS7: Padding {
     }
 
     public func remove(bytes: [UInt8], blockSize:Int?) -> [UInt8] {
-        assert(bytes.count > 0, "Need bytes to remove padding")
-        guard bytes.count > 0, let lastByte = bytes.last else {
+        assert(!bytes.isEmpty, "Need bytes to remove padding")
+        guard !bytes.isEmpty, let lastByte = bytes.last else {
             return bytes
         }
 

+ 7 - 18
Sources/CryptoSwift/Rabbit.swift

@@ -171,11 +171,13 @@ final public class Rabbit: BlockCipher {
         }
         return output8
     }
-    
-    // MARK: - Public
+}
+
+// MARK: Cipher
+extension Rabbit: Cipher {
     public func encrypt(bytes: [UInt8]) -> [UInt8] {
         setup()
-        
+
         var result = [UInt8](count: bytes.count, repeatedValue: 0)
         var output = nextOutput()
         var byteIdx = 0
@@ -185,7 +187,7 @@ final public class Rabbit: BlockCipher {
                 output = nextOutput()
                 outputIdx = 0
             }
-            
+
             result[byteIdx] = bytes[byteIdx] ^ output[outputIdx]
 
             byteIdx += 1
@@ -193,21 +195,8 @@ final public class Rabbit: BlockCipher {
         }
         return result
     }
-    
+
     public func decrypt(bytes: [UInt8]) -> [UInt8] {
         return encrypt(bytes)
     }
 }
-
-
-// MARK: - CipherType
-
-extension Rabbit: CipherProtocol {
-    public func cipherEncrypt(bytes:[UInt8]) -> [UInt8] {
-        return self.encrypt(bytes)
-    }
-    
-    public func cipherDecrypt(bytes: [UInt8]) -> [UInt8] {
-        return self.decrypt(bytes)
-    }
-}

+ 4 - 4
Sources/CryptoSwift/String+Extension.swift

@@ -33,19 +33,19 @@ extension String {
         return self.utf8.lazy.map({ $0 as UInt8 }).sha512().toHexString()
     }
 
-    public func crc32(seed: UInt32? = nil) -> String {
-        return self.utf8.lazy.map({ $0 as UInt8 }).crc32(seed).toHexString()
+    public func crc32(seed: UInt32? = nil, reflect : Bool = true) -> String {
+        return self.utf8.lazy.map({ $0 as UInt8 }).crc32(seed, reflect: reflect).toHexString()
     }
 
     public func crc16(seed: UInt16? = nil) -> String {
         return self.utf8.lazy.map({ $0 as UInt8 }).crc16(seed).toHexString()
     }
 
-    public func encrypt(cipher: CipherProtocol) throws -> [UInt8] {
+    public func encrypt(cipher: Cipher) throws -> [UInt8] {
         return try self.utf8.lazy.map({ $0 as UInt8 }).encrypt(cipher)
     }
 
-    public func decrypt(cipher: CipherProtocol) throws -> [UInt8] {
+    public func decrypt(cipher: Cipher) throws -> [UInt8] {
         return try self.utf8.lazy.map({ $0 as UInt8 }).decrypt(cipher)
     }
     

+ 55 - 0
Sources/CryptoSwift/UpdatableCryptor.swift

@@ -0,0 +1,55 @@
+//
+//  UpdatableCryptor.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 06/05/16.
+//  Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
+//
+
+public protocol UpdatableCryptor {
+    /// Encrypt/Decrypt given bytes in chunks.
+    ///
+    /// - parameter bytes: Bytes to process
+    /// - parameter isLast: (Optional) Given chunk is the last one. No more updates after this call.
+    /// - returns: Processed data or empty array.
+    mutating func update(withBytes bytes:[UInt8], isLast: Bool) throws -> [UInt8]
+
+    /// Encrypt/Decrypt given bytes in chunks.
+    ///
+    /// - parameter bytes: Bytes to process
+    /// - parameter isLast: (Optional) Given chunk is the last one. No more updates after this call.
+    /// - parameter output: Resulting data
+    /// - returns: Processed data or empty array.
+    mutating func update(withBytes bytes:[UInt8], isLast: Bool, output: (Array<UInt8>) -> Void) throws
+
+    /// Finish encryption/decryption. This may apply padding.
+    /// - parameter bytes: Bytes to process
+    /// - returns: Processed data.
+    mutating func finish(withBytes bytes:[UInt8]) throws -> [UInt8]
+
+    /// Finish encryption/decryption. This may apply padding.
+    /// - parameter bytes: Bytes to process
+    /// - parameter output: Resulting data
+    /// - returns: Processed data.
+    mutating func finish(withBytes bytes:[UInt8], output: (Array<UInt8>) -> Void) throws
+}
+
+extension UpdatableCryptor {
+    mutating public func update(withBytes bytes:[UInt8], isLast: Bool = false, output: (Array<UInt8>) -> Void) throws {
+        let processed = try self.update(withBytes: bytes, isLast: isLast)
+        if (!processed.isEmpty) {
+            output(processed)
+        }
+    }
+
+    mutating public func finish(withBytes bytes:[UInt8] = []) throws  -> [UInt8] {
+        return try self.update(withBytes: bytes, isLast: true)
+    }
+
+    mutating public func finish(withBytes bytes:[UInt8] = [], output: (Array<UInt8>) -> Void) throws {
+        let processed = try self.update(withBytes: bytes, isLast: true)
+        if (!processed.isEmpty) {
+            output(processed)
+        }
+    }
+}

+ 16 - 2
Sources/CryptoSwift/Utils.swift

@@ -34,8 +34,22 @@ func rotateRight(x:UInt64, n:UInt64) -> UInt64 {
     return ((x >> n) | (x << (64 - n)))
 }
 
-func reverseBytes(value: UInt32) -> UInt32 {
-    return ((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8) | ((value & 0x00FF0000) >> 8)  | ((value & 0xFF000000) >> 24);
+func reverseUInt8(uint8 : UInt8) -> UInt8 {
+    var v : UInt8 = uint8
+    v = (v & 0xF0) >> 4 | (v & 0x0F) << 4
+    v = (v & 0xCC) >> 2 | (v & 0x33) << 2
+    v = (v & 0xAA) >> 1 | (v & 0x55) << 1
+    return v
+}
+
+func reverseUInt32(uint32 : UInt32) -> UInt32 {
+    var v = uint32
+    v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1)
+    v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2)
+    v = ((v >> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4)
+    v = ((v >> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8)
+    v = ((v >> 16) & 0xffff) | ((v & 0xffff) << 16)
+    return v
 }
 
 func toUInt32Array(slice: ArraySlice<UInt8>) -> Array<UInt32> {

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels