Jelajahi Sumber

willDecryptLast value depends on the context

Marcin Krzyzanowski 6 tahun lalu
induk
melakukan
ea602f6f75

+ 1 - 1
CryptoSwift.xcodeproj/project.pbxproj

@@ -600,8 +600,8 @@
 				754310432050111A003FB1DF /* CompactMap.swift */,
 				75B3ED76210F9DF7005D4ADA /* BlockDecryptor.swift */,
 				75B3ED78210FA016005D4ADA /* BlockEncryptor.swift */,
-				756A64C52111083B00BE8805 /* StreamEncryptor.swift */,
 				753674062175D012003E32A6 /* StreamDecryptor.swift */,
+				756A64C52111083B00BE8805 /* StreamEncryptor.swift */,
 			);
 			path = CryptoSwift;
 			sourceTree = "<group>";

+ 1 - 1
Sources/CryptoSwift/BlockDecryptor.swift

@@ -48,7 +48,7 @@ public class BlockDecryptor: Cryptor, Updatable {
             if isLast || (accumulatedWithoutSuffix.count - processedBytesCount) >= blockSize {
 
                 if isLast, var finalizingWorker = worker as? FinalizingModeWorker {
-                    chunk = try finalizingWorker.willDecryptLast(block: chunk + accumulated.suffix(worker.additionalBufferSize)) // tag size
+                    chunk = try finalizingWorker.willDecryptLast(bytes: chunk + accumulated.suffix(worker.additionalBufferSize)) // tag size
                 }
 
                 if !chunk.isEmpty {

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

@@ -162,7 +162,7 @@ class CCMModeWorker: StreamModeWorker, SeekableModeWorker, CounterModeWorker, Fi
         return Array(ciphertext) + (xor(tag, S0) as Array<UInt8>)
     }
 
-    func willDecryptLast(block ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+    func willDecryptLast(bytes ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
         return ciphertext
     }
 

+ 3 - 2
Sources/CryptoSwift/BlockMode/CipherModeWorker.swift

@@ -46,8 +46,9 @@ public protocol FinalizingModeWorker: CipherModeWorker {
     // Any final calculations, eg. calculate tag
     // Called after the last block is encrypted
     mutating func finalize(encrypt ciphertext: ArraySlice<UInt8>) throws -> Array<UInt8>
-    // Called before decryption, hence input is ciphertext
-    mutating func willDecryptLast(block ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8>
+    // Called before decryption, hence input is ciphertext.
+    // ciphertext is either a last block, or a tag (for stream workers)
+    mutating func willDecryptLast(bytes ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8>
     // Called after decryption, hence input is ciphertext
     mutating func didDecryptLast(block plaintext: ArraySlice<UInt8>) throws -> Array<UInt8>
 }

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

@@ -186,7 +186,7 @@ final class GCMModeWorker: BlockModeWorker, FinalizingModeWorker {
     // The authenticated decryption operation has five inputs: K, IV , C, A, and T. It has only a single
     // output, either the plaintext value P or a special symbol FAIL that indicates that the inputs are not
     // authentic.
-    func willDecryptLast(block ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+    func willDecryptLast(bytes ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
         // Validate tag
         switch mode {
         case .combined:

+ 5 - 20
Sources/CryptoSwift/StreamDecryptor.swift

@@ -16,8 +16,6 @@ final class StreamDecryptor: Cryptor, Updatable {
     private let blockSize: Int
     private var worker: CipherModeWorker
     private let padding: Padding
-    // Accumulated bytes. Not all processed bytes.
-    private var accumulated = Array<UInt8>(reserveCapacity: 16)
 
     private var lastBlockRemainder = 0
 
@@ -29,22 +27,11 @@ final class StreamDecryptor: Cryptor, Updatable {
 
     // MARK: Updatable
     public func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool) throws -> Array<UInt8> {
-        accumulated = Array(bytes)
-        
-        var plaintext = Array<UInt8>(reserveCapacity: bytes.count)
-        for var chunk in accumulated.batched(by: blockSize) {
-
-            if isLast, var finalizingWorker = worker as? FinalizingModeWorker {
-                chunk = try finalizingWorker.willDecryptLast(block: chunk + accumulated.suffix(worker.additionalBufferSize)) // tag size
-            }
-
-            if !chunk.isEmpty {
-                plaintext += worker.decrypt(block: chunk)
-            }
+        let accumulated = Array(bytes)
 
-            if var finalizingWorker = worker as? FinalizingModeWorker, isLast == true {
-                plaintext = try finalizingWorker.didDecryptLast(block: plaintext.slice)
-            }
+        var plaintext = Array<UInt8>(reserveCapacity: bytes.count)
+        for chunk in accumulated.batched(by: blockSize) {
+            plaintext += worker.encrypt(block: chunk)
         }
 
         // omit unecessary calculation if not needed
@@ -54,7 +41,7 @@ final class StreamDecryptor: Cryptor, Updatable {
 
         if isLast {
             // CTR doesn't need padding. Really. Add padding to the last block if really want. but... don't.
-            plaintext = padding.remove(from: plaintext, blockSize: blockSize)
+            plaintext = padding.remove(from: plaintext, blockSize: blockSize - lastBlockRemainder)
         }
 
         if var finalizingWorker = worker as? FinalizingModeWorker, isLast == true {
@@ -71,7 +58,5 @@ final class StreamDecryptor: Cryptor, Updatable {
 
         try worker.seek(to: position)
         self.worker = worker
-
-        accumulated = []
     }
 }