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
     */
-    public func encrypt(message:NSData) -> NSData? {
+    public func encrypt(message:NSData, addPadding: Bool = true) -> NSData? {
         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())
+        } 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())
@@ -186,7 +189,7 @@ public class AES {
         return out
     }
     
-    public func decrypt(message:NSData) -> NSData? {
+    public func decrypt(message:NSData, removePadding:Bool = true) -> NSData? {
         if (message.length % AES.blockSizeBytes() != 0) {
             // 128 bit block exceeded
             assertionFailure("AES 128-bit block exceeded!")
@@ -201,6 +204,11 @@ public class AES {
         } else {
             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!)
     }
     

+ 1 - 1
CryptoSwift/PKCS7.swift

@@ -34,7 +34,7 @@ public struct PKCS7 {
     
     public func removePadding() -> NSData {
         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;

+ 3 - 3
README.md

@@ -96,8 +96,7 @@ ChaCha20
 
 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
 	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
 	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 encryptedData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).encrypt(paddedPlaintextData)
 	
 	// or
 	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
 	let decryptedPlaintextData = Cipher.AES(key: keyData, iv: ivData, blockMode: .CBC).decrypt(encryptedData)