使用NSValueTransformer的iOS核心数据加密 [英] iOS Core Data encryption using NSValueTransformer

查看:60
本文介绍了使用NSValueTransformer的iOS核心数据加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Core Data和CommonCrypto加密数据.我正在尝试使用NSValueTransformer延迟加密和解密.

I'm experimenting with encrypting data with Core Data and CommonCrypto. I am trying to use a NSValueTransformer to lazily encrypt and decrypt.

但是,当我现在尝试将加密的数据保存到持久性存储协调器时,它会失败.每次我尝试将我的数据保存到数据库时,它都会给我:

However when I'm now trying save the encrypted data to the persistent store coordinator, it fails. Every time im trying to save my data to the database, it gives me:

-[__ NSCFString字节]:无法识别的选择器已发送到实例

-[__NSCFString bytes]: unrecognized selector sent to instance

我确定这是某种数据库和NSManagedObject不匹配,但我无法弄清楚.我觉得这可能很简单,但是找不到解决方案.我的代码:

I'm sure it's some sort of database and NSManagedObject mismatch, but I can't figure it out. I feel it's probably rather simple, but I can't find the solution. My code:

NSValueTransformer

class TryHardEncryption: NSValueTransformer {

override class func transformedValueClass() -> AnyClass {
    return NSString.self
}

override class func allowsReverseTransformation() -> Bool {
    return true
}


override func reverseTransformedValue(value: AnyObject?) -> AnyObject? {
    if let message = value as? NSString {
        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 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))");
            return base64cryptString
        } else {
            print("Error: \(cryptStatus)")
        }
    }
    return nil
}

override func transformedValue(value: AnyObject?) -> AnyObject? {
    if let message = value as? NSString {
        let keyString        = "12345678901234567890123456789012"
        let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let keyBytes         = UnsafePointer<UInt8>(keyData.bytes)
        print("keyLength   = \(keyData.length), keyData   = \(keyData)")

        let data: NSData! = message.dataUsingEncoding(NSUTF8StringEncoding) as NSData!
        let dataLength    = Int(data.length)
        let dataBytes     = UnsafePointer<UInt8>(data.bytes)
        print("dataLength  = \(dataLength), data      = \(data)")

        let cryptData    = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)!
        let cryptPointer = UnsafeMutablePointer<UInt8>(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(kCCOptionECBMode + kCCOptionPKCS7Padding)

        var numBytesEncrypted :size_t = 0

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

        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            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)")
            return NSString(string: base64cryptString) as NSObject

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

}

要使NSValueTransformer正常工作,我要做的是:

What I had to do to get the NSValueTransformer to work is:

let transformer: TryHardEncryption = TryHardEncryption()
    NSValueTransformer.setValueTransformer(transformer, forName: "TryHardEncryption")

没有上面的代码,从未调用过NSValueTransformer.

Without the above code, the NSValueTransformer was never called.

我已将数据库字段标记为Transformable类型,并将其命名为:TryHardEncryption.你们知道这是怎么回事吗?

I've marked the database field as the Transformable type and named it: TryHardEncryption. Do you guys know what is wrong here?

编辑它涉及的属性是:

@NSManaged var establishmentDescription: String?

当我调试它们时,加密和解密函数都返回一个字符串.

Both the encrypt and decrypt functions return a String when I debug them.

推荐答案

我终于弄明白了...我对非常对象必须是什么类型以及nsvaluetransformer必须返回什么类型感到困惑.我没有在nsvaluetransformer中将值强制转换为正确的类型,因此我在代码中返回nil.但是,它并没有以我很容易弄清楚的方式崩溃.其次,我将实体列改回了NSObject.在transformedValue方法中返回一个NSData对象,在reverseTransformedValue方法中返回一个NSString.实际上,这是我使其工作所需的全部.非常感谢你的帮助.确实是类型错误.

I finally figured it out... I was confused as to what type very object had to be and what my nsvaluetransformer had to return. I wasnt casting the value to the proper type in the nsvaluetransformer and thus I was returning nil in the code. However it wasnt crashing in a way that I would easily figure this out. Secondly I changed the entity column back to an NSObject. Returned an NSData object in the transformedValue method and a NSString in the reverseTransformedValue method. This was actually all i needed to make it work. Thanks a lot for your help. It indeed was a type error.

这篇关于使用NSValueTransformer的iOS核心数据加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