Issue decrypting with CommonCrypto in Swift

不羁的心 提交于 2019-12-04 12:11:54

The difference is that NSData+AESCrypt.m is using CBC mode (the default) with an iv of NULL. The code in the question is using ECB mode.

Best practice is to use CBC mode with a random iv. The iv is typically pre-pended to the encrypted data so the decryption can separate the iv and data prior to decryption.

Do not use NSData+AESCrypt.m, it has not been maintained, is a category on NSData, does not support ARC. Consider RNCryptor for Objective-C, it is actively maintained.

This is the change I made in "NSData+AESCrypt.m", method AES256EncryptWithKey: kCCOptionPKCS7Padding + kCCOptionECBMode. I added kCCOptionECBMode, that's all.

Here is the call I made: NSString *keyString = @"12345678901234567890123456789012";

NSString *message = @"Don´t try to read this text. Top Secret Stuff";
NSData   *data    = [message dataUsingEncoding:NSUTF8StringEncoding];

NSData *crypData = [data AES256EncryptWithKey:keyString];
NSLog(@"crypData: %@", crypData);

Output:

crypData: <118a32dc c23f7caa 883abc3c 1c7f0770 e200016b 2737acfa 17bb96fb a02b02a7 c147603b 06acd863 94bb8ff2 6cb14515>

Which is the same as from the above code (the same as the previous question):

cryptData = <118a32dc c23f7caa 883abc3c 1c7f0770 e200016b 2737acfa 17bb96fb a02b02a7 c147603b 06acd863 94bb8ff2 6cb14515>

It is just a matter of getting all of the inputs the same: operation, algorithm, options, keyBytes, keyLength, dataBytes, dataLength and iv if non ECB mode. CCCrypt is just a function call, that's all. Put in the same input, get the same output.

Put in NSLog() statements, preferably hex dumps for data and strings. Compare and fix as needed.

Believe it or not, this is the easy part of electronic security.

Swift 2.0 AES128 Encryption and Decryption.

Should import the following header into Obj-c bridge header inorder to work

#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonKeyDerivation.h>


static func AES128Encryption()
    {
        let keyString        = "12345678901234567890123456789012"
        let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let keyBytes         = UnsafeMutablePointer<Void>(keyData.bytes)
        print("keyLength   = \(keyData.length), keyData   = \(keyData)")

        let message       = "Don´t try to read this text. Top Secret Stuff"
        let data: NSData! = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let dataLength    = size_t(data.length)
        let dataBytes     = UnsafeMutablePointer<Void>(data.bytes)
        print("dataLength  = \(dataLength), data      = \(data)")

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

        let keyLength              = size_t(kCCKeySizeAES256)
        let operation: CCOperation = UInt32(kCCEncrypt)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
        let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding + kCCOptionECBMode)

        var numBytesEncrypted :size_t = 0

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

        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
          //  let x: UInt = numBytesEncrypted
            cryptData!.length = Int(numBytesEncrypted)
            print("cryptLength = \(numBytesEncrypted), cryptData = \(cryptData)")

            // Not all data is a UTF-8 string so Base64 is used
            let base64cryptString = cryptData!.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
            print("base64cryptString = \(base64cryptString)")

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

    static func AES128Decryption(data:NSData) //data = cryptData
    {
        let keyString        = "12345678901234567890123456789012"
        let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let keyBytes         = UnsafeMutablePointer<Void>(keyData.bytes)
        print("keyLength   = \(keyData.length), keyData   = \(keyData)")

        //let message       = "Don´t try to read this text. Top Secret Stuff"
       // let data: NSData! = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let dataLength    = size_t(data.length)
        let dataBytes     = UnsafeMutablePointer<Void>(data.bytes)
        print("dataLength  = \(dataLength), data      = \(data)")

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

        let keyLength              = size_t(kCCKeySizeAES256)
        let operation: CCOperation = UInt32(kCCDecrypt)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
        let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding + kCCOptionECBMode)

        var numBytesEncrypted :size_t = 0

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

        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            //  let x: UInt = numBytesEncrypted
            cryptData!.length = Int(numBytesEncrypted)
            print("DecryptcryptLength = \(numBytesEncrypted), Decrypt = \(cryptData)")

            // Not all data is a UTF-8 string so Base64 is used
            let base64cryptString = cryptData!.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
            print("base64DecryptString = \(base64cryptString)")
               print( "utf8 actual string = \(NSString(data: cryptData!, encoding: NSUTF8StringEncoding))");
        } else {
            print("Error: \(cryptStatus)")
        }
    }

