Closer/iphone/CloserTests/CryptoTests/FieldEncryptorTests.swift

62 lines
2.7 KiB
Swift
Raw Permalink Normal View History

import XCTest
import CryptoKit
@testable import Closer
final class FieldEncryptorTests: XCTestCase {
private let key = SymmetricKey(size: .bits256)
func testStringRoundTripWithoutAAD() throws {
let plaintext = "hello, closer"
let blob = try FieldEncryptor.encryptString(plaintext, key: key, aad: nil)
XCTAssertTrue(blob.hasPrefix(FieldEncryptor.prefix))
let recovered = try FieldEncryptor.decryptString(blob, key: key, aad: nil)
XCTAssertEqual(recovered, plaintext)
}
func testStringRoundTripWithAAD() throws {
let plaintext = "secret payload"
let aad = "couple-123".data(using: .utf8)!
let blob = try FieldEncryptor.encryptString(plaintext, key: key, aad: aad)
let recovered = try FieldEncryptor.decryptString(blob, key: key, aad: aad)
XCTAssertEqual(recovered, plaintext)
}
func testBinaryRoundTrip() throws {
let plaintext = Data((0..<64).map { $0 })
let aad = Data([0x00, 0x01, 0x02])
let ct = try FieldEncryptor.encrypt(plaintext, key: key, aad: aad)
let recovered = try FieldEncryptor.decrypt(ct, key: key, aad: aad)
XCTAssertEqual(recovered, plaintext)
}
func testTamperedCiphertextThrows() throws {
let plaintext = "tamper me"
let blob = try FieldEncryptor.encryptString(plaintext, key: key, aad: nil)
var bytes = Array(blob.utf8)
// Flip a bit in the base64 payload portion.
let prefixEnd = FieldEncryptor.prefix.count
bytes[prefixEnd + 5] ^= 0x01
let tampered = String(bytes: bytes, encoding: .utf8)!
XCTAssertThrowsError(try FieldEncryptor.decryptString(tampered, key: key, aad: nil))
}
func testWrongAADThrows() throws {
let plaintext = "aad bound"
let blob = try FieldEncryptor.encryptString(plaintext, key: key, aad: Data([0xAB]))
XCTAssertThrowsError(try FieldEncryptor.decryptString(blob, key: key, aad: Data([0xBA])))
}
func testKnownVectorCryptoKitRoundTrip() throws {
// NIST-style AES-256-GCM test vector derived from CryptoKit itself:
// fixed key + fixed nonce + fixed plaintext should round-trip deterministically.
let keyBytes = Data(repeating: 0xAB, count: 32)
let fixedKey = SymmetricKey(data: keyBytes)
let nonce = AES.GCM.Nonce(data: Data(repeating: 0xCD, count: 12))!
let plaintext = Data("known vector plaintext".utf8)
let sealed = try AES.GCM.seal(plaintext, using: fixedKey, nonce: nonce)
let ct = sealed.combined!
let recovered = try AES.GCM.open(try AES.GCM.SealedBox(combined: ct), using: fixedKey)
XCTAssertEqual(recovered, plaintext)
}
}