Quellcode durchsuchen

Work with slices by default. Reuse Int(bytes:) for Collection.toUInt...

Marcin Krzyżanowski vor 8 Jahren
Ursprung
Commit
e3503c0174

+ 1 - 1
CryptoSwift.xcodeproj/project.pbxproj

@@ -360,10 +360,10 @@
 				75EC52701EE8B6CA0048EB3B /* SHA2.swift */,
 				75EC52711EE8B6CA0048EB3B /* SHA3.swift */,
 				75EC52721EE8B6CA0048EB3B /* String+Extension.swift */,
+				75EC52761EE8B6CA0048EB3B /* UInt8+Extension.swift */,
 				75EC52731EE8B6CA0048EB3B /* UInt16+Extension.swift */,
 				75EC52741EE8B6CA0048EB3B /* UInt32+Extension.swift */,
 				75EC52751EE8B6CA0048EB3B /* UInt64+Extension.swift */,
-				75EC52761EE8B6CA0048EB3B /* UInt8+Extension.swift */,
 				75EC52771EE8B6CA0048EB3B /* Updatable.swift */,
 				75EC52781EE8B6CA0048EB3B /* Utils.swift */,
 				75EC52791EE8B6CA0048EB3B /* ZeroPadding.swift */,

+ 3 - 3
Sources/CryptoSwift/AES.swift

@@ -146,7 +146,7 @@ public final class AES: BlockCipher {
 // MARK: Private
 private extension AES {
 
-    func encrypt(block: Array<UInt8>) -> Array<UInt8>? {
+    func encrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
 
         if blockMode.options.contains(.paddingRequired) && block.count != AES.blockSize {
             return Array(block)
@@ -240,10 +240,10 @@ private extension AES {
         return encrypted
     }
 
-    func decrypt(block: Array<UInt8>) -> Array<UInt8>? {
+    func decrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
 
         if blockMode.options.contains(.paddingRequired) && block.count != AES.blockSize {
-            return block
+            return Array(block)
         }
 
         let rounds = variant.Nr

+ 1 - 1
Sources/CryptoSwift/BlockMode/BlockMode.swift

@@ -14,7 +14,7 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
-typealias CipherOperationOnBlock = (_ block: Array<UInt8>) -> Array<UInt8>?
+typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
 
 public enum BlockMode {
     case ECB, CBC, PCBC, CFB, OFB, CTR

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

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

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

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

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

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

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

@@ -26,7 +26,7 @@ struct ECBModeWorker: BlockModeWorker {
     }
 
     mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
-        guard let ciphertext = cipherOperation(Array(plaintext)) else {
+        guard let ciphertext = cipherOperation(plaintext) else {
             return Array(plaintext)
         }
         return ciphertext

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

@@ -18,11 +18,9 @@
 //
 
 struct OFBModeWorker: BlockModeWorker {
-    typealias Element = Array<UInt8>
-
     let cipherOperation: CipherOperationOnBlock
-    private let iv: Element
-    private var prev: Element?
+    private let iv: Array<UInt8>
+    private var prev: ArraySlice<UInt8>?
 
     init(iv: Array<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
         self.iv = iv
@@ -30,19 +28,19 @@ struct OFBModeWorker: BlockModeWorker {
     }
 
     mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
-        guard let ciphertext = cipherOperation(prev ?? iv) else {
+        guard let ciphertext = cipherOperation(prev ?? iv.slice) else {
             return Array(plaintext)
         }
-        prev = ciphertext
+        prev = ciphertext.slice
         return xor(plaintext, ciphertext)
     }
 
     mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
-        guard let decrypted = cipherOperation(prev ?? iv) else {
+        guard let decrypted = cipherOperation(prev ?? iv.slice) else {
             return Array(ciphertext)
         }
         let plaintext = xor(decrypted, ciphertext)
-        prev = decrypted
+        prev = decrypted.slice
         return plaintext
     }
 }

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

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

+ 6 - 6
Sources/CryptoSwift/Blowfish.swift

@@ -384,11 +384,11 @@ public final class Blowfish {
         }
     }
 
-    fileprivate func encrypt(block: Array<UInt8>) -> Array<UInt8>? {
+    fileprivate func encrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
         var result = Array<UInt8>()
 
-        var l = UInt32(bytes: block[0..<4])
-        var r = UInt32(bytes: block[4..<8])
+        var l = UInt32(bytes: block[block.startIndex + 0..<block.startIndex.advanced(by: 4)])
+        var r = UInt32(bytes: block[block.startIndex + 4..<block.startIndex.advanced(by: 8)])
 
         encryptBlowfishBlock(l: &l, r: &r)
 
@@ -413,11 +413,11 @@ public final class Blowfish {
         return result
     }
 
-    fileprivate func decrypt(block: Array<UInt8>) -> Array<UInt8>? {
+    fileprivate func decrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
         var result = Array<UInt8>()
 
-        var l = UInt32(bytes: block[0..<4])
-        var r = UInt32(bytes: block[4..<8])
+        var l = UInt32(bytes: block[block.startIndex + 0..<block.startIndex.advanced(by: 4)])
+        var r = UInt32(bytes: block[block.startIndex + 4..<block.startIndex.advanced(by: 8)])
 
         decryptBlowfishBlock(l: &l, r: &r)
 

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

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

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

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

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

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

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

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

+ 6 - 1
Sources/CryptoSwift/Utils.swift

@@ -73,11 +73,16 @@ func xor(_ a: ArraySlice<UInt8>, _ b: Array<UInt8>) -> Array<UInt8> {
 }
 
 func xor(_ a: ArraySlice<UInt8>, _ b: ArraySlice<UInt8>) -> Array<UInt8> {
+    return Array(xor(a, b) as ArraySlice<UInt8>)
+}
+
+func xor(_ a: ArraySlice<UInt8>, _ b: ArraySlice<UInt8>) -> ArraySlice<UInt8> {
     var xored = Array<UInt8>(repeating: 0, count: min(a.count, b.count))
     for i in 0..<xored.count {
         xored[xored.startIndex.advanced(by: i)] = a[a.startIndex.advanced(by: i)] ^ b[b.startIndex.advanced(by: i)]
     }
-    return xored
+    // don't want to modify slice in place
+    return xored.slice
 }
 
 /**

+ 3 - 3
Tests/CryptoSwiftTests/ExtensionsTest.swift

@@ -25,12 +25,12 @@ final class ExtensionsTest: XCTestCase {
     }
 
     func testToUInt32Array() {
-        let chunk: ArraySlice<UInt8> = [1, 1, 1, 7, 2, 3, 4, 5]
+        let chunk: ArraySlice<UInt8> = [0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1]
         let result = chunk.toUInt32Array()
 
         XCTAssert(result.count == 2, "Invalid conversion")
-        XCTAssert(result[0] == 117_506_305, "Invalid conversion")
-        XCTAssert(result[1] == 84_148_994, "Invalid conversion")
+        XCTAssertEqual(result[0], 0x5060708)
+        XCTAssertEqual(result[1], 0x1020304)
     }
 
     func testDataInit() {