eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1import XCTest
2@testable import LChatCore
3
4// The sealed-branding KDF must agree byte-for-byte with the web
5// (crypto.js deriveBrandingKey) — the pinned vector here is the SAME one
6// test/crypto.test.mjs pins. If this fails you changed the derivation;
7// don't re-pin — sealed blobs already at rest would silently brick.
8final class SealedBrandingTests: XCTestCase {
9 private let vectorB = "k3m7p2qx4f"
10 private let vectorSalt = "AAECAwQFBgcICQoLDA0ODw" // bytes 0x00..0x0f
11 private let vectorBlob =
12 "uu9h74mrboFkgWSzYhnd67QKxlD7k9t6nJ79flw9UKkdkTMIZRTtxOcBW-ivDIckbudRf9uB64AXiGB4qcPfOA"
13
14 func testPinnedWebVectorDecrypts() throws {
15 struct Pin: Codable { let name: String; let emoji: String }
16 let key = try SealedBrandingCrypto.deriveKey(b: vectorB, saltB64url: vectorSalt)
17 let pin = try key.decryptJSON(Pin.self, blob: vectorBlob)
18 XCTAssertEqual(pin.name, "Vector Pin")
19 XCTAssertEqual(pin.emoji, "🔏")
20 }
21
22 func testWrongKeyOrSaltFailsClosed() throws {
23 let wrongB = try SealedBrandingCrypto.deriveKey(b: "aaaaaaaaaa", saltB64url: vectorSalt)
24 XCTAssertThrowsError(try wrongB.decryptJSON(SealedBranding.self, blob: vectorBlob))
25 let wrongSalt = try SealedBrandingCrypto.deriveKey(b: vectorB, saltB64url: "_w0ODQwLCgkIBwYFBAMCAQA")
26 XCTAssertThrowsError(try wrongSalt.decryptJSON(SealedBranding.self, blob: vectorBlob))
27 }
28
29 func testEmptyInputsThrow() {
30 XCTAssertThrowsError(try SealedBrandingCrypto.deriveKey(b: "", saltB64url: vectorSalt))
31 XCTAssertThrowsError(try SealedBrandingCrypto.deriveKey(b: vectorB, saltB64url: ""))
32 }
33
34 // The sealed avatar path: bytes encrypted under the derived key round-trip
35 // through the same iv||ct format the web's encryptBytes produces.
36 func testAvatarBytesRoundTrip() throws {
37 let key = try SealedBrandingCrypto.deriveKey(b: vectorB, saltB64url: vectorSalt)
38 let photo = Data([0xFF, 0xD8, 0xFF, 0xE0, 1, 2, 3, 4, 5])
39 let sealed = try key.encryptBytes(photo)
40 XCTAssertEqual(try key.decryptBytes(sealed), photo)
41 }
42
43 // The blob's field names are the contract with the web (sealBrandingNow's
44 // JSON) — decode a literal to keep them pinned.
45 func testBrandingBlobFieldNames() throws {
46 let json = """
47 {"name":"Family","description":"Us","admin_name":"Paul",
48 "admin_email":"p@x.com","avatar_alt":"A sunflower","avatar_mime":"image/jpeg"}
49 """.data(using: .utf8)!
50 let b = try JSONDecoder().decode(SealedBranding.self, from: json)
51 XCTAssertEqual(b.name, "Family")
52 XCTAssertEqual(b.avatar_mime, "image/jpeg")
53 }
54}
55