AES Encrypt and Decrypt

126,884

Solution 1

I found the solution, it is a good library.

Cross platform 256bit AES encryption / decryption.

This project contains the implementation of 256 bit AES encryption which works on all the platforms (C#, iOS, Android). One of the key objective is to make AES work on all the platforms with simple implementation.

Platforms Supported: iOS , Android , Windows (C#).

https://github.com/Pakhee/Cross-platform-AES-encryption

Solution 2

CryptoSwift Example

Updated to Swift 2

import Foundation
import CryptoSwift

extension String {
    func aesEncrypt(key: String, iv: String) throws -> String{
        let data = self.dataUsingEncoding(NSUTF8StringEncoding)
        let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes(), padding: PKCS7())
        let encData = NSData(bytes: enc, length: Int(enc.count))
        let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
        let result = String(base64String)
        return result
    }

    func aesDecrypt(key: String, iv: String) throws -> String {
        let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
        let dec = try AES(key: key, iv: iv, blockMode:.CBC).decrypt(data!.arrayOfBytes(), padding: PKCS7())
        let decData = NSData(bytes: dec, length: Int(dec.count))
        let result = NSString(data: decData, encoding: NSUTF8StringEncoding)
        return String(result!)
    }
}

Usage:

let key = "bbC2H19lkVbQDfakxcrtNMQdd0FloLyw" // length == 32
let iv = "gqLOHUioQ0QjhuvI" // length == 16
let s = "string to encrypt"
let enc = try! s.aesEncrypt(key, iv: iv)
let dec = try! enc.aesDecrypt(key, iv: iv)
print(s) // string to encrypt
print("enc:\(enc)") // 2r0+KirTTegQfF4wI8rws0LuV8h82rHyyYz7xBpXIpM=
print("dec:\(dec)") // string to encrypt
print("\(s == dec)") // true

Make sure you have the right length of iv (16) and key (32) then you won't hit "Block size and Initialization Vector must be the same length!" error.

Solution 3

CryptoSwift Example

Updated SWIFT 4.*

func aesEncrypt() throws -> String {
    let encrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).encrypt([UInt8](self.data(using: .utf8)!))
    return Data(encrypted).base64EncodedString()
}

func aesDecrypt() throws -> String {
    guard let data = Data(base64Encoded: self) else { return "" }
    let decrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).decrypt([UInt8](data))
    return String(bytes: decrypted, encoding: .utf8) ?? self
}

Solution 4

There is an interesting "pure-swift" Open Source library:

Example with AES decrypt (got from project README.md file):

import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = AES(setup).decrypt(encryptedData)

Solution 5

I was using CommonCrypto to generate Hash through the code of MihaelIsaev/HMAC.swift from Easy to use Swift implementation of CommonCrypto HMAC. This implementation is without using Bridging-Header, with creation of Module file.

Now to use AESEncrypt and Decrypt, I directly added the functions inside "extension String {" in HAMC.swift.

func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
    if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
        data = self.dataUsingEncoding(NSUTF8StringEncoding),
        cryptData    = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {

            let keyLength              = size_t(kCCKeySizeAES128)
            let operation: CCOperation = UInt32(kCCEncrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
            let options:   CCOptions   = UInt32(options)

            var numBytesEncrypted :size_t = 0

            let cryptStatus = CCCrypt(operation,
                algoritm,
                options,
                keyData.bytes, keyLength,
                iv,
                data.bytes, data.length,
                cryptData.mutableBytes, cryptData.length,
                &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
                return base64cryptString
            }
            else {
                return nil
            }
    }
    return nil
}

func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
    if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
        data = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters),
        cryptData    = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {

            let keyLength              = size_t(kCCKeySizeAES128)
            let operation: CCOperation = UInt32(kCCDecrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
            let options:   CCOptions   = UInt32(options)

            var numBytesEncrypted :size_t = 0

            let cryptStatus = CCCrypt(operation,
                algoritm,
                options,
                keyData.bytes, keyLength,
                iv,
                data.bytes, data.length,
                cryptData.mutableBytes, cryptData.length,
                &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let unencryptedMessage = String(data: cryptData, encoding:NSUTF8StringEncoding)
                return unencryptedMessage
            }
            else {
                return nil
            }
    }
    return nil
}

The functions were taken from RNCryptor. It was an easy addition in the hashing functions and in one single file "HMAC.swift", without using Bridging-header. I hope this will be useful for developers in swift requiring Hashing and AES Encryption/Decryption.

Example of using the AESDecrypt as under.

 let iv = "AA-salt-BBCCDD--" // should be of 16 characters.
 //here we are convert nsdata to String
 let encryptedString = String(data: dataFromURL, encoding: NSUTF8StringEncoding)
 //now we are decrypting
 if let decryptedString = encryptedString?.aesDecrypt("12345678901234567890123456789012", iv: iv) // 32 char pass key
 {                    
      // Your decryptedString
 }
Share:
126,884
mehr
Author by

mehr

Updated on March 19, 2020

