$ java -cp classes Tenants (25.0.5+8-LTS) == Per-tenant, per-purpose, per-version keys (first 8 bytes shown) tenant-acme aes v1 = 503b6a158de948ef hmac v1 = de11af197467596c aes v2 = 0c80331430e74d8d tenant-globex aes v1 = 3e7dd7c93250c77e hmac v1 = ab1c9c0b01b4e64b aes v2 = 22859d1db92cf04b PASS same inputs give the same key every time (nothing to store) PASS two tenants get different keys PASS encryption key and MAC key of one tenant differ PASS key version 2 differs from version 1 (rotation) == Isolation in practice: tenant A's ciphertext is opaque to tenant B's key acme key decrypts: invoice #4711 for acme globex key fails: AEADBadTagException: Tag mismatch PASS tenant B cannot open tenant A's data == HMAC key from the same master, used for a signed token tag = 3cb1fb88afc1c173475dac3a12f68f05... == The info bytes that separate the contexts (hex) for tenant-acme / aes-gcm / v1 000f61636d652d62696c6c696e672f763100076165732d67636d000b74656e616e742d61636d65000400000001 ALL CHECKS PASSED exit=0