4

我正在为 and 进行crypt/decrypt 工作,Swift-onlycrypt部分的工作基于@Zaph 在链接问题中提供的答案:Issue using CCCrypt (CommonCrypt) in SwiftExtensionStringNSData

crypt 输出是使用 Objective-C 中良好的旧 NSData+AESCrypt.m 类别测试的

我一直在处理解密部分的问题:代码编译并运行良好,但结果不是最初加密的预期文本。

extension NSData {
    func AES256EncryptDataWithKey(key: String) -> NSData {
        let keyData: NSData! = (key as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let keyBytes         = UnsafePointer<UInt8>(keyData.bytes)
        let keyLength        = size_t(kCCKeySizeAES256)
        let dataLength    = UInt(self.length)
        let dataBytes     = UnsafePointer<UInt8>(self.bytes)
        let bufferData    = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
        var bufferPointer = UnsafeMutablePointer<UInt8>(bufferData.mutableBytes)
        let bufferLength  = size_t(bufferData.length)
        let operation: CCOperation = UInt32(kCCEncrypt)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
        let options:   CCOptions   = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
        var numBytesEncrypted: UInt = 0
        var cryptStatus = CCCrypt(operation,
            algoritm,
            options,
            keyBytes, keyLength,
            nil,
            dataBytes, dataLength,
            bufferPointer, bufferLength,
            &numBytesEncrypted)
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            bufferData.length = Int(numBytesEncrypted) // Requiered to adjust buffer size
            return bufferData as NSData
        } else {
            println("Error: \(cryptStatus)")
            return NSData()
        }
    }

    func AES256DecryptDataWithKey(key: String) -> NSData {
        let keyData: NSData! = (key as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let keyBytes         = UnsafePointer<UInt8>(keyData.bytes)
        let keyLength        = size_t(kCCKeySizeAES256)
        let dataLength    = UInt(self.length)
        let dataBytes     = UnsafePointer<UInt8>(self.bytes)
        let string = self.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
        let bufferData    = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
        var bufferPointer = UnsafeMutablePointer<UInt8>(bufferData.mutableBytes)
        let bufferLength  = size_t(bufferData.length)
        let operation: CCOperation = UInt32(kCCDecrypt)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
        let options:   CCOptions   = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
        var numBytesDecrypted: UInt = 0
        var cryptStatus = CCCrypt(operation,
            algoritm,
            options,
            keyBytes, keyLength,
            nil,
            dataBytes, dataLength,
            bufferPointer, bufferLength,
            &numBytesDecrypted)            
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            bufferData.length = Int(numBytesDecrypted) // Requiered to adjust buffer size
            return bufferData as NSData
        } else {
            println("Error: \(cryptStatus)")
            return NSData()
        }
    }
}

extension String {        
    func AES256EncryptStringWithKey(key: String) -> String {
        let data = (self as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let encryptedData = data.AES256EncryptDataWithKey(key)
        // Not all data is a UTF-8 string so Base64 is used
        let base64cryptString = encryptedData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
        return base64cryptString
    }

    func AES256DecryptStringWithKey(key: String) -> String {
        let data: NSData! = (self as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let decryptedData = data.AES256DecryptDataWithKey(key)            
        // Not all data is a UTF-8 string so Base64 is used
        let base64decryptString = decryptedData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
        return base64decryptString
    }
}

如您所见,String.encryptStringWithKey()调用NSData.encryptDataWithKey(). 所以扩展适用于两种类型StringNSData

    let string: String = "Don´t try to read this text. Top Secret Stuff"
    let key = "12345678901234567890123456789012"
    println("Original String  : \(string)");
    let encryptedString = string.AES256EncryptStringWithKey(key)
    println("Encrypted String : \(encryptedString)")        
    let decryptedString = encryptedString.AES256DecryptStringWithKey(key)
    println("Decrypted String: \(decryptedString)")

任何帮助将不胜感激

4

3 回答 3

3

不同之处在于 NSData+AESCrypt.m 使用 CBC 模式(默认),iv 为 NULL。问题中的代码使用 ECB 模式。

最佳实践是使用带有随机 iv 的 CBC 模式。iv 通常预先添加到加密数据,因此解密可以在解密之前将 iv 和数据分开。

不要使用NSData+AESCrypt.m,它没有维护,是NSData上的一个类,不支持ARC。考虑用于 Objective-C 的RNCryptor,它被积极维护。

这是我在 "NSData+AESCrypt.m", method 中所做的更改AES256EncryptWithKey: kCCOptionPKCS7Padding + kCCOptionECBMode。我补充说kCCOptionECBMode,仅此而已。

这是我打的电话: 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);

输出:

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

这与上面的代码相同(与上一个问题相同):

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

只需让所有输入都相同:操作、算法、选项、keyBytes、keyLength、dataBytes、dataLength 和 iv(如果非 ECB 模式)。CCCrypt只是一个函数调用,仅此而已。输入相同的输入,得到相同的输出。

放入NSLog()语句,最好是数据和字符串的十六进制转储。根据需要进行比较和修复。

信不信由你,这是电子安全的简单部分。

于 2014-09-11T01:32:32.990 回答
1

Swift 2.0 AES128 加密和解密。

应将以下标头导入 Obj-c 桥标头才能工作

#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)")
        }
    }
于 2015-08-11T06:01:19.490 回答
-1

Swift4 AES128 解密和 JWT

注意:如果在加密纯文本时将 iv 与 key 一起使用,在解密时不要使用它,您的问题将得到解决。 密钥和 iv长度为 16 位

下面的解密代码可能会对您有所帮助:这里用于解密的加密字符串是base64Encoded,我们得到的解密字符串是 JWT(Json Web Token)。

要配置 CommonCrypto,请参考链接: 如何在 SWIFT3 中使用 CommonCrypto?

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

导入 UIKit 导入 CommonCrypto

类视图控制器: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

}

}

扩展数据{

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;
}

}

于 2018-08-11T14:10:56.230 回答