jamiechoo

 

Swift原生的AES-128全部功能和实例

Swift 提供了对 AES 加密的原生支持,主要通过 CryptoKit 框架来实现。CryptoKit 支持对称加密,包括 AES(高级加密标准)算法,支持不同的模式如 AES-GCM 和 AES-CBC。

虽然 Swift 没有直接列出 “AES-128” 的特定函数,但你可以通过设置密钥的大小来指定 AES-128。AES 的密钥长度可以是 128、192 或 256 位,分别对应不同的加密强度。在 CryptoKit 中,使用 AES.GCMAES.CBC 模式进行加密时,可以通过密钥长度来指定使用 AES-128。

主要功能包括:

  1. AES-GCM (Galois/Counter Mode): 用于加密和验证数据,常用于现代加密。
  2. AES-CBC (Cipher Block Chaining Mode): 一种更传统的加密模式,需要使用 IV(初始化向量)。

使用 CryptoKit 进行 AES-128 加密的示例

1. AES-GCM (AES-128)

AES-GCM 是一种推荐的模式,它不仅加密数据,还提供了验证数据完整性的功能(即认证)。

示例代码:

import CryptoKit
 
// 生成 128 位(16 字节)的对称密钥
let key = SymmetricKey(size: .bits128)
// 要加密的数据
let plaintext = "Hello, AES-GCM!".data(using: .utf8)!
// 加密
let sealedBox = try! AES.GCM.seal(plaintext, using: key)
// 获取加密数据
let ciphertext = sealedBox.ciphertext
// 获取认证标签和初始向量
let tag = sealedBox.tag
let nonce = sealedBox.nonce
print("Ciphertext: \(ciphertext.base64EncodedString())")
print("Tag: \(tag.base64EncodedString())")
print("Nonce: \(nonce)")
// 解密
let sealedBoxToOpen = try! AES.GCM.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag)
let decryptedData = try! AES.GCM.open(sealedBoxToOpen, using: key)
// 将解密后的数据转换回字符串
let decryptedString = String(data: decryptedData, encoding: .utf8)!
print("Decrypted String: \(decryptedString)")

解释:

  • SymmetricKey(size: .bits128):生成一个 128 位对称密钥(即 AES-128 密钥)。
  • AES.GCM.seal(plaintext, using: key):使用 AES-GCM 加密数据。
  • AES.GCM.open(sealedBoxToOpen, using: key):使用同一密钥解密数据。

2. AES-CBC (AES-128)

CryptoKit 并不直接提供对 AES-CBC 的支持,但我们可以使用 CommonCrypto 库来实现 AES-CBC 模式。下面是一个基于 CommonCrypto 实现 AES-128-CBC 加密的示例。

示例代码:

import CommonCrypto
import Foundation
 
 
// AES-128 加密(CBC 模式)
func aesCBCEncrypt(data: Data, key: Data, iv: Data) -> Data? {
    let keyLength = kCCKeySizeAES128 // AES-128 密钥长度
    var cryptData = Data(count: data.count + kCCBlockSizeAES128)
    var numBytesEncrypted: size_t = 0
      let cryptStatus = cryptData.withUnsafeMutableBytes { cryptBytes in
        data.withUnsafeBytes { dataBytes in
          iv.withUnsafeBytes { ivBytes in
            key.withUnsafeBytes { keyBytes in
              CCCrypt(
                  CCOperation(kCCEncrypt),
                  CCAlgorithm(kCCAlgorithmAES),
                  CCOptions(kCCOptionPKCS7Padding),
                  keyBytes.baseAddress,
                  keyLength,
                  ivBytes.baseAddress,
                  dataBytes.baseAddress,
                  data.count,
                  cryptBytes.baseAddress,
                  cryptData.count,
                  &numBytesEncrypted
                    ) } } }
                  }
        if cryptStatus == kCCSuccess {
          cryptData.removeSubrange(numBytesEncrypted..<cryptData.count) return cryptData }
            return nil
            }
      // AES-128 解密(CBC 模式)
 
func aesCBCDecrypt(data: Data, key: Data, iv: Data) -> Data? {
    let keyLength = kCCKeySizeAES128
    var cryptData = Data(count: data.count + kCCBlockSizeAES128)
    var numBytesDecrypted: size_t = 0
    let cryptStatus = cryptData.withUnsafeMutableBytes { cryptBytes in
        data.withUnsafeBytes { dataBytes in
          iv.withUnsafeBytes { ivBytes in
            key.withUnsafeBytes { keyBytes in
                CCCrypt( CCOperation(kCCDecrypt),
                CCAlgorithm(kCCAlgorithmAES),
                CCOptions(kCCOptionPKCS7Padding),
                keyBytes.baseAddress,
                keyLength,
                ivBytes.baseAddress,
                dataBytes.baseAddress,
                data.count,
                cryptBytes.baseAddress,
                cryptData.count, &numBytesDecrypted
                    ) } } }
                  }
      if cryptStatus == kCCSuccess {
          cryptData.removeSubrange(numBytesDecrypted..<cryptData.count)
              return cryptData }
                  return nil }
          // 测试 AES-128-CBC 加密和解密
      let key = "0123456789abcdef".data(using: .utf8)!
          // 128 位密钥
      let iv = "abcdef9876543210".data(using: .utf8)!
          // IV 长度为 16 字节
      let plaintext = "Hello,
        AES-CBC!".data(using: .utf8)!
          // 加密
        if let ciphertext = aesCBCEncrypt(data: plaintext, key: key, iv: iv) {
            print("Ciphertext: \(ciphertext.base64EncodedString())")
          // 解密
        if let decryptedData = aesCBCDecrypt(data: ciphertext, key: key, iv: iv) {
          let decryptedString = String(data: decryptedData, encoding: .utf8)!
            print("Decrypted String: \(decryptedString)") }
          }

解释:

  • aesCBCEncrypt:使用 AES-128-CBC 模式对数据进行加密。
  • aesCBCDecrypt:使用 AES-128-CBC 模式对加密数据进行解密。
  • kCCAlgorithmAES:指定使用 AES 算法。
  • kCCKeySizeAES128:AES-128 的密钥长度为 16 字节(128 位)。

CryptoKit 提供的功能:

  1. AES-GCM:用于加密和验证数据。
    • AES.GCM.seal(_:using:):加密数据。
    • AES.GCM.open(_:using:):解密数据。
  2. 支持 128、192 和 256 位密钥:通过密钥长度来确定 AES 的强度,支持 .bits128.bits192.bits256
  3. 对称密钥生成SymmetricKey 类可以生成 128、192、256 位的对称密钥。
  4. 认证加密:AES-GCM 模式同时提供加密和认证(验证消息未被篡改)。

总结:

  • AES-GCMCryptoKit 原生支持,并且推荐使用这种模式进行加密和认证。通过 SymmetricKey 设置 128 位密钥即可实现 AES-128。
  • AES-CBC:可以通过 CommonCrypto 来实现。如果你需要使用 CBC 模式,请使用 CommonCrypto

在 Swift 中,CryptoKit 提供了方便、安全的加密方法,特别是 AES-GCM,适用于大多数应用场景。如果你需要传统的 AES-CBC 模式,则可以使用 CommonCrypto 实现。

posted on 2024-10-03 17:22  jamiechoo  阅读(336)  评论(0)    收藏  举报

导航