AES快速encryption

我试图在swift中实现AESencryption。 Android和C#的encryption解密工作正常。 我需要快速实施它。 这是Android和C#的当前代码是由此。

我试图使用

  1. CryptoSwift
  2. 跨平台AESencryption

但是没有一个可行。 当我在服务器上发送encryption的string时,它不被解密。

任何帮助将不胜感激

一定要使用iv, PKCS5Padding (实际上是PKCS#7)填充和一个16字节(128位)密钥的CBC模式使用相同的参数。

PKCS#5填充和PKCS#7填充基本上是相同的,有时由于历史原因PKCS#5填充指定用于AES,但实际填充是PKCS#7。

确保密钥,iv和encryption数据的编码都匹配。 hex转储他们在两个平台,以确保他们是相同的。 encryptionfunction不难使用,如果所有的input参数都是正确的,输出将是正确的。

为了使这个更安全,iv应该是随机的字节,并且在解密期间用于encryption数据。

跨平台AESencryption使用256位密钥,因此不能按原样工作。

例:

Swift 2

 // operation: kCCEncrypt or kCCDecrypt func testCrypt(data data:[UInt8], keyData:[UInt8], ivData:[UInt8], operation:Int) -> [UInt8]? { let cryptLength = size_t(data.count+kCCBlockSizeAES128) var cryptData = [UInt8](count:cryptLength, repeatedValue:0) let keyLength = size_t(kCCKeySizeAES128) let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128) let options: CCOptions = UInt32(kCCOptionPKCS7Padding) var numBytesEncrypted :size_t = 0 let cryptStatus = CCCrypt(CCOperation(operation), algoritm, options, keyData, keyLength, ivData, data, data.count, &cryptData, cryptLength, &numBytesEncrypted) if UInt32(cryptStatus) == UInt32(kCCSuccess) { cryptData.removeRange(numBytesEncrypted..<cryptData.count) } else { print("Error: \(cryptStatus)") } return cryptData; } let message = "Don´t try to read this text. Top Secret Stuff" let messageData = Array(message.utf8) let keyData = Array("12345678901234567890123456789012".utf8) let ivData = Array("abcdefghijklmnop".utf8) let encryptedData = testCrypt(data:messageData, keyData:keyData, ivData:ivData, operation:kCCEncrypt)! let decryptedData = testCrypt(data:encryptedData, keyData:keyData, ivData:ivData, operation:kCCDecrypt)! var decrypted = String(bytes:decryptedData, encoding:NSUTF8StringEncoding)! print("message: \(message)"); print("messageData: \(NSData(bytes:messageData, length:messageData.count))"); print("keyData: \(NSData(bytes:keyData, length:keyData.count))"); print("ivData: \(NSData(bytes:ivData, length:ivData.count))"); print("encryptedData: \(NSData(bytes:encryptedData, length:encryptedData.count))"); print("decryptedData: \(NSData(bytes:decryptedData, length:decryptedData.count))"); print("decrypted: \(String(bytes:decryptedData,encoding:NSUTF8StringEncoding)!)"); 

输出:

消息:不要尝试阅读这个文本。 最高机密的东西  
 messageData:446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666  
 keyData:31323334 35363738 39303132 33343536 37383930 31323334 35363738 39303132  
 ivData:61626364 65666768 696a6b6c 6d6e6f70  
 encryptedData:b1b6dc17 62eaf3f8 baa1cb87 21ddc35c dee803ed fb320020 85794848 21206943 a85feb5b c8ee58fc d6fb664b 96b81114  
解密数据:446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666  
解密:不要尝试阅读这个文本。 最高机密的东西  

Swift 3与[UInt8]types

 func testCrypt(data:[UInt8], keyData:[UInt8], ivData:[UInt8], operation:Int) -> [UInt8]? { let cryptLength = size_t(data.count+kCCBlockSizeAES128) var cryptData = [UInt8](repeating:0, count:cryptLength) let keyLength = size_t(kCCKeySizeAES128) let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128) let options: CCOptions = UInt32(kCCOptionPKCS7Padding) var numBytesEncrypted :size_t = 0 let cryptStatus = CCCrypt(CCOperation(operation), algoritm, options, keyData, keyLength, ivData, data, data.count, &cryptData, cryptLength, &numBytesEncrypted) if UInt32(cryptStatus) == UInt32(kCCSuccess) { cryptData.removeSubrange(numBytesEncrypted..<cryptData.count) } else { print("Error: \(cryptStatus)") } return cryptData; } 

