DEV Community

Takuya Matsuyama
Takuya Matsuyama

Posted on

How to encrypt/decrypt with AES-GCM using CryptoKit in Swift

I'm developing a native module for React Native that allows you to encrypt/decrypt data with AES-GCM for my Markdown note-taking app. Here is a working memo.

CryptoKit is available from iOS 13.0.

Convert hexadecimal strings

First, you need to extend Data class to deal with hexadecimal strings:

public extension Data { init?(hexString: String) { let len = hexString.count / 2 var data = Data(capacity: len) var i = hexString.startIndex for _ in 0..<len { let j = hexString.index(i, offsetBy: 2) let bytes = hexString[i..<j] if var num = UInt8(bytes, radix: 16) { data.append(&num, count: 1) } else { return nil } i = j } self = data } /// Hexadecimal string representation of `Data` object. var hexadecimal: String { return map { String(format: "%02x", $0) } .joined() } } 
Enter fullscreen mode Exit fullscreen mode

Load key

A key is given in hex string. The key length is 256 bits.

import CryptoKit let keyStr = "d5a423f64b607ea7c65b311d855dc48f36114b227bd0c7a3d403f6158a9e4412" let key = SymmetricKey(data: Data(hexString:keyStr)!) 
Enter fullscreen mode Exit fullscreen mode

Decrypt

An encrypted data comes with a ciphertext, an initialization vector (a.k.a. nonce), and an auth tag.

let ciphertext = Data(base64Encoded: "LzpSalRKfL47H5rUhqvA") let nonce = Data(hexString: "131348c0987c7eece60fc0bc") // = initialization vector let tag = Data(hexString: "5baa85ff3e7eda3204744ec74b71d523") let sealedBox = try! AES.GCM.SealedBox(nonce: AES.GCM.Nonce(data: nonce!), ciphertext: ciphertext!, tag: tag!) let decryptedData = try! AES.GCM.open(sealedBox, using: key) print(String(decoding: decryptedData, as: UTF8.self)) 
Enter fullscreen mode Exit fullscreen mode

Encrypt

let plainData = "This is a plain text".data(using: .utf8) let sealedData = try! AES.GCM.seal(plainData!, using: key, nonce: AES.GCM.Nonce(data:nonce!)) let encryptedContent = try! sealedData.combined! print("Nonce: \(sealedData.nonce.withUnsafeBytes { Data(Array($0)).hexadecimal })") print("Tag: \(sealedData.tag.hexadecimal)") print("Data: \(sealedData.ciphertext.base64EncodedString())") 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)