소스 검색

protocol BlockMode for cipher block modes

Marcin Krzyżanowski 10 년 전
부모
커밋
4e409b5117
3개의 변경된 파일63개의 추가작업 그리고 47개의 파일을 삭제
  1. 4 4
      CryptoSwift/AES.swift
  2. 46 40
      CryptoSwift/CipherBlockMode.swift
  3. 13 3
      CryptoSwift/Playground/CryptoPlayground.playground/section-1.swift

+ 4 - 4
CryptoSwift/AES.swift

@@ -113,7 +113,7 @@ public class AES {
             return nil
         }
         
-        if (blockMode.requireIV() && iv.length != AES.blockSizeBytes()) {
+        if (blockMode.needIV && iv.length != AES.blockSizeBytes()) {
             assert(false, "Block size and Initialization Vector must be the same length!")
             return nil
         }
@@ -149,7 +149,7 @@ public class AES {
         }
         
         let blocks = finalBytes.chunks(AES.blockSizeBytes())
-        return blockMode.encryptBlocks(blocks, iv: self.iv?.bytes(), cipher: encryptBlock)
+        return blockMode.encryptBlocks(blocks, iv: self.iv?.bytes(), cipherOperation: encryptBlock)
     }
     
     private func encryptBlock(block:[UInt8]) -> [UInt8]? {
@@ -196,9 +196,9 @@ public class AES {
         var out:[UInt8]?
         if (blockMode == .CFB) {
             // CFB uses encryptBlock to decrypt
-            out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipher: encryptBlock)
+            out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipherOperation: encryptBlock)
         } else {
-            out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipher: decryptBlock)
+            out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipherOperation: decryptBlock)
         }
         
         if let out = out, let padding = padding {

+ 46 - 40
CryptoSwift/CipherBlockMode.swift

@@ -8,20 +8,32 @@
 
 import Foundation
 
-typealias CipherWorker = (block: [UInt8]) -> [UInt8]?
+// I have no better name for that
+typealias CipherOperationOnBlock = (block: [UInt8]) -> [UInt8]?
+
+private protocol BlockMode {
+    var needIV:Bool { get }
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]?
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]?
+}
 
 public enum CipherBlockMode {
     case ECB, CBC, CFB
     
-    func requireIV() -> Bool {
+    private var mode:BlockMode {
         switch (self) {
-        case CBC, CFB:
-            return true
-        default:
-            return false
+        case CBC:
+            return CBCMode()
+        case CFB:
+            return CFBMode()
+        case ECB:
+            return ECBMode()
         }
     }
     
+    var needIV: Bool {
+        return mode.needIV
+    }
     
     /**
     Process input blocks with given block cipher mode. With fallback to plain mode.
@@ -32,7 +44,7 @@ public enum CipherBlockMode {
     
     :returns: encrypted bytes
     */
-    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:CipherWorker) -> [UInt8]? {
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         
         // if IV is not available, fallback to plain
         var finalBlockMode:CipherBlockMode = self
@@ -40,39 +52,31 @@ public enum CipherBlockMode {
             finalBlockMode = .ECB
         }
         
-        switch (finalBlockMode) {
-        case CBC:
-            return CBCMode.encryptBlocks(blocks, iv: iv, cipher: cipher)
-        case CFB:
-            return CFBMode.encryptBlocks(blocks, iv: iv, cipher: cipher)
-        case ECB:
-            return ECBMode.encryptBlocks(blocks, cipher: cipher)
-        }
+        return finalBlockMode.mode.encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
     
-    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:(block:[UInt8]) -> [UInt8]?) -> [UInt8]? {
         // if IV is not available, fallback to plain
         var finalBlockMode:CipherBlockMode = self
         if (iv == nil) {
             finalBlockMode = .ECB
         }
-        
-        switch (finalBlockMode) {
-        case CBC:
-            return CBCMode.decryptBlocks(blocks, iv: iv, cipher: cipher)
-        case CFB:
-            return CFBMode.decryptBlocks(blocks, iv: iv, cipher: cipher)
-        case ECB:
-            return ECBMode.decryptBlocks(blocks, cipher: cipher)
-        }
+
+        return finalBlockMode.mode.decryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
 }
 
 /**
 *  Cipher-block chaining (CBC)
 */
-private struct CBCMode {
-    static func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:CipherWorker) -> [UInt8]? {
+private struct CBCMode: BlockMode {
+    var needIV:Bool = true
+    
+    init() {
+        
+    }
+    
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         assert(iv != nil, "CFB require IV")
         if (iv == nil) {
             return nil;
@@ -89,7 +93,7 @@ private struct CBCMode {
             }
             
             // encrypt with cipher
-            if let encrypted = cipher(block: xoredPlaintext) {
+            if let encrypted = cipherOperation(block: xoredPlaintext) {
                 lastCiphertext = encrypted
                 
                 if (out == nil) {
@@ -102,7 +106,7 @@ private struct CBCMode {
         return out;
     }
     
-    static func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:CipherWorker) -> [UInt8]? {
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         assert(iv != nil, "CFB require IV")
         if (iv == nil) {
             return nil
@@ -111,7 +115,7 @@ private struct CBCMode {
         var out:[UInt8]?
         var lastCiphertext:[UInt8] = iv!
         for (idx,ciphertext) in enumerate(blocks) {
-            if let decrypted = cipher(block: ciphertext) { // decrypt
+            if let decrypted = cipherOperation(block: ciphertext) { // decrypt
                 
                 var xored:[UInt8] = [UInt8](count: ciphertext.count, repeatedValue: 0)
                 for i in 0..<ciphertext.count {
@@ -133,8 +137,9 @@ private struct CBCMode {
 /**
 *  Cipher feedback (CFB)
 */
-private struct CFBMode {
-    static func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:CipherWorker) -> [UInt8]? {
+private struct CFBMode: BlockMode {
+    var needIV:Bool = true
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         assert(iv != nil, "CFB require IV")
         if (iv == nil) {
             return nil
@@ -143,7 +148,7 @@ private struct CFBMode {
         var out:[UInt8]?
         var lastCiphertext:[UInt8] = iv!
         for (idx,plaintext) in enumerate(blocks) {
-            if let encrypted = cipher(block: lastCiphertext) {
+            if let encrypted = cipherOperation(block: lastCiphertext) {
                 var xoredPlaintext:[UInt8] = [UInt8](count: plaintext.count, repeatedValue: 0)
                 for i in 0..<plaintext.count {
                     xoredPlaintext[i] = plaintext[i] ^ encrypted[i]
@@ -161,7 +166,7 @@ private struct CFBMode {
         return out;
     }
     
-    static func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipher:CipherWorker) -> [UInt8]? {
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         assert(iv != nil, "CFB require IV")
         if (iv == nil) {
             return nil
@@ -170,7 +175,7 @@ private struct CFBMode {
         var out:[UInt8]?
         var lastCiphertext:[UInt8] = iv!
         for (idx,ciphertext) in enumerate(blocks) {
-            if let decrypted = cipher(block: lastCiphertext) {
+            if let decrypted = cipherOperation(block: lastCiphertext) {
                 var xored:[UInt8] = [UInt8](count: ciphertext.count, repeatedValue: 0)
                 for i in 0..<ciphertext.count {
                     xored[i] = ciphertext[i] ^ decrypted[i]
@@ -194,11 +199,12 @@ private struct CFBMode {
 /**
 *  Electronic codebook (ECB)
 */
-private struct ECBMode {
-    static func encryptBlocks(blocks:[[UInt8]], cipher:CipherWorker) -> [UInt8]? {
+private struct ECBMode: BlockMode {
+    var needIV:Bool = false
+    func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
         var out:[UInt8]?
         for (idx,plaintext) in enumerate(blocks) {
-            if let encrypted = cipher(block: plaintext) {
+            if let encrypted = cipherOperation(block: plaintext) {
                 
                 if (out == nil) {
                     out = [UInt8]()
@@ -210,7 +216,7 @@ private struct ECBMode {
         return out
     }
     
-    static func decryptBlocks(blocks:[[UInt8]], cipher:CipherWorker) -> [UInt8]? {
-        return encryptBlocks(blocks, cipher: cipher)
+    func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
+        return encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
     }
 }

+ 13 - 3
CryptoSwift/Playground/CryptoPlayground.playground/section-1.swift

@@ -1,7 +1,17 @@
 // Playground - noun: a place where people can play
 
 import Foundation
-import CryptoSwift
 
-let plaintext = "Lorem ipsum"
-let MD5 = plaintext.md5()
+protocol Proto {
+    
+}
+
+struct S1: Proto {
+    
+}
+
+func create<M: Proto>(p:M) -> M {
+    return p()
+}
+
+let qq = create(S1())