AES Encrypt and Decrypt
Asked Answered
P

12

38

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.

Phrenology answered 21/11, 2014 at 23:20 Comment(2)
I found it, github.com/Pakhee/Cross-platform-AES-encryption And i can add Objective-C file to my project, but i have a lot of problem in call methods and returns values, swift and objective-C are not compatible :(Phrenology
Did you found solution, i need same solution for iOS.Fra
P
2

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

Phrenology answered 22/11, 2014 at 13:22 Comment(2)
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.Lock
problem in both encryption and decryption while using this library.Keefer
B
36

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.

Bhopal answered 13/6, 2015 at 16:1 Comment(11)
this code throws an error Block size and Initialization Vector must be the same length! when doing the encryption.Nuptial
@Nuptial I just added the usage example. iv and key need to be in the right length. 16 for iv and 32 for key.Bhopal
Is there a way to create the IV from the key value?Fusty
i got nil error when i encrypt that string "q3xnpwB3d3+UCW1zt6LM4ePQAVkOw/ZRF5qBB7J2YTdqlZaWSzZR+oXEAOlgkt43AoY2BhqjBltf1e7ZRNs5XIPHTOkNqgYfAPzfsGUPo+8=" Something wrong?Granuloma
Note that CryptoSwift is 500 to 1000 times slower than Common Crypto.Earp
@Bhopal Can you provide me File encryption and decryption demo using CryptoSwift . PleaseEx
How to get IV value?Mexicali
Is there any example without an iv. If yes can you please share it here.Euphonic
Just wanted to note that this is where Voatz copy and pasted the key and IV they hardcoded into their "secure" voting platform.Cardigan
@Bhopal please help here #66758204Danas
Fair warning folks: CryptoSwift is not worth using. Key derivation takes too much time to be feasible. https://mcmap.net/q/410274/-pbkdf2-key-derivation-taking-too-long/5786349Boron
P
33

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
}
Provitamin answered 11/12, 2016 at 5:52 Comment(9)
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.Earp
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...Provitamin
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.Earp
@Earp It would be nice if you could provide your recommended implementation example.Provitamin
@Earp 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??Provitamin
@MaksimKniazev hmm what do you mean?Physicochemical
@ArchyWilhes魏何 what are you referring to??Provitamin
Your solution works very well but in the last line of code it's not necessary doing Data(decrypted).bytes since decrypted is [UInt8]Banff
@MaksimKniazev please hep here #66758204Danas
P
14

Code provided by SHS didn't work for me, but this one apparently did (I used a Bridging Header: #import <CommonCrypto/CommonCrypto.h>):

extension String {

    func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
        if let keyData = key.data(using: String.Encoding.utf8),
            let data = self.data(using: String.Encoding.utf8),
            let cryptData    = NSMutableData(length: Int((data.count)) + 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 as NSData).bytes, keyLength,
                                      iv,
                                      (data as NSData).bytes, data.count,
                                      cryptData.mutableBytes, cryptData.length,
                                      &numBytesEncrypted)

            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
                return base64cryptString


            }
            else {
                return nil
            }
        }
        return nil
    }

    func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
        if let keyData = key.data(using: String.Encoding.utf8),
            let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
            let 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 as NSData).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 as Data, encoding:String.Encoding.utf8)
                return unencryptedMessage
            }
            else {
                return nil
            }
        }
        return nil
    }


}

From my ViewController:

 let encoded = message.aesEncrypt(key: keyString, iv: iv)
 let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
Participial answered 4/8, 2017 at 12:49 Comment(3)
Worked like a charm. Then used the following in my php code. $decryptedData = openssl_decrypt(base64_decode($data), OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv);Cohe
#user1094081 do u have same in Objective c?Razo
Worked like a charm. Server side C# code and service side Crypto JS, very easy to implement, because of String input and String outputSven
B
8

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)
Brena answered 20/1, 2015 at 17:15 Comment(3)
getting this error Type 'Cipher' has no member 'AES'Tachometer
@QadirHussain try just AES instead of Cipher.AES.Triode
where to get value for ivData?Slum
B
6

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
 }
Bordure answered 17/3, 2016 at 11:26 Comment(3)
Can you provide me File encryption and decryption demo using RNCryptor..PleaseEx
@ShreePool - You may get full code in swift 3.0 and usage of HAMC from this link https://mcmap.net/q/162037/-commonhmac-in-swiftBordure
actually I want to solve this.#41543390Ex
C
5

CryptoSwift is very interesting project but for now it has some AES speed limitations. Be carefull if you need to do some serious crypto - it might be worth to go through the pain of bridge implemmenting CommonCrypto.

BigUps to Marcin for pureSwift implementation

Cheriecherilyn answered 5/1, 2016 at 10:56 Comment(1)
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.Earp
S
5

You can use CommonCrypto from iOS or CryptoSwift as external library. There are implementations with both tools below. That said, CommonCrypto output with AES should be tested, as it is not clear in CC documentation, which mode of AES it uses.

