objective-c - 在 Swift 中使用 CommonCrypto 进行解密

标签 objective-c swift cryptography commoncrypto

我正在为 StringNSData 使用 Swift-only crypt/decrypt Extension,以及crypt 部分基于@Zaph 在链接问题中提供的答案工作:Issue using CCCrypt (CommonCrypt) in Swift

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

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

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)")

任何帮助将不胜感激

最佳答案

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

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

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

这是我在“NSData+AESCrypt.m”中所做的更改,方法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() 语句,最好是数据和字符串的十六进制转储。根据需要进行比较和修复。

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

关于objective-c - 在 Swift 中使用 CommonCrypto 进行解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25776238/

相关文章:

iphone - NSFetchRequest 内存问题

ios - Swift 中的 UITableView 子类

ios - 在 Swift 中刷新 UITableView

java - Java 和 PHP 的简单解密/加密

python - 为什么 Fernet 加密 token 总是以相同的序列开头? (Python 密码学包)

objective-c - iOS中获取AVPlayer的音量

ios - 使用AWS IOS SDK验证用户身份

python - 无法为 Python 2.7.11 安装 openssl-devel

objective-c - 将 NSData 转换为十六进制 NSString

ios - 当我快速点击 1 个 UIButton 时停止所有 UIButtons 工作