Browse Source

Manual padding of data is optional and CryptoSwift by default always will add PKCS7 padding before encryption, and remove after decryption when Cipher enum is used. If you need manually disable/enable padding, you can do this by setting parameter for encrypt()/decrypt() on class AES.

Marcin Krzyżanowski 11 years ago
parent
commit
dc9e634654
3 changed files with 17 additions and 9 deletions
  1. 13 5
      CryptoSwift/AES.swift
  2. 1 1
      CryptoSwift/PKCS7.swift
  3. 3 3
      README.md

+ 13 - 5
CryptoSwift/AES.swift

@@ -140,12 +140,15 @@ public class AES {
     
     
     :returns: Encrypted data
     :returns: Encrypted data
     */
     */
-    public func encrypt(message:NSData) -> NSData? {
+    public func encrypt(message:NSData, addPadding: Bool = true) -> NSData? {
         var finalMessage = message;
         var finalMessage = message;
-        if (message.length % AES.blockSizeBytes() != 0) {
-            // 128 bit block exceeded, need padding
-            // by default PKCS7 padding is addedd
+
+        if (addPadding) {
             finalMessage = PKCS7(data: message).addPadding(AES.blockSizeBytes())
             finalMessage = PKCS7(data: message).addPadding(AES.blockSizeBytes())
+        } else if (message.length % AES.blockSizeBytes() != 0) {
+            // 128 bit block exceeded, need padding
+            assertionFailure("AES 128-bit block exceeded!")
+            return nil
         }
         }
         
         
         let blocks = finalMessage.bytes().chunks(AES.blockSizeBytes())
         let blocks = finalMessage.bytes().chunks(AES.blockSizeBytes())
@@ -186,7 +189,7 @@ public class AES {
         return out
         return out
     }
     }
     
     
-    public func decrypt(message:NSData) -> NSData? {
+    public func decrypt(message:NSData, removePadding:Bool = true) -> NSData? {
         if (message.length % AES.blockSizeBytes() != 0) {
         if (message.length % AES.blockSizeBytes() != 0) {
             // 128 bit block exceeded
             // 128 bit block exceeded
             assertionFailure("AES 128-bit block exceeded!")
             assertionFailure("AES 128-bit block exceeded!")
@@ -201,6 +204,11 @@ public class AES {
         } else {
         } else {
             out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipher: decryptBlock)
             out = blockMode.decryptBlocks(blocks, iv: self.iv?.bytes(), cipher: decryptBlock)
         }
         }
+        
+        if (out != nil && removePadding) {
+            return PKCS7(data: NSData.withBytes(out!)).removePadding()
+        }
+        
         return out == nil ? nil : NSData.withBytes(out!)
         return out == nil ? nil : NSData.withBytes(out!)
     }
     }
     
     

+ 1 - 1
CryptoSwift/PKCS7.swift

@@ -34,7 +34,7 @@ public struct PKCS7 {
     
     
     public func removePadding() -> NSData {
     public func removePadding() -> NSData {
         if let padding = data.bytes().last {
         if let padding = data.bytes().last {
-            if (padding <= 8) {
+            if (padding >= 1 && padding <= 8) {
                 return data.subdataWithRange(NSRange(location: 0, length: data.length - Int(padding)))
                 return data.subdataWithRange(NSRange(location: 0, length: data.length - Int(padding)))
             }
             }
             return data;
             return data;

+ 3 - 3
README.md

@@ -96,8 +96,7 @@ ChaCha20
 
 
 AES
 AES
 
 
-Padding plaintext data is required for most of the cases (unless message can be split into chunks of block size). Nonetheless explicit padding is optional  and CryptoSwift will add padding when necessary. Removing padding is necessary after decryption if applied earlier (CryptoSwift can't decide if padding was applied earlier, this is up to you). For this reason the most convenient way is always add padding before encryption and remove after decryption, as described below:
-
+Notice regarding padding: *Manual padding of data is optional and CryptoSwift by default always will add PKCS7 padding before encryption, and remove after decryption when __Cipher__ enum is used. If you need manually disable/enable padding, you can do this by setting parameter for encrypt()/decrypt() on class __AES__.*
 
 
 	// 1. Add padding
 	// 1. Add padding
 	let paddedPlaintextData = PKCS7(data: plaintextData).addPadding(AES.blockSizeBytes())
 	let paddedPlaintextData = PKCS7(data: plaintextData).addPadding(AES.blockSizeBytes())
@@ -105,11 +104,12 @@ Padding plaintext data is required for most of the cases (unless message can be
 	// 2. Encrypt with key and random IV
 	// 2. Encrypt with key and random IV
 	let keyData = NSData.withBytes([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
 	let keyData = NSData.withBytes([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
 	let ivData:NSData = Cipher.randomIV(keyData)
 	let ivData:NSData = Cipher.randomIV(keyData)
+	
 	let encryptedData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).encrypt(paddedPlaintextData)
 	let encryptedData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).encrypt(paddedPlaintextData)
 	
 	
 	// or
 	// or
 	let aes = AES(key: keyData, iv: ivData, blockMode: .CBC) // CBC is default
 	let aes = AES(key: keyData, iv: ivData, blockMode: .CBC) // CBC is default
-	let encryptedData = aes?.encrypt(paddedData)
+	let encryptedData = aes?.encrypt(paddedData, addPadding: true) // With padding enabled
 	
 	
 	// 3. decrypt with key and IV
 	// 3. decrypt with key and IV
 	let decryptedPlaintextData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).decrypt(encryptedData)
 	let decryptedPlaintextData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).decrypt(encryptedData)