瀏覽代碼

Retire BytesSequence in favor of BatchedCollection.

Marcin Krzyżanowski 8 年之前
父節點
當前提交
00654e0558

+ 4 - 4
CryptoSwift.xcodeproj/project.pbxproj

@@ -35,7 +35,6 @@
 		757BC93C1C1CA5790093AAA9 /* AES.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC91A1C1CA5790093AAA9 /* AES.swift */; };
 		757BC9401C1CA5790093AAA9 /* Array+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC91B1C1CA5790093AAA9 /* Array+Extension.swift */; };
 		757BC9481C1CA5790093AAA9 /* Authenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC91D1C1CA5790093AAA9 /* Authenticator.swift */; };
-		757BC9501C1CA5790093AAA9 /* BytesSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC91F1C1CA5790093AAA9 /* BytesSequence.swift */; };
 		757BC9541C1CA5790093AAA9 /* ChaCha20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9201C1CA5790093AAA9 /* ChaCha20.swift */; };
 		757BC9601C1CA5790093AAA9 /* Checksum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9231C1CA5790093AAA9 /* Checksum.swift */; };
 		757BC9681C1CA5790093AAA9 /* CSArrayType+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757BC9251C1CA5790093AAA9 /* CSArrayType+Extensions.swift */; };
@@ -68,6 +67,7 @@
 		758A94291A65C67400E46135 /* HMACTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758A94271A65C59200E46135 /* HMACTests.swift */; };
 		758F58F11C8FB6E20054C377 /* OFB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758F58F01C8FB6E20054C377 /* OFB.swift */; };
 		7595ADE81D86A29A0099EBEF /* HMAC+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7595ADE71D86A29A0099EBEF /* HMAC+Foundation.swift */; };
+		759FF2A81E226B7D00BC4EE1 /* BatchedCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759FF2A71E226B7D00BC4EE1 /* BatchedCollection.swift */; };
 		75B601EB197D6A6C0009B53D /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 754BE45519693E190098E6F3 /* CryptoSwift.framework */; };
 		75C2E7681D55EFA1003D2BCA /* UInt16+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75C2E7671D55EFA1003D2BCA /* UInt16+Extension.swift */; };
 		75C2E76D1D55F097003D2BCA /* Access.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75C2E76C1D55F097003D2BCA /* Access.swift */; };
@@ -186,7 +186,6 @@
 		757BC91A1C1CA5790093AAA9 /* AES.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AES.swift; path = Sources/CryptoSwift/AES.swift; sourceTree = SOURCE_ROOT; };
 		757BC91B1C1CA5790093AAA9 /* Array+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Array+Extension.swift"; path = "Sources/CryptoSwift/Array+Extension.swift"; sourceTree = SOURCE_ROOT; };
 		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; };
 		757BC9231C1CA5790093AAA9 /* Checksum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Checksum.swift; path = Sources/CryptoSwift/Checksum.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; };
@@ -219,6 +218,7 @@
 		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; };
 		7595ADE71D86A29A0099EBEF /* HMAC+Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HMAC+Foundation.swift"; sourceTree = "<group>"; };
+		759FF2A71E226B7D00BC4EE1 /* BatchedCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BatchedCollection.swift; path = Sources/CryptoSwift/BatchedCollection.swift; sourceTree = SOURCE_ROOT; };
 		75C2E7671D55EFA1003D2BCA /* UInt16+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UInt16+Extension.swift"; path = "Sources/CryptoSwift/UInt16+Extension.swift"; sourceTree = SOURCE_ROOT; };
 		75C2E76C1D55F097003D2BCA /* Access.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Access.swift; sourceTree = "<group>"; };
 		75CB93241C8F5EC10087740D /* CBC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CBC.swift; path = Sources/CryptoSwift/BlockMode/CBC.swift; sourceTree = SOURCE_ROOT; };
@@ -301,7 +301,7 @@
 				757BC91D1C1CA5790093AAA9 /* Authenticator.swift */,
 				80545D121CA9FECD00474A99 /* Bit.swift */,
 				757F440D1CC1822A002B1F85 /* SecureBytes.swift */,