CommonCrypto in Swift 4.2

    import CommonCrypto

    func encrypt(data: Data) -> Data {
        return cryptCC(data: data, key: key, operation: kCCEncrypt)
    }

    func decrypt(data: Data) -> Data {
        return cryptCC(data: data, key: key, operation: kCCDecrypt)
    }

    private func cryptCC(data: Data, key: String operation: Int) -> Data {

        guard key.count == kCCKeySizeAES128 else {
            fatalError("Key size failed!")
        }

        var ivBytes: [UInt8]
        var inBytes: [UInt8]
        var outLength: Int

        if operation == kCCEncrypt {
            ivBytes = [UInt8](repeating: 0, count: kCCBlockSizeAES128)
            guard kCCSuccess == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
                fatalError("IV creation failed!")
            }

            inBytes = Array(data)
            outLength = data.count + kCCBlockSizeAES128

        } else {
            ivBytes = Array(Array(data).dropLast(data.count - kCCBlockSizeAES128))
            inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128))
            outLength = inBytes.count

        }

        var outBytes = [UInt8](repeating: 0, count: outLength)
        var bytesMutated = 0

        guard kCCSuccess == CCCrypt(CCOperation(operation), CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), Array(key), kCCKeySizeAES128, &ivBytes, &inBytes, inBytes.count, &outBytes, outLength, &bytesMutated) else {
            fatalError("Cryptography operation \(operation) failed")
        }

        var outData = Data(bytes: &outBytes, count: bytesMutated)

        if operation == kCCEncrypt {
            ivBytes.append(contentsOf: Array(outData))
            outData = Data(bytes: ivBytes)
        }
        return outData

    }


CryptoSwift v0.14 in Swift 4.2


    enum Operation {
        case encrypt
        case decrypt
    }

    private let keySizeAES128 = 16
    private let aesBlockSize = 16

    func encrypt(data: Data, key: String) -> Data {
        return crypt(data: data, key: key, operation: .encrypt)
    }

    func decrypt(data: Data, key: String) -> Data {
        return crypt(data: data, key: key, operation: .decrypt)
    }

    private func crypt(data: Data, key: String, operation: Operation) -> Data {

        guard key.count == keySizeAES128 else {
            fatalError("Key size failed!")
        }
        var outData: Data? = nil

        if operation == .encrypt {
            var ivBytes = [UInt8](repeating: 0, count: aesBlockSize)
            guard 0 == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
                fatalError("IV creation failed!")
            }

            do {
                let aes = try AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
                let encrypted = try aes.encrypt(Array(data))
                ivBytes.append(contentsOf: encrypted)
                outData = Data(bytes: ivBytes)

            } catch {
                print("Encryption error: \(error)")
            }

        } else {
            let ivBytes = Array(Array(data).dropLast(data.count - aesBlockSize))
            let inBytes = Array(Array(data).dropFirst(aesBlockSize))

            do {
                let aes = try AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
                let decrypted = try aes.decrypt(inBytes)
                outData = Data(bytes: decrypted)

            } catch {
                print("Decryption error: \(error)")
            }
        }
        return outData!

    }

Schrecklichkeit answered 27/2, 2019 at 8:33 Comment(1)
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.Settlings
N
4

Update Swift 4.2

Here, for instance, we encrypt a string to base64encoded string. And then we decrypt the same to a readable string. (That would be same as our input string).

In my case, I use this to encrypt a string and embed that to QR Code. Then another party scan that and decrypt the same. So intermediate won't understand the QR codes.

Step 1: Encrypt a string "Encrypt My Message 123"

Step 2: Encrypted base64Encoded string : +yvNjiD7F9/JKmqHTc/Mjg== (The same printed on QR code)

Step 3: Scan and decrypt the string "+yvNjiD7F9/JKmqHTc/Mjg=="

Step 4: It comes final result - "Encrypt My Message 123"

Functions for Encrypt & Decrypt:

func encryption(stringToEncrypt: String) -> String{
    let key = "MySecretPKey"
    //let iv = "92c9d2c07a9f2e0a"
    let data = stringToEncrypt.data(using: .utf8)
    let keyD = key.data(using: .utf8)
    let encr = (data as NSData?)!.aes128EncryptedData(withKey: keyD)
    let base64String: String = (encr as NSData?)!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    print(base64String)
    return base64String
}

func decryption(encryptedString:String) -> String{
    let key = "MySecretPKey"
    //let iv = "92c9d2c07a9f2e0a"
    let keyD = key.data(using: .utf8)
    let decrpStr = NSData(base64Encoded: encryptedString, options: NSData.Base64DecodingOptions(rawValue: 0))
    let dec = (decrpStr)!.aes128DecryptedData(withKey: keyD)
    let backToString = String(data: dec!, encoding: String.Encoding.utf8)
    print(backToString!)
    return backToString!
}

Usage:

    let enc = encryption(stringToEncrypt: "Encrypt My Message 123")
    let decryptedString = decryption(encryptedString: enc)
    print(decryptedString) 

