import Foundation
import CryptoKit

// Independent format check using public test keys, not production key material.
let url = URL(fileURLWithPath: CommandLine.arguments.count > 1 ? CommandLine.arguments[1] : "attachment-v1-test-vector.json")
let vector = try JSONSerialization.jsonObject(with: Data(contentsOf: url)) as! [String: Any]
let reference = vector["reference"] as! [String: Any]
let id = reference["id"] as! String
func decode(_ value: Any?) -> Data { Data(base64Encoded: value as! String)! }
func open(_ data: Data, iv: Data, key: SymmetricKey, purpose: String) throws -> Data {
    let box = try AES.GCM.SealedBox(nonce: AES.GCM.Nonce(data: iv), ciphertext: data.dropLast(16), tag: data.suffix(16))
    return try AES.GCM.open(box, using: key, authenticating: Data("lock:attachment:v1:\(id):\(purpose)".utf8))
}
let messageKey = SymmetricKey(data: decode(vector["message_key"]))
let rawFileKey = try open(decode(reference["wrapped_key"]), iv: decode(reference["key_iv"]), key: messageKey, purpose: "key")
precondition(rawFileKey.count == 32)
let fileKey = SymmetricKey(data: rawFileKey)
let metadataData = try open(decode(reference["metadata_ciphertext"]), iv: decode(reference["metadata_iv"]), key: fileKey, purpose: "metadata")
let metadata = try JSONSerialization.jsonObject(with: metadataData) as! NSDictionary
precondition(metadata == (vector["metadata"] as! NSDictionary))
let plaintext = try open(decode(vector["file_ciphertext"]), iv: decode(reference["file_iv"]), key: fileKey, purpose: "file")
precondition(plaintext == decode(vector["plaintext_base64"]))
print("PASS: attachment key, metadata and file decrypt with CryptoKit.")
