eha*_*ro2 11 cryptography objective-c ios commoncrypto swift
我正在将一个有效的Objective-C类别(NSData + AESCrypt.m)移植到Swift,我发现了一个与指针一起工作的问题.Swift中加密部分的代码正确编译,但生成运行时EXEC_BAD_ACCES错误.
我到目前为止的代码是(我试图尽可能地剖析代码):
let key = "123456789012345678901234567890120"
let keyLength = UInt(kCCKeySizeAES256 + 1)
let keyPointer = strdup(key) // Convert key to <UnsafeMutablePointer<Int8>
let message = "Don´t try to read this text. Top Secret Stuff"
let data = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding)
let dataBytes = data?.bytes
let length = data?.length
let dataLength = UInt(length!)
let dataPointer = UnsafePointer<UInt8>(dataBytes!)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
let cryptBufferSize = UInt(dataLength + kCCBlockSizeAES128)
var cryptBuffer = [UInt8](count: Int(cryptBufferSize), repeatedValue: 0)
var cryptBufferPointer = UnsafeMutablePointer<UInt8>(cryptBuffer)
var numBytesEncrypted = UnsafeMutablePointer<UInt>()
var cryptStatus = CCCrypt(operation, algoritm, options, keyPointer, keyLength, nil, dataPointer, dataLength, cryptBufferPointer, cryptBufferSize, numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
let size = NSInteger(cryptBufferSize)
let encryptedData = NSData(bytes: cryptBufferPointer, length: size)
let encryptedString = NSString(data: encryptedData, encoding: NSUTF8StringEncoding)
println("Encrypted String = \(encryptedString)") // EXEC_BAD_ACCESS error
} else {
println("Error: \(cryptStatus)")
}
Run Code Online (Sandbox Code Playgroud)
encryptedData对象显示以下信息:
<279c2d0f d3ce2200 0dc10cc1 9df46e76 cb26f423 7c9bde76 f9d8d0e2 632acef9 74fb0614 4717422b 684d1889 e3ce882c 00000000 00000000 00000000 0000>
Run Code Online (Sandbox Code Playgroud)
但encryptedString显示0x0000000000在调试器中,并尝试println()生成EXEC_BAD_ACCESS错误
知道缺少什么吗?
RGDS ....
zap*_*aph 22
Swift 2.0
下面是一个示例
如果这不是所需要的,那么方法应该是一个很好的示例
注意:键字符串将转换为数据
将Security.framework
添加#import <CommonCrypto/CommonCryptor.h>到项目添加到桥接标头.
let keyString = "12345678901234567890123456789012"
let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
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!
print("data length = \(data.length), data = \(data)")
let cryptData = NSMutableData(length: Int(data.length) + kCCBlockSizeAES128)!
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
var cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
nil,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&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)")
} else {
print("Error: \(cryptStatus)")
}
Run Code Online (Sandbox Code Playgroud)
输出:
keyLength = 32, keyData = <31323334 35363738 39303132 33343536 37383930 31323334 35363738 39303132>
dataLength = 46, data = <446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666>
cryptLength = 48, cryptData = <118a32dc c23f7caa 883abc3c 1c7f0770 e200016b 2737acfa 17bb96fb a02b02a7 c147603b 06acd863 94bb8ff2 6cb14515>
base64cryptString = EYoy3MI/fKqIOrw8HH8HcOIAAWsnN6z6F7uW+6ArAqfBR2A7BqzYY5S7j/JssUUV
Run Code Online (Sandbox Code Playgroud)
斯威夫特3
iv以加密数据为前缀
aesCBC128Encrypt将创建一个随机IV并加密前缀为加密代码.
aesCBC128Decrypt将在解密期间使用前缀IV.
输入是数据,键是数据对象.如果需要的编码形式(如Base64)在调用方法中转换为和/或来自.
密钥长度应精确为128位(16字节),192位(24字节)或256位(32字节).如果使用其他密钥大小,则会引发错误.
PKCS#7填充默认设置.
此示例需要Common Crypto
.必须为项目提供桥接标头:
#import <CommonCrypto/CommonCrypto.h>
添加Security.framework到项目中.
这是示例,而不是生产代码.
enum AESError: Error {
case KeyError((String, Int))
case IVError((String, Int))
case CryptorError((String, Int))
}
// The iv is prefixed to the encrypted data
func aesCBCEncrypt(data:Data, keyData:Data) throws -> Data {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if (validKeyLengths.contains(keyLength) == false) {
throw AESError.KeyError(("Invalid key length", keyLength))
}
let ivSize = kCCBlockSizeAES128;
let cryptLength = size_t(ivSize + data.count + kCCBlockSizeAES128)
var cryptData = Data(count:cryptLength)
let status = cryptData.withUnsafeMutableBytes {ivBytes in
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes)
}
if (status != 0) {
throw AESError.IVError(("IV generation failed", Int(status)))
}
var numBytesEncrypted :size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
options,
keyBytes, keyLength,
cryptBytes,
dataBytes, data.count,
cryptBytes+kCCBlockSizeAES128, cryptLength,
&numBytesEncrypted)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.count = numBytesEncrypted + ivSize
}
else {
throw AESError.CryptorError(("Encryption failed", Int(cryptStatus)))
}
return cryptData;
}
// The iv is prefixed to the encrypted data
func aesCBCDecrypt(data:Data, keyData:Data) throws -> Data? {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if (validKeyLengths.contains(keyLength) == false) {
throw AESError.KeyError(("Invalid key length", keyLength))
}
let ivSize = kCCBlockSizeAES128;
let clearLength = size_t(data.count - ivSize)
var clearData = Data(count:clearLength)
var numBytesDecrypted :size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytes, keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128, clearLength,
cryptBytes, clearLength,
&numBytesDecrypted)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
clearData.count = numBytesDecrypted
}
else {
throw AESError.CryptorError(("Decryption failed", Int(cryptStatus)))
}
return clearData;
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
let clearData = "clearData0123456".data(using:String.Encoding.utf8)!
let keyData = "keyData890123456".data(using:String.Encoding.utf8)!
print("clearData: \(clearData as NSData)")
print("keyData: \(keyData as NSData)")
var cryptData :Data?
do {
cryptData = try aesCBCEncrypt(data:clearData, keyData:keyData)
print("cryptData: \(cryptData! as NSData)")
}
catch (let status) {
print("Error aesCBCEncrypt: \(status)")
}
let decryptData :Data?
do {
let decryptData = try aesCBCDecrypt(data:cryptData!, keyData:keyData)
print("decryptData: \(decryptData! as NSData)")
}
catch (let status) {
print("Error aesCBCDecrypt: \(status)")
}
Run Code Online (Sandbox Code Playgroud)
示例输出:
clearData: <636c6561 72446174 61303132 33343536>
keyData: <6b657944 61746138 39303132 33343536>
cryptData: <92c57393 f454d959 5a4d158f 6e1cd3e7 77986ee9 b2970f49 2bafcf1a 8ee9d51a bde49c31 d7780256 71837a61 60fa4be0>
decryptData: <636c6561 72446174 61303132 33343536>
Run Code Online (Sandbox Code Playgroud)
笔记:
CBC模式示例代码的一个典型问题是它将随机IV的创建和共享留给用户.此示例包括生成IV,加密数据前缀并在解密期间使用前缀IV.这使临时用户免于CBC模式所需的细节.
为了安全起见,加密数据也应该具有身份验证,此示例代码不提供为了小,并允许其他平台更好的互操作性.
还缺少密钥的密钥派生密钥,建议使用PBKDF2是文本密码用作密钥材料.
对于强大的生产准备好的多平台加密代码,请参阅RNCryptor.
kar*_*agu 10
Swift 2.0加密和解密.刚刚更新了上面的答案以支持Swift 2.0.
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)")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13794 次 |
| 最近记录: |