Asynchronous encryption in Swift

I am trying to encrypt a string, using Public/Private Key system. I need to pass a string to the server, where a PHP script can decrypt it. I have a working JavaScript to PHP script system, however, I’d like to make it possible for the PHP script to also accept data from the iOS app. Can anyone point me in the right direction, or perhaps even introduce me to a system which could achieve a similar result. I am looking for any type of encryption that I could use to decrypt with PHP. Thank you in advance.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

PHP and iOS both support AES encryption.

On iOS Common Crypto supports both asymmetric (RSA) and symmetric (AES) encryption. If there is not a compelling need for PKI (Public key infrastructure) use AES.

The only issue is that PHP uses non-standard padding (null) instead of PKCS#7 so you will have to do your own padding either on the iOS size to match the Bozo scheme PHP uses or on the PHP side to match the standard PKCS#7. Note the PHP padding fails if the last byte of the data is 0.

Here is an implementation example wrapped in a function with an iv:

Swift 2.0

Add the Security.framework to the project.

#import <CommonCrypto/CommonCrypto.h

func testCrypt(data:NSData, keyData:NSData, ivData:NSData, operation:CCOperation) -> NSData? {
    let keyBytes = UnsafePointer<UInt8>(keyData.bytes)
    print("keyLength   = \(keyData.length), keyData   = \(keyData)")

    let ivBytes = UnsafePointer<UInt8>(ivData.bytes)
    print("ivLength    = \(ivData.length), ivData    = \(ivData)")

    let dataLength = Int(data.length)
    let dataBytes  = UnsafePointer<UInt8>(data.bytes)
    print("dataLength  = \(dataLength), data      = \(data)")

    let cryptData: NSMutableData! = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
    let cryptPointer = UnsafeMutablePointer<UInt8>(cryptData.mutableBytes)
    let cryptLength  = size_t(cryptData.length)

    let keyLength              = size_t(kCCKeySizeAES128)
    let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
    let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding)

    var numBytesEncrypted :size_t = 0

    let cryptStatus = CCCrypt(operation,
        algoritm,
        options,
        keyBytes, keyLength,
        ivBytes,
        dataBytes, dataLength,
        cryptPointer, cryptLength,
        &numBytesEncrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.length = Int(numBytesEncrypted)
        print("cryptLength = \(numBytesEncrypted), cryptData = \(cryptData)")

    } else {
        print("Error: \(cryptStatus)")
    }

    return cryptData;
}

// Test code:

let keyString = "!Use a data key!"
let keyData = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!

let ivString = "Use a random iv!"
let ivData = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!

let message = "Don´t try to read this text. Top Secret Stuff"
let data = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!

print("data: \(data)")
if let encryptedData = testCrypt(data, keyData:keyData, ivData:ivData, operation:UInt32(kCCEncrypt)) {
    print("encryptedData: \(encryptedData)")
    if let decryptedData = testCrypt(encryptedData, keyData:keyData, ivData:ivData, operation:UInt32(kCCDecrypt)) {
        print("decryptedData: \(decryptedData)")
    }
}

Output:

data: 446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666
keyLength   = 16, keyData   = 21557365 20612064 61746120 6b657921
ivLength    = 16, ivData    = 21557365 20612064 61746120 6b657921
dataLength  = 46, data      = 446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666
cryptLength = 48, cryptData = c184cb8b 3d24b56f 1e2896c4 a933a824 d5f8820b 9e7549c6 4188594c 8c1e5941 67adbc80 420bc362 0d851d4f f88d6675
encryptedData: c184cb8b 3d24b56f 1e2896c4 a933a824 d5f8820b 9e7549c6 4188594c 8c1e5941 67adbc80 420bc362 0d851d4f f88d6675
keyLength   = 16, keyData   = 21557365 20612064 61746120 6b657921
ivLength    = 16, ivData    = 21557365 20612064 61746120 6b657921
dataLength  = 48, data      = c184cb8b 3d24b56f 1e2896c4 a933a824 d5f8820b 9e7549c6 4188594c 8c1e5941 67adbc80 420bc362 0d851d4f f88d6675
cryptLength = 46, cryptData = 446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666
decryptedData: 446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666

There are other examples of Swift AES encryption here on SO.

ECB example SO answer wrapped in a function, but you should really use CBC mode.

CBC example SO answer code.

Solution 2

Possibly you can use openssl library to encrypt/decrypt RSA.

It exits in both iOS and PHP.

If you want to send your strings in safe manner, using security layer (SSL/TLS) is enough as Zaph says.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply