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() } }
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)!)
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))
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())")
Top comments (0)