Comments

  • mehr
    mehr about 4 years

    I write an application by swift, i need AES Encrypt and Decrypt functionality, i received encrypted data from another .Net solution, but i can't find something to do it.

    This is my .net Encryption:

     public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
        {
            byte[] encryptedBytes = null;
    
            byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
    
            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;
    
                    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);
    
                    AES.Mode = CipherMode.CBC;
    
                    using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }
    
            return encryptedBytes;
        }
    

    I need to decrypt function in swift.

  • Deekor
    Deekor over 8 years
    this code throws an error Block size and Initialization Vector must be the same length! when doing the encryption.
  • Admin
    Admin over 8 years
    @Deekor I just added the usage example. iv and key need to be in the right length. 16 for iv and 32 for key.
  • Fred Faust
    Fred Faust over 8 years
    Is there a way to create the IV from the key value?
  • Thiha Aung
    Thiha Aung over 8 years
    i got nil error when i encrypt that string "q3xnpwB3d3+UCW1zt6LM4ePQAVkOw/ZRF5qBB7J2YTdqlZaWSzZR+oXEAOl‌​gkt43AoY2BhqjBltf1e7‌​ZRNs5XIPHTOkNqgYfAPz‌​fsGUPo+8=" Something wrong?
  • zaph
    zaph about 8 years
    Yep, AES encryption using CryptoSwift is 500 to 1000 times slower than Common Crypto, this is because Common Crypto utilizes the hardware encryption capabilities and CryptoSwift does not.
  • zaph
    zaph about 8 years
    Note that CryptoSwift is 500 to 1000 times slower than Common Crypto.
  • Artjom B.
    Artjom B. almost 8 years
    That's quite a bad library. a) Key and IV are padded with null for some reason if they don't have the right size. This is bad, because people are just gonna use that with passwords, but passwords don't have enough entropy to be used as keys! Instead keys can be derived from passwords with schemes such as PBKDF2 or Argon2. b) This library doesn't provide authentication at all. c) IV's are for some reason text-based and not binary. d) The users needs to manage the IV themselves and will most likely get it wrong.
  • Shree Prakash
    Shree Prakash over 7 years
    @yutelin Can you provide me File encryption and decryption demo using CryptoSwift . Please
  • Shree Prakash
    Shree Prakash over 7 years
    Can you provide me File encryption and decryption demo using RNCryptor..Please
  • SHS
    SHS over 7 years
    @ShreePool - You may get full code in swift 3.0 and usage of HAMC from this link stackoverflow.com/a/41465726/2641380
  • Shree Prakash
    Shree Prakash over 7 years
    actually I want to solve this.stackoverflow.com/questions/41542890/…
  • Jayprakash Dubey
    Jayprakash Dubey about 7 years
    How to get IV value?
  • Rekha.t
    Rekha.t about 7 years
    problem in both encryption and decryption while using this library.
  • zaph
    zaph almost 7 years
    It is best to avoid using CryptoSwift, amoung other things it is 500 to 1000 times slower than Common Crypto based implementations. Apple's Common Crypto is FIPS certified and as such has been well vetted, using CryptoSwift is taking a chance on correctness and security.
  • Yaroslav Dukal
    Yaroslav Dukal almost 7 years
    I am using this for encrypting chat messages. Basically what you saying is this is not good idea? I have been using it for a while and did not notice anything bad...
  • zaph
    zaph almost 7 years
    Essentially every data breach can say "I have been using it for a while and did not notice anything bad" … but then something bad happened. It's like seat belts, why bother.
  • Dinesh
    Dinesh about 6 years
    Is there any example without an iv. If yes can you please share it here.
  • Qadir Hussain
    Qadir Hussain almost 6 years
    getting this error Type 'Cipher' has no member 'AES'
  • Yaroslav Dukal
    Yaroslav Dukal over 5 years
    @zaph It would be nice if you could provide your recommended implementation example.
  • Yaroslav Dukal
    Yaroslav Dukal over 5 years
    @zaph what data breach are you talking about ? How could you decrypt encrypted string not knowing what method was it used to decrypt, KEY and IV??
  • Archy Will He 何魏奇
    Archy Will He 何魏奇 over 5 years
    @MaksimKniazev hmm what do you mean?
  • Yaroslav Dukal
    Yaroslav Dukal over 5 years
    @ArchyWilhes魏何 what are you referring to??
  • Ahmadreza
    Ahmadreza about 5 years
    Use of unresolved identifier 'AES'; did you mean 'YES'?
  • westrada
    westrada almost 5 years
    Your solution works very well but in the last line of code it's not necessary doing Data(decrypted).bytes since decrypted is [UInt8]
  • NoodleOfDeath
    NoodleOfDeath almost 5 years
    @QadirHussain try just AES instead of Cipher.AES.
  • Alex Zavatone
    Alex Zavatone about 4 years
    No, you can't just copy and paste those methods. AES isn't declared anywhere. What did you do? Add CryptoSwift to your project and not tell us?
  • user40176
    user40176 about 4 years
    Just wanted to note that this is where Voatz copy and pasted the key and IV they hardcoded into their "secure" voting platform.
  • Ravi Sharma
    Ravi Sharma about 4 years
    where to get value for ivData?
  • JAnton
    JAnton almost 4 years
    Just what I was looking for. Thx
  • Raviteja Mathangi
    Raviteja Mathangi almost 4 years
    getting nil value in decrypted string can you help me .. i following you're code.i have only secret key and encrypted string
  • Steven W. Klassen
    Steven W. Klassen over 3 years
    Just found a very big error in the CommonCrypto version of this answer. At least, it is a problem with Swift 5.2 - perhaps it was not with Swift 4.2. The problem is that only the first character of the key seems to be significant. I can decrypt my messages with any key of the same length that begins with the same letter! The problem seems to be with the Array(key) passed as the forth argument in CCCrypt. If I replace it with just key it seems to work properly.
  • Amit
    Amit about 3 years
    @MaksimKniazev please hep here stackoverflow.com/questions/66757704/…
  • Amit
    Amit about 3 years
    @yutelin please help here stackoverflow.com/questions/66757704/…
  • metamonkey
    metamonkey over 2 years
    Fair warning folks: CryptoSwift is not worth using. Key derivation takes too much time to be feasible. stackoverflow.com/q/68931972/5786349