我通过swift编写应用程序,我需要AES加密和解密功能,我从另一个.Net解决方案接收加密数据,但我找不到要做的事情。
这是我的.net加密:
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
我需要在swift中解密函数。
答案 0 :(得分:30)
CryptoSwift Example
已更新至Swift 2
import Foundation
import CryptoSwift
extension String {
func aesEncrypt(key: String, iv: String) throws -> String{
let data = self.dataUsingEncoding(NSUTF8StringEncoding)
let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes(), padding: PKCS7())
let encData = NSData(bytes: enc, length: Int(enc.count))
let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
let result = String(base64String)
return result
}
func aesDecrypt(key: String, iv: String) throws -> String {
let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
let dec = try AES(key: key, iv: iv, blockMode:.CBC).decrypt(data!.arrayOfBytes(), padding: PKCS7())
let decData = NSData(bytes: dec, length: Int(dec.count))
let result = NSString(data: decData, encoding: NSUTF8StringEncoding)
return String(result!)
}
}
用法:
let key = "bbC2H19lkVbQDfakxcrtNMQdd0FloLyw" // length == 32
let iv = "gqLOHUioQ0QjhuvI" // length == 16
let s = "string to encrypt"
let enc = try! s.aesEncrypt(key, iv: iv)
let dec = try! enc.aesDecrypt(key, iv: iv)
print(s) // string to encrypt
print("enc:\(enc)") // 2r0+KirTTegQfF4wI8rws0LuV8h82rHyyYz7xBpXIpM=
print("dec:\(dec)") // string to encrypt
print("\(s == dec)") // true
确保你有正确长度的iv(16)和键(32)然后你不会点击“块大小和初始化向量必须是相同的长度!”错误。
答案 1 :(得分:24)
CryptoSwift Example
更新了 SWIFT 4。*
func aesEncrypt() throws -> String {
let encrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).encrypt([UInt8](self.data(using: .utf8)!))
return Data(encrypted).base64EncodedString()
}
func aesDecrypt() throws -> String {
guard let data = Data(base64Encoded: self) else { return "" }
let decrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).decrypt([UInt8](data))
return String(bytes: decrypted, encoding: .utf8) ?? self
}
答案 2 :(得分:9)
Code provided by SHS didn't work for me, but this one apparently did (I used a Bridging Header: #import <CommonCrypto/CommonCrypto.h>
):
extension String {
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
}
From my ViewController
:
let encoded = message.aesEncrypt(key: keyString, iv: iv)
let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
答案 3 :(得分:6)
有一个有趣的“纯粹 - 快速”开源库:
CryptoSwift:https://github.com/krzyzanowskim/CryptoSwift
支持:AES-128,AES-192,AES-256,ChaCha20
AES解密示例(从项目README.md文件获取):
import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = Cipher.AES(setup).decrypt(encryptedData)
答案 4 :(得分:4)
我使用CommonCrypto通过Easy to use Swift implementation of CommonCrypto HMAC的MihaelIsaev / HMAC.swift代码生成Hash。此实现不使用Bridging-Header,而是创建Module文件。
现在使用AESEncrypt和Decrypt,我直接在HAMC.swift中的“extension String {”中添加了函数。
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
data = self.dataUsingEncoding(NSUTF8StringEncoding),
cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
data = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters),
cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData, encoding:NSUTF8StringEncoding)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
这些功能取自RNCryptor。它是哈希函数和单个文件“HMAC.swift”中的一个简单添加,不使用Bridging-header。我希望这对于快速需要Hashing和AES加密/解密的开发人员非常有用。
使用AESDecrypt的示例。
let iv = "AA-salt-BBCCDD--" // should be of 16 characters.
//here we are convert nsdata to String
let encryptedString = String(data: dataFromURL, encoding: NSUTF8StringEncoding)
//now we are decrypting
if let decryptedString = encryptedString?.aesDecrypt("12345678901234567890123456789012", iv: iv) // 32 char pass key
{
// Your decryptedString
}
答案 5 :(得分:3)
CryptoSwift是一个非常有趣的项目,但目前它有一些AES速度限制。如果你需要做一些严肃的加密,请小心 - 可能值得经历桥接实现CommonCrypto的痛苦。
Bigcin to Marcin for pureSwift实现
答案 6 :(得分:1)
您可以将iOS的CommonCrypto或CryptoSwift用作外部库。下面有两种工具的实现。就是说,应该对带有AES的CommonCrypto输出进行测试,因为在CC文档中尚不清楚它使用哪种AES模式。
Swift 4.2中的CommonCrypto
import CommonCrypto func encrypt(data: Data) -> Data { return cryptCC(data: data, key: key, operation: kCCEncrypt) } func decrypt(data: Data) -> Data { return cryptCC(data: data, key: key, operation: kCCDecrypt) } private func cryptCC(data: Data, key: String operation: Int) -> Data { guard key.count == kCCKeySizeAES128 else { fatalError("Key size failed!") } var ivBytes: [UInt8] var inBytes: [UInt8] var outLength: Int if operation == kCCEncrypt { ivBytes = [UInt8](repeating: 0, count: kCCBlockSizeAES128) guard kCCSuccess == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else { fatalError("IV creation failed!") } inBytes = Array(data) outLength = data.count + kCCBlockSizeAES128 } else { ivBytes = Array(Array(data).dropLast(data.count - kCCBlockSizeAES128)) inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128)) outLength = inBytes.count } var outBytes = [UInt8](repeating: 0, count: outLength) var bytesMutated = 0 guard kCCSuccess == CCCrypt(CCOperation(operation), CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), Array(key), kCCKeySizeAES128, &ivBytes, &inBytes, inBytes.count, &outBytes, outLength, &bytesMutated) else { fatalError("Cryptography operation \(operation) failed") } var outData = Data(bytes: &outBytes, count: bytesMutated) if operation == kCCEncrypt { ivBytes.append(contentsOf: Array(outData)) outData = Data(bytes: ivBytes) } return outData }
Swift 4.2中的CryptoSwift v0.14
enum Operation { case encrypt case decrypt } private let keySizeAES128 = 16 private let aesBlockSize = 16 func encrypt(data: Data, key: String) -> Data { return crypt(data: data, key: key, operation: .encrypt) } func decrypt(data: Data, key: String) -> Data { return crypt(data: data, key: key, operation: .decrypt) } private func crypt(data: Data, key: String, operation: Operation) -> Data { guard key.count == keySizeAES128 else { fatalError("Key size failed!") } var outData: Data? = nil if operation == .encrypt { var ivBytes = [UInt8](repeating: 0, count: aesBlockSize) guard 0 == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else { fatalError("IV creation failed!") } do { let aes = try AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes)) let encrypted = try aes.encrypt(Array(data)) ivBytes.append(contentsOf: encrypted) outData = Data(bytes: ivBytes) } catch { print("Encryption error: \(error)") } } else { let ivBytes = Array(Array(data).dropLast(data.count - aesBlockSize)) let inBytes = Array(Array(data).dropFirst(aesBlockSize)) do { let aes = try AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes)) let decrypted = try aes.decrypt(inBytes) outData = Data(bytes: decrypted) } catch { print("Decryption error: \(error)") } } return outData! }
答案 7 :(得分:0)
我找到了解决方案,它是一个很好的库。
跨平台256位AES加密/解密。
该项目包含256位AES加密的实现,适用于所有平台(C#,iOS,Android)。其中一个关键目标是通过简单的实现使AES在所有平台上运行。
平台支持: iOS, Android, Windows(C#)。
答案 8 :(得分:0)
您只需 复制并粘贴 这些方法(Swift 4 +):
class func encryptMessage(message: String, encryptionKey: String, iv: String) -> String? {
if let aes = try? AES(key: encryptionKey, iv: iv),
let encrypted = try? aes.encrypt(Array<UInt8>(message.utf8)) {
return encrypted.toHexString()
}
return nil
}
class func decryptMessage(encryptedMessage: String, encryptionKey: String, iv: String) -> String? {
if let aes = try? AES(key: encryptionKey, iv: iv),
let decrypted = try? aes.decrypt(Array<UInt8>(hex: encryptedMessage)) {
return String(data: Data(bytes: decrypted), encoding: .utf8)
}
return nil
}
示例:
let encryptMessage = encryptMessage(message: "Hello World!", encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of encryptMessage is: 649849a5e700d540f72c4429498bf9f4
let decryptedMessage = decryptMessage(encryptedMessage: encryptMessage, encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of decryptedMessage is: Hello World!
别忘了加密密钥和iv应该是16个字节。
答案 9 :(得分:0)
更新Swift 4.2
例如,在这里,我们将字符串加密为base64编码的字符串。然后,我们将其解密为可读的字符串。 (这与我们的输入字符串相同)。
就我而言,我使用它来加密字符串并将其嵌入QR码。然后,另一方对此进行扫描并解密。因此,中级将无法理解QR码。
步骤1:加密字符串“加密我的消息123”
第2步:加密的base64编码的字符串:+ yvNjiD7F9 / JKmqHTc / Mjg ==(在QR码上打印相同)
步骤3:扫描并解密字符串“ + yvNjiD7F9 / JKmqHTc / Mjg ==”
步骤4::最终结果-“加密我的消息123”
加密和解密功能
func encryption(stringToEncrypt: String) -> String{
let key = "MySecretPKey"
//let iv = "92c9d2c07a9f2e0a"
let data = stringToEncrypt.data(using: .utf8)
let keyD = key.data(using: .utf8)
let encr = (data as NSData?)!.aes128EncryptedData(withKey: keyD)
let base64String: String = (encr as NSData?)!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(base64String)
return base64String
}
func decryption(encryptedString:String) -> String{
let key = "MySecretPKey"
//let iv = "92c9d2c07a9f2e0a"
let keyD = key.data(using: .utf8)
let decrpStr = NSData(base64Encoded: encryptedString, options: NSData.Base64DecodingOptions(rawValue: 0))
let dec = (decrpStr)!.aes128DecryptedData(withKey: keyD)
let backToString = String(data: dec!, encoding: String.Encoding.utf8)
print(backToString!)
return backToString!
}
用法:
let enc = encryption(stringToEncrypt: "Encrypt My Message 123")
let decryptedString = decryption(encryptedString: enc)
print(decryptedString)
用于支持AES加密功能的类用Objective-C编写。因此,为快速起见,您需要使用桥头来支持这些。
类名称:NSData + AES.h
#import <Foundation/Foundation.h>
@interface NSData (AES)
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key;
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
@end
类名称:NSData + AES.m
#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (AES)
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key
{
return [self AES128EncryptedDataWithKey:key iv:nil];
}
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key
{
return [self AES128DecryptedDataWithKey:key iv:nil];
}
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
return [self AES128Operation:kCCEncrypt key:key iv:iv];
}
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
return [self AES128Operation:kCCDecrypt key:key iv:iv];
}
- (NSData *)AES128Operation:(CCOperation)operation key:(NSData *)key iv:(NSData *)iv
{
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
key.bytes,
kCCBlockSizeAES128,
iv.bytes,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
@end
我希望有帮助。
谢谢!
答案 10 :(得分:0)
Swift4:
let key = "ccC2H19lDDbQDfakxcrtNMQdd0FloLGG" // length == 32
let iv = "ggGGHUiDD0Qjhuvv" // length == 16
func encryptFile(_ path: URL) -> Bool{
do{
let data = try Data.init(contentsOf: path)
let encodedData = try data.aesEncrypt(key: key, iv: iv)
try encodedData.write(to: path)
return true
}catch{
return false
}
}
func decryptFile(_ path: URL) -> Bool{
do{
let data = try Data.init(contentsOf: path)
let decodedData = try data.aesDecrypt(key: key, iv: iv)
try decodedData.write(to: path)
return true
}catch{
return false
}
}
** Pod安装Crypto Swift ** 1. pod'CryptoSwift'#添加到PodFile 2. Pod安装
import CryptoSwift
extension Data {
func aesEncrypt(key: String, iv: String) throws -> Data{
let encypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).encrypt(self.bytes)
return Data(bytes: encypted)
}
func aesDecrypt(key: String, iv: String) throws -> Data {
let decrypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).decrypt(self.bytes)
return Data(bytes: decrypted)
}
}
答案 11 :(得分:0)
尝试下面的代码为我工作。
AES加密
public static String getEncryptedString(String value) {
try {
byte[] key = your Key in byte array;
byte[] input = sault in byte array
return Base64.encodeToString(encrypt(value.getBytes("UTF-8"), key, input), Base64.DEFAULT);
} catch (UnsupportedEncodingException e) {
return "";
}
}
public static byte[] encrypt(byte[] data, byte[] key, byte[] ivs) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] finalIvs = new byte[16];
int len = ivs.length > 16 ? 16 : ivs.length;
System.arraycopy(ivs, 0, finalIvs, 0, len);
IvParameterSpec ivps = new IvParameterSpec(finalIvs);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivps);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
AES解密
public static String decrypt(String encrypted) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
byte[] key = your Key in byte array;
byte[] input = sault in byte array
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(input);
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] raw = Base64.decode(encrypted, Base64.DEFAULT);
byte[] originalBytes = ecipher.doFinal(raw);
String original = new String(originalBytes, "UTF8");
return original;
}
答案 12 :(得分:0)
这是一篇很老的文章,但是 XCode 10 添加了CommonCrypto模块,因此您不需要模块映射。同样使用 Swift 5 ,也无需进行烦人的投射。
您可以执行以下操作:
func decrypt(_ data: Data, iv: Data, key: Data) throws -> String {
var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128)
var bufferLen: Int = 0
let status = CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
[UInt8](key),
kCCBlockSizeAES128,
[UInt8](iv),
[UInt8](data),
data.count,
&buffer,
buffer.count,
&bufferLen
)
guard status == kCCSuccess,
let str = String(data: Data(bytes: buffer, count: bufferLen),
encoding: .utf8) else {
throw NSError(domain: "AES", code: -1, userInfo: nil)
}
return str
}