iOS 使用 NSValueTransformer 的核心数据加密
iOS Core Data encryption using NSValueTransformer
我正在尝试使用 Core Data 和 CommonCrypto 加密数据。我正在尝试使用 NSValueTransformer 来延迟加密和解密。
但是,当我现在尝试将加密数据保存到持久性存储协调器时,它失败了。每次我试图将我的数据保存到数据库时,它都会给我:
-[__NSCFString bytes]: unrecognized selector sent to instance
我确定是某种数据库和 NSManagedObject 不匹配,但我无法弄清楚。我觉得这可能很简单,但我找不到解决方案。我的代码:
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 工作,我必须做的是:
let transformer: TryHardEncryption = TryHardEncryption()
NSValueTransformer.setValueTransformer(transformer, forName: "TryHardEncryption")
如果没有上面的代码,NSValueTransformer 就不会被调用。
我已将数据库字段标记为可转换类型并将其命名为:TryHardEncryption。你们知道这里出了什么问题吗?
编辑
它涉及的 属性 是:
@NSManaged var establishmentDescription: String?
加密和解密函数 return 当我调试它们时都是一个字符串。
我终于弄明白了...我对每个对象必须是什么类型以及我的 nsvaluetransformer 必须是什么感到困惑 return。我没有在 nsvaluetransformer 中将值转换为正确的类型,因此我在代码中 returning nil。然而,它并没有以我很容易弄清楚的方式崩溃。其次,我将实体列改回 NSObject。在 transformedValue 方法中返回一个 NSData 对象,在 reverseTransformedValue 方法中返回一个 NSString。这实际上是我需要让它工作的全部。非常感谢你的帮助。确实是类型错误。
为了帮助任何想要查看更正代码示例的人,请将问题中 transformedValue() 的 return 行替换为:
return base64cryptString.dataUsingEncoding(NSUTF8StringEncoding)
我正在尝试使用 Core Data 和 CommonCrypto 加密数据。我正在尝试使用 NSValueTransformer 来延迟加密和解密。
但是,当我现在尝试将加密数据保存到持久性存储协调器时,它失败了。每次我试图将我的数据保存到数据库时,它都会给我:
-[__NSCFString bytes]: unrecognized selector sent to instance
我确定是某种数据库和 NSManagedObject 不匹配,但我无法弄清楚。我觉得这可能很简单,但我找不到解决方案。我的代码:
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 工作,我必须做的是:
let transformer: TryHardEncryption = TryHardEncryption()
NSValueTransformer.setValueTransformer(transformer, forName: "TryHardEncryption")
如果没有上面的代码,NSValueTransformer 就不会被调用。
我已将数据库字段标记为可转换类型并将其命名为:TryHardEncryption。你们知道这里出了什么问题吗?
编辑 它涉及的 属性 是:
@NSManaged var establishmentDescription: String?
加密和解密函数 return 当我调试它们时都是一个字符串。
我终于弄明白了...我对每个对象必须是什么类型以及我的 nsvaluetransformer 必须是什么感到困惑 return。我没有在 nsvaluetransformer 中将值转换为正确的类型,因此我在代码中 returning nil。然而,它并没有以我很容易弄清楚的方式崩溃。其次,我将实体列改回 NSObject。在 transformedValue 方法中返回一个 NSData 对象,在 reverseTransformedValue 方法中返回一个 NSString。这实际上是我需要让它工作的全部。非常感谢你的帮助。确实是类型错误。
为了帮助任何想要查看更正代码示例的人,请将问题中 transformedValue() 的 return 行替换为:
return base64cryptString.dataUsingEncoding(NSUTF8StringEncoding)