-				757BC91F1C1CA5790093AAA9 /* BytesSequence.swift */,
+				759FF2A71E226B7D00BC4EE1 /* BatchedCollection.swift */,
 				753B32FE1DAB711200D06422 /* RandomBytesSequence.swift */,
 				755655C61D080E3F00F004E7 /* Cryptors.swift */,
 				75DB81A71CDC06B100ED181A /* Updatable.swift */,
@@ -582,6 +582,7 @@
 				757BC9701C1CA5790093AAA9 /* Digest.swift in Sources */,
 				75CB93351C8F5FCE0087740D /* PCBC.swift in Sources */,
 				75CB93301C8F5F580087740D /* BlockMode.swift in Sources */,
+				759FF2A81E226B7D00BC4EE1 /* BatchedCollection.swift in Sources */,
 				757BC9121C1CA56A0093AAA9 /* String+FoundationExtension.swift in Sources */,
 				757BC9B41C1CA5790093AAA9 /* UInt8+Extension.swift in Sources */,
 				757BC9401C1CA5790093AAA9 /* Array+Extension.swift in Sources */,
@@ -598,7 +599,6 @@
 				758F58F11C8FB6E20054C377 /* OFB.swift in Sources */,
 				75CB934E1C8F609D0087740D /* BlockModeOptions.swift in Sources */,
 				757BC9801C1CA5790093AAA9 /* IntegerConvertible.swift in Sources */,
-				757BC9501C1CA5790093AAA9 /* BytesSequence.swift in Sources */,
 				757BC9881C1CA5790093AAA9 /* MD5.swift in Sources */,
 				757BC9A81C1CA5790093AAA9 /* SHA1.swift in Sources */,
 				75DB81A81CDC06B100ED181A /* Updatable.swift in Sources */,

+ 22 - 0
CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/7797B693-C86A-4026-B2CE-05813EFA26F4.plist

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

+ 8 - 2
Sources/CryptoSwift/AES.swift

