$ java -cp classes Mistakes (25.0.5+8-LTS) == 1. Same info for two purposes: the 'two' keys are one key PASS encryption key == MAC key when info is the same PASS distinct info labels give distinct keys == 2. Gluing fields together without a delimiter: tenant 'ab' + 'c' collides with 'a' + 'bc' PASS naive concatenation collides PASS length-prefixed fields (Tenants.info) do not collide == 3. Salt: leaving it out is the same as HashLen zero bytes, and a salt is not a secret PASS no salt == 32 zero bytes (SHA-256) PASS a different salt changes every output, so a salt change is a key change == 4. Asking for more than 255 * HashLen bytes length 8160 -> ok (8160 bytes) length 8161 -> InvalidAlgorithmParameterException: The specified SunJCE provider does not support this input == 5. Deriving a key from a low-entropy secret (a 4-digit PIN) HKDF-derived key: attacker finds PIN 4821 after 4822 guesses PASS PBKDF2 (600000 iterations) is at least 1000 times slower per guess than HKDF ALL CHECKS PASSED exit=0