Swift 3与Datatypes

 func testCrypt(data:Data, keyData:Data, ivData:Data, operation:Int) -> Data { let cryptLength = size_t(data.count + 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 data.withUnsafeBytes {dataBytes in ivData.withUnsafeBytes {ivBytes in keyData.withUnsafeBytes {keyBytes in CCCrypt(CCOperation(operation), CCAlgorithm(kCCAlgorithmAES), options, keyBytes, keyLength, ivBytes, dataBytes, data.count, cryptBytes, cryptLength, &numBytesEncrypted) } } } } if UInt32(cryptStatus) == UInt32(kCCSuccess) { cryptData.removeSubrange(numBytesEncrypted..<cryptData.count) } else { print("Error: \(cryptStatus)") } return cryptData; } let message = "Don´t try to read this text. Top Secret Stuff" let messageData = message.data(using:String.Encoding.utf8)! let keyData = "12345678901234567890123456789012".data(using:String.Encoding.utf8)! let ivData = "abcdefghijklmnop".data(using:String.Encoding.utf8)! let encryptedData = testCrypt(data:messageData, keyData:keyData, ivData:ivData, operation:kCCEncrypt) let decryptedData = testCrypt(data:encryptedData, keyData:keyData, ivData:ivData, operation:kCCDecrypt) var decrypted = String(bytes:decryptedData, encoding:String.Encoding.utf8)! 

来自日落文件部分的示例:

CBC模式下的AESencryption随机IV(Swift 3+)

iv是encryption数据的前缀

aesCBC128Encrypt将创build一个随机的IV,并以encryption的代码为前缀。
aesCBC128Decrypt将在解密期间使用前缀IV。

input是数据,关键是数据对象。 如果需要,如Base64等编码forms转换为和/或从调用方法。

密钥的长度应该是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; } 

用法示例:

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

输出示例:

 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> 

笔记:
CBC模式示例代码的一个典型问题是它将随机IV的创build和共享留给用户。 这个例子包括IV的生成,在encryption的数据前加前缀,并且在解密期间使用前缀IV。 这使得临时用户从CBC模式所需的细节中解放出来。

为了安全,encryption的数据也应该具有authentication,这个示例代码没有规定为了小而且允许其他平台更好的互操作性。

另外还缺less密钥的密钥推导,build议使用PBKDF2是将文本密码用作密钥材料。

要获得稳健的生产就绪多平台encryption代码,请参阅RNCryptor 。

我的两分钱:

swift 4 / xcode 9扩展数据:

 extension Data{ 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; } } func testAES() -> Bool { let message = "secret message" let key = "key890123456" let ivString = "abcdefghijklmnop" // 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 encryptedData = messageData.aesEncrypt( keyData:keyData, ivData:ivData, operation:kCCEncrypt) let decryptedData = encryptedData.aesEncrypt( keyData:keyData, ivData:ivData, operation:kCCDecrypt) let decrypted = String(bytes:decryptedData, encoding:String.Encoding.utf8)! return message == decrypted } 

find一个名为RNCryptor的快速语言实现的AESencryption/解密库。

安装可以用Cocoapods或Carthage完成。 以下是encryption和解密的示例代码。

 // Encryption let data = "sample data string".data(using: String.Encoding.utf8) let password = "Secret password" let encryptedData = RNCryptor.encrypt(data: data, withPassword: password) // Decryption do { let originalData = try RNCryptor.decrypt(data: encryptedData, withPassword: password) // ... } catch { print(error) }