@@ -444,6 +444,12 @@ extension AES {
             var processedBytes = 0
             var encrypted = Array<UInt8>()
             encrypted.reserveCapacity(self.accumulated.count)
+//            for chunk in self.accumulated.batched(by: AES.blockSize) {
+//                if (isLast || (self.accumulated.count - processedBytes) >= AES.blockSize) {
+//                    encrypted += worker.encrypt(Array(chunk))
+//                    processedBytes += chunk.count
+//                }
+//            }
             for chunk in self.accumulated.chunks(size: AES.blockSize) {
                 if (isLast || (self.accumulated.count - processedBytes) >= AES.blockSize) {
                     encrypted += worker.encrypt(chunk)
@@ -497,9 +503,9 @@ extension AES {
             var processedBytes = 0
             var plaintext = Array<UInt8>()
             plaintext.reserveCapacity(self.accumulated.count)
-            for chunk in self.accumulated.chunks(size: AES.blockSize) {
+            for chunk in self.accumulated.batched(by: AES.blockSize) {
                 if (isLast || (self.accumulated.count - processedBytes) >= AES.blockSize) {
-                    plaintext += self.worker.decrypt(chunk)
+                    plaintext += self.worker.decrypt(Array(chunk))
 
                     // remove "offset" from the beginning of first chunk
                     if self.offsetToRemove > 0 {

+ 52 - 0
Sources/CryptoSwift/BatchedCollection.swift

@@ -0,0 +1,52 @@
+//
+//  BatchedCollection.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 08/01/2017.
+//  Copyright © 2017 Marcin Krzyzanowski. All rights reserved.
+//
+
+struct BatchedCollectionIndex<Base: Collection> {
+    let range: Range<Base.Index>
+}
+
+extension BatchedCollectionIndex: Comparable {
+    static func ==<Base: Collection>(lhs: BatchedCollectionIndex<Base>, rhs: BatchedCollectionIndex<Base>) -> Bool {
+        return lhs.range.lowerBound == rhs.range.lowerBound
+    }
+    static func < <Base: Collection>(lhs: BatchedCollectionIndex<Base>, rhs: BatchedCollectionIndex<Base>) -> Bool {
+        return lhs.range.lowerBound < rhs.range.lowerBound
+    }
+}
+
+protocol BatchedCollectionType: Collection {
+    associatedtype Base: Collection
+}
+
+struct BatchedCollection<Base: Collection>: Collection {
+    let base: Base
+    let size: Base.IndexDistance
+    typealias Index = BatchedCollectionIndex<Base>
+    private func nextBreak(after idx: Base.Index) -> Base.Index {
+        return base.index(idx, offsetBy: size, limitedBy: base.endIndex)
+            ?? base.endIndex
+    }
+    var startIndex: Index {
+        return Index(range: base.startIndex..<nextBreak(after: base.startIndex))
+    }
+    var endIndex: Index {
+        return Index(range: base.endIndex..<base.endIndex)
+    }
+    func index(after idx: Index) -> Index {
+        return Index(range: idx.range.upperBound..<nextBreak(after: idx.range.upperBound))
+    }
+    subscript(idx: Index) -> Base.SubSequence {
+        return base[idx.range]
+    }
+}
+
+extension Collection {
+    func batched(by size: IndexDistance) -> BatchedCollection<Self> {
+        return BatchedCollection(base: self, size: size)
+    }
+}

+ 3 - 3
Sources/CryptoSwift/Blowfish.swift

@@ -467,8 +467,8 @@ extension Blowfish: Cipher {
         var out = Array<UInt8>()
         out.reserveCapacity(bytes.count)
 
-        for chunk in BytesSequence(chunkSize: Blowfish.blockSize, data: bytes) {
-            out += self.encryptWorker.encrypt(Array(chunk)) //FIXME: copying here is innefective
+        for chunk in bytes.batched(by: Blowfish.blockSize) {
+            out += self.encryptWorker.encrypt(Array(chunk))
         }
 
         if blockMode.options.contains(.PaddingRequired) && (out.count % Blowfish.blockSize != 0) {
@@ -492,7 +492,7 @@ extension Blowfish: Cipher {
         var out = Array<UInt8>()
         out.reserveCapacity(bytes.count)
 
-        for chunk in BytesSequence(chunkSize: Blowfish.blockSize, data: Array(bytes)) {
+        for chunk in Array(bytes).batched(by: Blowfish.blockSize) {
             out += self.decryptWorker.decrypt(Array(chunk)) //FIXME: copying here is innefective
         }
 

+ 0 - 45
Sources/CryptoSwift/BytesSequence.swift

@@ -1,45 +0,0 @@
-//
-//  BytesSequence.swift
-//  CryptoSwift
-//
-//  Created by Marcin Krzyzanowski on 26/09/15.
-//  Copyright © 2015 Marcin Krzyzanowski. All rights reserved.
-//
-
-/// Generic version of BytesSequence is slower, therefore specialized version is in use
-///
-// struct BytesSequence<D: RandomAccessCollection>: Sequence where D.Iterator.Element == UInt8, D.IndexDistance == Int, D.SubSequence.IndexDistance == Int, D.Index == Int {
-//    let chunkSize: D.IndexDistance
-//    let data: D
-//
-//    func makeIterator() -> AnyIterator<D.SubSequence> {
-//        var offset = data.startIndex
-//        return AnyIterator {
-//            let end = Swift.min(self.chunkSize, self.data.count - offset)
-//            let result = self.data[offset..<offset + end]
-//            offset = offset.advanced(by: result.count)
-//            if !result.isEmpty {
-//                return result
-//            }
-//            return nil
-//        }
-//    }
-// }
-
-struct BytesSequence: Sequence {
-    let chunkSize: Array<UInt8>.IndexDistance
-    let data: Array<UInt8>
-
-    func makeIterator() -> AnyIterator<ArraySlice<UInt8>> {
-        var offset = data.startIndex
-        return AnyIterator {
-            let end = Swift.min(self.chunkSize, self.data.count &- offset)
-            let result = self.data[offset ..< offset &+ end]
-            offset = offset.advanced(by: result.count)
-            if !result.isEmpty {
-                return result
-            }
-            return nil
-        }
-    }
-}

+ 2 - 2
Sources/CryptoSwift/ChaCha20.swift

@@ -260,7 +260,7 @@ extension ChaCha20 {
 
             var encrypted = Array<UInt8>()
             encrypted.reserveCapacity(self.accumulated.count)
-            for chunk in BytesSequence(chunkSize: ChaCha20.blockSize, data: self.accumulated) {
+            for chunk in self.accumulated.batched(by: ChaCha20.blockSize) {
                 if (isLast || self.accumulated.count >= ChaCha20.blockSize) {
                     encrypted += try chacha.encrypt(chunk)
                     self.accumulated.removeFirst(chunk.count) //TODO: improve performance
@@ -297,7 +297,7 @@ extension ChaCha20 {
 
             var plaintext = Array<UInt8>()
             plaintext.reserveCapacity(self.accumulated.count)
-            for chunk in BytesSequence(chunkSize: ChaCha20.blockSize, data: self.accumulated) {
+            for chunk in self.accumulated.batched(by: ChaCha20.blockSize) {
                 if (isLast || self.accumulated.count >= ChaCha20.blockSize) {
                     plaintext += try chacha.decrypt(chunk)
 

+ 2 - 2
Sources/CryptoSwift/Checksum.swift

@@ -76,7 +76,7 @@ public final class Checksum {
 
     func crc32(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
         var crc: UInt32 = seed != nil ? seed! : 0xffffffff
-        for chunk in BytesSequence(chunkSize: 256, data: message) {
+        for chunk in message.batched(by: 256) {
             for b in chunk {
                 let idx = Int((crc ^ UInt32(reflect ? b : reversed(b))) & 0xff)
                 crc = (crc >> 8) ^ Checksum.table32[idx]
@@ -87,7 +87,7 @@ public final class Checksum {
 
     func crc16(_ message: Array<UInt8>, seed: UInt16? = nil) -> UInt16 {
         var crc: UInt16 = seed != nil ? seed! : 0x0000
-        for chunk in BytesSequence(chunkSize: 256, data: message) {
+        for chunk in message.batched(by: 256) {
             for b in chunk {
                 crc = (crc >> 8) ^ Checksum.table16[Int((crc ^ UInt16(b)) & 0xFF)]
             }

+ 1 - 1
Sources/CryptoSwift/MD5.swift

@@ -121,7 +121,7 @@ extension MD5: Updatable {
         }
 
         var processedBytes = 0
-        for chunk in BytesSequence(chunkSize: MD5.blockSize, data: self.accumulated) {
+        for chunk in self.accumulated.batched(by: MD5.blockSize) {
             if (isLast || (self.accumulated.count - processedBytes) >= MD5.blockSize) {
                 self.process(block: chunk, currentHash: &self.accumulatedHash)
                 processedBytes += chunk.count

+ 1 - 1
Sources/CryptoSwift/SHA1.swift

@@ -107,7 +107,7 @@ extension SHA1: Updatable {
         }
 
         var processedBytes = 0
-        for chunk in BytesSequence(chunkSize: SHA1.blockSize, data: self.accumulated) {
+        for chunk in self.accumulated.batched(by: SHA1.blockSize) {
             if (isLast || (self.accumulated.count - processedBytes) >= SHA1.blockSize) {
                 self.process(block: chunk, currentHash: &self.accumulatedHash)
                 processedBytes += chunk.count

+ 1 - 1
Sources/CryptoSwift/SHA2.swift

@@ -273,7 +273,7 @@ extension SHA2: Updatable {
         }
 
         var processedBytes = 0
-        for chunk in BytesSequence(chunkSize: self.blockSize, data: self.accumulated) {
+        for chunk in self.accumulated.batched(by: self.blockSize) {
             if (isLast || (self.accumulated.count - processedBytes) >= self.blockSize) {
                 switch self.variant {
                 case .sha224, .sha256:

+ 1 - 1
Sources/CryptoSwift/SHA3.swift

@@ -257,7 +257,7 @@ extension SHA3: Updatable {
         }
 
         var processedBytes = 0
-        for chunk in BytesSequence(chunkSize: self.blockSize, data: self.accumulated) {
+        for chunk in self.accumulated.batched(by: self.blockSize) {
             if (isLast || (self.accumulated.count - processedBytes) >= self.blockSize) {
                 self.process(block: chunk.toUInt64Array(), currentHash: &self.accumulatedHash)
                 processedBytes += chunk.count