import XCTest
import CryptoKit
import Foundation
class CryptoKitUnitTest: XCTestCase {
func testEncryptandDecrypt(){
let secret = "my-256-bit-secret-my-secret-my-s"
let key = SymmetricKey(data: secret.data(using: .utf8)!)
let plain = "Say hello to my little friend!"
let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!)
// Encrypt
let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce)
let ciphertext = sealedBox.ciphertext.base64EncodedString()
print("ciphertext: \(ciphertext)") // bWtTZkPAu7oXpQ3QpHvoTvc4NQgDTIycXHFJWvjk
let sealedBoxToDecrypt = try! AES.GCM.SealedBox(nonce: nonce,
ciphertext: Data(base64Encoded: ciphertext)!,
tag: sealedBox.tag)
let decrypted = try! AES.GCM.open(sealedBoxToDecrypt, using: key)
print(String(decoding: decrypted, as: UTF8.self))
}
func testEncryptandDecryptFirstWay() {
let keyStr = "d5a423f64b607ea7c65b311d855dc48f36114b227bd0c7a3d403f6158a9e4412"
let key = SymmetricKey(data: Data(hex:keyStr))
let nonceData = Data(hex: "131348c0987c7eece60fc0bc")
let nonce: AES.GCM.Nonce = try! AES.GCM.Nonce(data: nonceData)
let plain = "This is first cypto graphy method"
var decyptedStr = ""
if let encyptedData = plain.asData.encrypt(nonce: nonce, key: key) {
decyptedStr = encyptedData.decrypt(nonce: nonce, key: key)
}
XCTAssertEqual(plain, decyptedStr)
}
}
extension Data {
func encrypt(nonce: AES.GCM.Nonce, key: SymmetricKey) ->Data?{
// Encrypt
do {
let sealedBox = try AES.GCM.seal(self, using: key, nonce: nonce)
let cipherText = sealedBox.ciphertext.base64EncodedString()
let tag = sealedBox.tag
let tagPlusCipherText = tag + cipherText.asData
return tagPlusCipherText
}
catch let exceptionInfo {
debugPrint("Encrypt exception Info: \(exceptionInfo)")
}
return nil
}
func decrypt(nonce: AES.GCM.Nonce, key: SymmetricKey) -> String{
let tag = self.subtract(0, 16)
let cipherTextData = self.subtract(tag.count, self.count - tag.count)
let cipherText = cipherTextData.asString
// Decrypt
var decodeStr: String = ""
do {
let sealedBoxToDecrypt = try AES.GCM.SealedBox(nonce: nonce,
ciphertext: Data(base64Encoded: cipherText)!,
tag: tag)
let decrypted = try AES.GCM.open(sealedBoxToDecrypt, using: key)
decodeStr = String(decoding: decrypted, as: UTF8.self)
} catch let exceptionInfo {
debugPrint("Decrypt exception info: \(exceptionInfo)")
}
return decodeStr
}
public func subtract(_ start: Int, _ length: Int) ->Data {
precondition(self.count >= start + length,
"Invalid data range range. trying to find out of bound data")
let allBytes = Array(Data(bytes: self.bytes, count: self.count))
let partBytes = Array(allBytes[start..<start + length])
let dataPart = Data(bytes: partBytes, count: partBytes.count)
return dataPart
}
var asString: String {
let str = String(decoding: self, as: UTF8.self)
return str
}
}
extension String {
var asData: Data {
return self.data(using: .utf8) ?? Data()
}
}
mySealedBox.combined
. So do you do anything with the key and ciphertext in between the calls of these methods? Could you print outencryptedData
anddecryptToData
in hexadecimals or base64? The code I must admit looks a bit haphazard, withlet combinedData = decryptToData // Previous sealed bo
not even being utilized... Preferably print out the key value as well! – Illustration