Swift4 AES128 Decryption and JWT

Note: If iv is used along with key while encrypting the plain text dont use it while decrypting , your issue will be resolved. key and iv length is 16bit

Following code for decryption may help you: Here the encrypted string used for decryption is base64Encoded and the decrypted string which we get is JWT(Json Web Token).

To Configure CommonCrypto refer link: How is CommonCrypto used in SWIFT3?

https://www.devglan.com/online-tools/aes-encryption-decryption https://jwt.io/

import UIKit import CommonCrypto

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    testAES()
}


func testAES()  {

    let testMessSr  = "74oIlwieBbxGvHjibQoSxWWAL0zNfy7yaQboYizPc+ouMsAkXbvMNb0RagXklA2zOlo29J7Zr7zFiOalBfKSvV3pzw7KWCtTMw16SNeOIRWYpSWNcNXxgoQR7Jy33s0JP8elQCo/6G+inivE2hm3kl7QTr/Jz5bx/ho0LmWrirn/L4WAJlDFHue23vjhrKGIfEvwIdWHPNh1qd+hCY4pQA==:NjkzQUU1MkM5RTZERjNFMA=="

    //Here I'm separating iv from base64encoded string as while decrypting theres no need of iv
    let splitStr = testMessSr.components(separatedBy: ":")

    print("base64EncodedString: \(splitStr[0])")
    print("iv: \(splitStr[1])")

    let base64EncodedString = splitStr[0]

    let message = Data(base64Encoded: base64EncodedString ,options : Data.Base64DecodingOptions.ignoreUnknownCharacters)
    let key         = "EE99C7A159003D36"
    let ivString     = "693AE52C9E6DF3E0"   // 16 bytes for AES128

   // let messageData = message.data(using:String.Encoding.utf8)!
    let keyData     = key.data(using: .utf8)!
    let ivData      = ivString.data(using: .utf8)!

    let decryptedData = message?.aesEncrypt( keyData:keyData, ivData:ivData, operation:kCCDecrypt)
    print("decryptedData: \(decryptedData)")
    let decryptedString = String(data: decryptedData as! Data, encoding: String.Encoding.utf8)
    print("decryptedString: \(decryptedString)") //JWT token

}

}

extension Data{

func aesEncrypt( keyData: Data, ivData: Data, operation: Int) -> Data {
    let dataLength = self.count
    let cryptLength  = size_t(dataLength + kCCBlockSizeAES128)
    var cryptData = Data(count:cryptLength)

    let keyLength = size_t(kCCKeySizeAES128)
    let options = CCOptions(kCCOptionPKCS7Padding)


    var numBytesEncrypted :size_t = 0

    let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
        self.withUnsafeBytes {dataBytes in
            ivData.withUnsafeBytes {ivBytes in
                keyData.withUnsafeBytes {keyBytes in
                    CCCrypt(CCOperation(operation),
                            CCAlgorithm(kCCAlgorithmAES),
                            options,
                            keyBytes, keyLength,
                            ivBytes,
                            dataBytes, dataLength,
                            cryptBytes, cryptLength,
                            &numBytesEncrypted)
                }
            }
        }
    }

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.removeSubrange(numBytesEncrypted..<cryptData.count)

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

    return cryptData;
}

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!