我通过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中解密函数。
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)和key(32)长度然后你不会点击“块大小和初始化向量必须是相同的长度!”错误。
你可以复制并粘贴这些方法(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!
不要忘记encryptionKey&iv应该是16个字节。
更新Swift 4.2
例如,我们将字符串加密为base64encoded字符串。然后我们将其解密为可读字符串。 (这与我们的输入字符串相同)。
在我的例子中,我使用它来加密字符串并将其嵌入到QR码中。然后另一方扫描并解密它。所以中间人不会理解二维码。
第1步:加密字符串“加密我的消息123”
第2步:加密的base64Encoded字符串:+ 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编写的。所以对于swift,你需要使用桥头来支持这些。
类名: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
我希望有所帮助。
谢谢!!!
尝试下面的代码,它为我工作。
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;
}
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
}
SHS提供的代码对我不起作用,但这个代码显然是这样做的(我使用过桥接头:#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
}
}
从我的ViewController
:
let encoded = message.aesEncrypt(key: keyString, iv: iv)
let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
有一个有趣的“纯粹的swift”开源库:
使用AES解密的示例(从项目README.md文件获取):
import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = AES(setup).decrypt(encryptedData)
我使用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
}
CryptoSwift是一个非常有趣的项目,但目前它有一些AES速度限制。如果你需要做一些严肃的加密,请小心 - 可能值得经历桥接实现CommonCrypto的痛苦。
Marcin的BigUps用于pureSwift实现
您可以使用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! }
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'#add to PodFile 2. pod install
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)
}
}
我找到了解决方案,它是一个很好的库。
跨平台256位AES加密/解密。
该项目包含256位AES加密的实现,适用于所有平台(C#,iOS,Android)。其中一个关键目标是通过简单的实现使AES在所有平台上运行。
支持的平台:iOS,Android,Windows(C#)。