Classes for supporting AES encrypting functions, these are written in Objective-C. So for swift, you need to use bridge header to support these.

Class Name: NSData+AES.h

#import <Foundation/Foundation.h>

@interface NSData (AES)

- (NSData *)AES128EncryptedDataWithKey:(NSData *)key;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key;
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv;

@end

Class Name: NSData+AES.m

#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES)

- (NSData *)AES128EncryptedDataWithKey:(NSData *)key
{
    return [self AES128EncryptedDataWithKey:key iv:nil];
}

- (NSData *)AES128DecryptedDataWithKey:(NSData *)key
{
    return [self AES128DecryptedDataWithKey:key iv:nil];
}

- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
    return [self AES128Operation:kCCEncrypt key:key iv:iv];
}

- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
    return [self AES128Operation:kCCDecrypt key:key iv:iv];
}

- (NSData *)AES128Operation:(CCOperation)operation key:(NSData *)key iv:(NSData *)iv
{
    
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          key.bytes,
                                          kCCBlockSizeAES128,
                                          iv.bytes,
                                          [self bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}

@end
Notify answered 20/12, 2018 at 7:31 Comment(2)
Just what I was looking for. ThxGalloping
getting nil value in decrypted string can you help me .. i following you're code.i have only secret key and encrypted stringDabber
L
4

Swift4:

let key = "ccC2H19lDDbQDfakxcrtNMQdd0FloLGG" // length == 32
let iv = "ggGGHUiDD0Qjhuvv" // length == 16
func encryptFile(_ path: URL) -> Bool{
    do{
        let data = try Data.init(contentsOf: path)
        let encodedData = try data.aesEncrypt(key: key, iv: iv)
        try encodedData.write(to: path)
        return true
    }catch{
        return false
    }
}

func decryptFile(_ path: URL) -> Bool{
    do{
        let data = try Data.init(contentsOf: path)
        let decodedData = try data.aesDecrypt(key: key, iv: iv)
        try decodedData.write(to: path)
        return true
    }catch{
        return false
    }
}

Install CryptoSwift

import CryptoSwift
extension Data {
    func aesEncrypt(key: String, iv: String) throws -> Data{
        let encypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).encrypt(self.bytes)
        return Data(bytes: encypted)
    }

    func aesDecrypt(key: String, iv: String) throws -> Data {
        let decrypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).decrypt(self.bytes)
        return Data(bytes: decrypted)
    }
}
Leyla answered 15/1, 2019 at 19:16 Comment(0)
P
2

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

Phrenology answered 22/11, 2014 at 13:22 Comment(2)
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.Lock
problem in both encryption and decryption while using this library.Keefer
K
0

This is a pretty old post but XCode 10 added the CommonCrypto module so you don't need a module map. Also with Swift 5, no need for the annoying casts.

You could do something like:

func decrypt(_ data: Data, iv: Data, key: Data) throws -> String {

    var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128)
    var bufferLen: Int = 0

    let status = CCCrypt(
        CCOperation(kCCDecrypt),
        CCAlgorithm(kCCAlgorithmAES128),
        CCOptions(kCCOptionPKCS7Padding),
        [UInt8](key),
        kCCBlockSizeAES128,
        [UInt8](iv),
        [UInt8](data),
        data.count,
        &buffer,
        buffer.count,
        &bufferLen
    )

    guard status == kCCSuccess,
        let str = String(data: Data(bytes: buffer, count: bufferLen),
                         encoding: .utf8) else {
                            throw NSError(domain: "AES", code: -1, userInfo: nil)
    }

    return str
}
Koah answered 3/9, 2019 at 22:44 Comment(0)
R
-2

You can just copy & paste these methods (Swift 4+):

    class func encryptMessage(message: String, encryptionKey: String, iv: String) -> String? {
        if let aes = try? AES(key: encryptionKey, iv: iv),
            let encrypted = try? aes.encrypt(Array<UInt8>(message.utf8)) {
            return encrypted.toHexString()
        }
        return nil
    }

    class func decryptMessage(encryptedMessage: String, encryptionKey: String, iv: String) -> String? {
        if let aes = try? AES(key: encryptionKey, iv: iv),
            let decrypted = try? aes.decrypt(Array<UInt8>(hex: encryptedMessage)) {
            return String(data: Data(bytes: decrypted), encoding: .utf8)
        }
        return nil
    }

Example:

let encryptMessage = encryptMessage(message: "Hello World!", encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")    
// Output of encryptMessage is: 649849a5e700d540f72c4429498bf9f4

let decryptedMessage = decryptMessage(encryptedMessage: encryptMessage, encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of decryptedMessage is: Hello World!

Don't forget encryptionKey & iv should be 16 bytes.


Rainfall answered 9/11, 2018 at 18:21 Comment(2)
Use of unresolved identifier 'AES'; did you mean 'YES'?Gerontocracy
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?Twinge

© 2022 - 2024 — McMap. All rights reserved.