首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Swift中使用CommonCrypto进行解密

在Swift中使用CommonCrypto进行解密
EN

Stack Overflow用户
提问于 2014-09-10 22:41:22
回答 3查看 4.5K关注 0票数 4

我正在为Swift-onlyNSData工作一个加密/解密Extension,而密码部分是基于@Zaph在链接问题:在Swift中使用CCCrypt (CommonCrypt)中提供的答案工作的。

使用目标C中的好的旧NSData+AESCrypt.m类别测试了隐窝输出。

我一直在处理解密部分中的一个问题:代码编译和运行良好,但结果不是原来加密的文本。

代码语言:javascript
运行
复制
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两种类型。

代码语言:javascript
运行
复制
    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)")

如有任何帮助,将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-11 01:32:32

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

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

不使用NSData+AESCrypt.m,它没有被维护,是NSData上的一个类别,不支持ARC。考虑到目标C的RNCryptor,它是积极维护的。

这是我在"NSData+AESCrypt.m“方法AES256EncryptWithKey: kCCOptionPKCS7Padding + kCCOptionECBMode中所做的更改。我加了kCCOptionECBMode,仅此而已。

下面是我打的电话: NSString *keyString = @"12345678901234567890123456789012";

代码语言:javascript
运行
复制
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);

输出:

代码语言:javascript
运行
复制
crypData: <118a32dc c23f7caa 883abc3c 1c7f0770 e200016b 2737acfa 17bb96fb a02b02a7 c147603b 06acd863 94bb8ff2 6cb14515>

与上述代码相同(与上一个问题相同):

代码语言:javascript
运行
复制
cryptData = <118a32dc c23f7caa 883abc3c 1c7f0770 e200016b 2737acfa 17bb96fb a02b02a7 c147603b 06acd863 94bb8ff2 6cb14515>

这只是一个得到所有输入相同的问题:操作、算法、选项、keyBytes、keyLength、dataBytes、dataLength和iv (如果不是欧洲央行模式)。CCCrypt只是一个函数调用,仅此而已。输入相同的输入,得到相同的输出。

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

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

票数 4
EN

Stack Overflow用户

发布于 2015-08-11 06:01:19

SWIFT2.0 AES128加密和解密。

应该将下面的头导入到Obj-c桥头中才能工作

代码语言:javascript
运行
复制
#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)")
        }
    }
票数 1
EN

Stack Overflow用户

发布于 2018-08-11 14:10:56

Swift4 AES128解密与JWT

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

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

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

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

导入UIKit导入CommonCrypto

类ViewController: UIViewController {

代码语言:javascript
运行
复制
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

}

}

扩展数据{

代码语言:javascript
运行
复制
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;
}

}

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25776238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档