Unravel โบ Java concepts โบ Security
Hashes, HMAC and secure random
A hash turns data of any size into a fixed fingerprint; an HMAC adds a secret key so that only parties who know it can create the fingerprint.
At a glance
A hash is the wax seal imprint of a letter: change one word and the imprint no longer matches.
- 1MessageDigest.getInstance("SHA-256").digest(bytes) returns 32 bytes; convert to text with HexFormat.of().formatHex(...) or Base64The same input always gives the same output.
- 2Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret, "HmacSHA256")); mac.doFinal(body) produces a keyed signature, used by GitHub, Stripe and cloud APIs to sign webhooks and requests
- 3SecureRandom provides unpredictable bytes for tokens, salts and keysjava.util.Random and Math.random() are predictable and must not be used for secrets.
- 4Use hashes for integrity (checksums, deduplication, ETags), HMAC for authenticity, and password hashing algorithms (BCrypt) for passwords
- Compare signatures with a constant-time method (MessageDigest.isEqual), not equals; a normal comparison stops at the first different byte, leaking information through timing
- MD5 and SHA-1 are broken for security (collisions can be forged)
- SHA-256 processes the message in 64-byte blocks through 64 rounds of bitwise operations, folding each block into a 256-bit state
Mac mac = Mac.getInstance("HmacSHA256");mac.init(new SecretKeySpec(webhookSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));byte[] expected = mac.doFinal(body.getBytes(StandardCharsets.UTF_8));byte[] received = HexFormat.of().parseHex(signatureHeader);if (!MessageDigest.isEqual(expected, received)) { throw new SecurityException("Invalid signature");}- line 1 uses Mac, the core of Hashes, HMAC and secure random
- line 3 uses doFinal, the core of Hashes, HMAC and secure random
- line 4 uses HexFormat, the core of Hashes, HMAC and secure random
- line 5 uses MessageDigest, the core of Hashes, HMAC and secure random
Read the full explanation (about 1 min)
A hash turns data of any size into a fixed fingerprint; an HMAC adds a secret key so that only parties who know it can create the fingerprint. They verify integrity and authenticity: webhook signatures, file checksums, request signing, tokens.
A mental model
A hash is the wax seal imprint of a letter: change one word and the imprint no longer matches. An HMAC is a seal made with a private signet ring, so only the ring owner can produce a valid one.
How it works
MessageDigest.getInstance("SHA-256").digest(bytes) returns 32 bytes; convert to text with HexFormat.of().formatHex(...) or Base64. The same input always gives the same output.
Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret, "HmacSHA256")); mac.doFinal(body) produces a keyed signature, used by GitHub, Stripe and cloud APIs to sign webhooks and requests.
SecureRandom provides unpredictable bytes for tokens, salts and keys. java.util.Random and Math.random() are predictable and must not be used for secrets.
Use hashes for integrity (checksums, deduplication, ETags), HMAC for authenticity, and password hashing algorithms (BCrypt) for passwords.
Going deeper
Compare signatures with a constant-time method (MessageDigest.isEqual), not equals; a normal comparison stops at the first different byte, leaking information through timing.
MD5 and SHA-1 are broken for security (collisions can be forged). Use SHA-256 or better; they are fine only for non-security checksums.
Always specify the charset when converting text to bytes (getBytes(StandardCharsets.UTF_8)); the platform default makes hashes differ between machines.
Under the hood
SHA-256 processes the message in 64-byte blocks through 64 rounds of bitwise operations, folding each block into a 256-bit state. HMAC computes H((K xor opad) || H((K xor ipad) || message)), a nested construction that avoids length-extension weaknesses of the raw hash. SecureRandom draws from the operating system entropy source.
Common mistakes
- MD5 or SHA-1 for security.
- Comparing signatures with equals.
- Predictable Random for tokens.
- Missing charset when hashing strings.
How Unravel recognises it
When you paste code, Unravel looks for these signs of hashes, hmac and secure random. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
MessageDigestMacDigestUtilsHexFormatSecureRandomHmacUtilsHashingKeyGenerator - Method calls:
digest()doFinal()sha256Hex()HmacUtils.hmacSha256Hex()MessageDigest.isEqual() - Configuration keys:
SHA-256SHA-512SHA-1MD5HmacSHA256HmacSHA512SHA1PRNG
Part of a learning path
- Security for backend developers ยท previous: Password hashing (BCrypt, Argon2, PBKDF2) ยท next: Symmetric encryption (AES-GCM) and key handling
Related concepts
Frequently asked questions
What is Hashes, HMAC and secure random?
A hash turns data of any size into a fixed fingerprint; an HMAC adds a secret key so that only parties who know it can create the fingerprint. They verify integrity and authenticity: webhook signatures, file checksums, request signing, tokens.
What are the most common mistakes with Hashes, HMAC and secure random?
MD5 or SHA-1 for security. Comparing signatures with equals. Predictable Random for tokens. Missing charset when hashing strings.
How can I see Hashes, HMAC and secure random in real code?
Paste your own Java into Unravel and it will point out where hashes, hmac and secure random appears, explain how it works at the detail level you choose, and draw the flow of the code around it.