AES加密和解密

meh*_*ehr 29 encryption aes ios swift cryptoswift

我通过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;
    }
Run Code Online (Sandbox Code Playgroud)

我需要在swift中解密函数.

小智 30

CryptoSwift 示例

更新为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!)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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
Run Code Online (Sandbox Code Playgroud)

确保你有正确的iv(16)和key(32)长度然后你不会点击"块大小和初始化向量必须是相同的长度!" 错误.

  • 请注意,CryptoSwift比Common Crypto慢500到1000倍. (3认同)

Mak*_*zev 27

CryptoSwift 示例

更新了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
}
Run Code Online (Sandbox Code Playgroud)

  • 基本上每一次数据泄露都可以说"我已经使用了一段时间而没有注意到任何不好的事情"......但随后出现了一些不好的事情.这就像安全带,为什么这么麻烦. (4认同)
  • 最好避免使用CryptoSwift,它要比基于Common Crypto的实现慢500到1000倍。Apple的Common Crypto已通过FIPS认证,因此经过严格的审查,使用CryptoSwift可以提高准确性和安全性。 (2认同)

小智 10

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
    }


}
Run Code Online (Sandbox Code Playgroud)

从我的ViewController:

 let encoded = message.aesEncrypt(key: keyString, iv: iv)
 let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
Run Code Online (Sandbox Code Playgroud)


Rob*_*rto 7

有一个有趣的"纯粹的swift"开源库:

使用AES解密的示例(从项目README.md文件获取):

import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = AES(setup).decrypt(encryptedData)
Run Code Online (Sandbox Code Playgroud)


ha1*_*100 5

CryptoSwift 是一个非常有趣的项目,但目前它有一些 AES 速度限制。如果您需要进行一些严肃的加密操作,请务必小心 - 经历实现 CommonCrypto 的桥梁的痛苦可能是值得的。

BigUps 到 Marcin 用于 pureSwift 实施

  • 是的,使用 CryptoSwift 的 AES 加密比 Common Crypto 慢 500 到 1000 倍,这是因为 Common Crypto 使用硬件加密功能,而 CryptoSwift 没有。 (4认同)

SHS*_*SHS 5

我正在使用 CommonCrypto 通过来自CommonCrypto HMAC 的 Easy to use Swift implementation 的 MihaelIsaev /HMAC.swift 的代码生成哈希。此实现不使用 Bridging-Header,而是创建模块文件。

现在为了使用 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
}
Run Code Online (Sandbox Code Playgroud)

这些函数取自RNCryptor。这是散列函数和单个文件“HMAC.swift”中的一个简单添加,无需使用 Bridging-header。我希望这对需要散列和 AES 加密/解密的 swift 开发人员有用。

使用 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
 }
Run Code Online (Sandbox Code Playgroud)


cen*_*ioz 5

您可以使用来自 iOS 或 CryptoSwift 的 CommonCrypto 作为外部库。下面有两种工具的实现。也就是说,应该测试带有 AES 的 CommonCrypto 输出,因为 CC 文档中不清楚它使用哪种 AES 模式。

Swift 4.2 中的 CommonCrypto

    导入 CommonCrypto

    func 加密(数据:数据)-> 数据 {
        return cryptCC(data: data, key: key, operation: kCCEncrypt)
    }

    func 解密(数据:数据)-> 数据 {
        返回 cryptCC(数据:数据,密钥:密钥,操作:kCCDecrypt)
    }

    private func cryptCC(data: Data, key: String operation: Int) -> Data {

        保护 key.count == kCCKeySizeAES128 else {
            致命错误(“密钥大小失败!”)
        }

        var ivBytes: [UInt8]
        var inBytes: [UInt8]
        var outLength: Int

        如果操作 == kCCEncrypt {
            ivBytes = [UInt8](重复:0,计数:kCCBlockSizeAES128)
            守卫 kCCSuccess == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
                fatalError("IV 创建失败!")
            }

            inBytes = 数组(数据)
            outLength = data.count + kCCBlockSizeAES128

        } 别的 {
            ivBytes = Array(Array(data).dropLast(data.count - kCCBlockSizeAES128))
            inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128))
            outLength = inBytes.count

        }

        var outBytes = [UInt8](重复:0,计数:outLength)
        var bytesMutated = 0

        守卫 kCCSuccess == CCCrypt(CCOperation(operation), CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), Array(key), kCCKeySizeAES128, &ivBytes, &inBytes, inBytes.count, &outBytes, outLength, &bytesMutated) else {
            致命错误(“密码操作\(操作)失败”)
        }

        var outData = Data(bytes: &outBytes, count: bytesMutated)

        如果操作 == kCCEncrypt {
            ivBytes.append(contentsOf: Array(outData))
            outData = 数据(字节:ivBytes)
        }
        返回数据

    }


Swift 4.2 中的 CryptoSwift v0.14

    枚举操作{
        大小写加密
        案例解密
    }

    私人让 keySizeAES128 = 16
    私人让 aesBlockSize = 16

    func encrypt(data: Data, key: String) -> Data {
        返回 crypt(data: data, key: key, operation: .encrypt)
    }

    func 解密(数据:数据,密钥:字符串)-> 数据 {
        返回 crypt(data: data, key: key, operation: .decrypt)
    }

    private func crypt(data: Data, key: String, operation: Operation) -> Data {

        保护 key.count == keySizeAES128 else {
            致命错误(“密钥大小失败!”)
        }
        var outData:数据?= 零

        如果操作 == .encrypt {
            var ivBytes = [UInt8](重复:0,计数:aesBlockSize)
            守卫 0 == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
                fatalError("IV 创建失败!")
            }

            做 {
                让 aes = 尝试 AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
                让加密 = 尝试 aes.encrypt(Array(data))
                ivBytes.append(contentsOf: 加密)
                outData = 数据(字节:ivBytes)

            } 抓住 {
                打印(“加密错误:\(错误)”)
            }

        } 别的 {
            让 ivBytes = Array(Array(data).dropLast(data.count - aesBlockSize))
            让 inBytes = Array(Array(data).dropFirst(aesBlockSize))

            做 {
                让 aes = 尝试 AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
                让解密 = 尝试 aes.decrypt(inBytes)
                outData = 数据(字节:解密)

            } 抓住 {
                print("解密错误:\(error)")
            }
        }
        返回数据!

    }


meh*_*ehr 2

我找到了解决方案,它是一个很好的库。

跨平台256位AES加密/解密。

该项目包含 256 位 AES 加密的实现,适用于所有平台(C#、iOS、Android)。主要目标之一是让 AES 在所有平台上运行并实现简单。

支持的平台:iOS、Android、Windows (C#)。

https://github.com/Pakhee/Cross-platform-AES-加密

  • 这是一个很糟糕的图书馆。a) 如果 Key 和 IV 的大小不正确,则出于某种原因,它们会用“null”填充。这很糟糕,因为人们只是将其与密码一起使用,但密码没有足够的熵来用作密钥!相反,可以使用 PBKDF2 或 Argon2 等方案从密码派生密钥。b) 该库根本不提供身份验证。c) 由于某种原因,IV 是基于文本的而不是二进制的。d) 用户需要自己管理IV,很可能会出错。 (4认同)