🧰 Core APIs Toolbox · Intermediate

UUID & hashing basics in Java

UUID.randomUUID, MessageDigest for checksums.

🧩 The mysteryTwo servers on opposite sides of the planet create order IDs at the same millisecond, without talking to each other — and never clash. How?

IDs without a coordinator

A UUID is a 128-bit identifier written as 36 characters: 32 hex digits plus 4 dashes. **UUID.randomUUID() creates a version 4 UUID: 122 of its bits are random**, from a secure generator — so collisions are practically impossible.

UUID id = UUID.randomUUID();
// e.g. 3f2a9c1e-…-4…-…  (36 chars)
🔮 Predict it

Reading a UUID

What does this print?

UUID id = UUID.fromString(
    "00000000-0000-4000-8000-000000000000");
System.out.println(id.version());
System.out.println(id.toString().length());
  1. 4 36
  2. 4 32
  3. 0 36
Show the answer

4 — the version is the first digit of the third group (4000). 36 — 32 hex digits plus 4 dashes.

Hashes are fingerprints

A cryptographic hash like SHA-256 turns any input into a fixed-size digest: always 32 bytes. Same input → same digest; change one letter → a totally different one. **HexFormat.of().formatHex(bytes)** (Java 17) prints it as 64 hex characters.

var md = MessageDigest.getInstance("SHA-256");
byte[] h = md.digest("hi".getBytes());
HexFormat.of().formatHex(h); // 64 chars
🔮 Predict it

Size of a fingerprint

What does this print?

void main() throws Exception {
    var md = MessageDigest
        .getInstance("SHA-256");
    byte[] a = md.digest("a".getBytes());
    byte[] b = md.digest("a much longer text"
        .getBytes());
    System.out.println(a.length);
    System.out.println(b.length);
}
  1. 1 18
  2. 32 32
  3. 256 256
Show the answer

32 both times — SHA-256 always outputs 256 bits = 32 bytes, no matter how big the input.

Storing passwords

✗ Fast hash
byte[] stored = md.digest(
    password.getBytes()); // SHA-256

SHA-256 is so fast that attackers can try billions of guesses per second, and unsalted hashes fall to precomputed tables.

✓ Slow, salted
String stored = encoder.encode(password);
// bcrypt, PBKDF2 or Argon2

Deliberately slow and salted, so each guess is expensive.

Which tool for which job

MD5 is broken (practical collisions): only for non-security checksums. SHA-256: integrity checks for files and downloads. **String.hashCode(): a 32-bit value for hash tables only — it collides easily. A UUID is an ID**, not a hash of anything.

💼 In the real world

Everyday uses

Database primary keys and request-tracing IDs are often UUIDs. Download pages publish SHA-256 checksums so you can verify files. And leaked databases of fast, unsalted password hashes are exactly why bcrypt and Argon2 are the industry standard.

Key takeaways

  1. UUID.randomUUID(): version 4, 122 random bits
  2. SHA-256 → 32 bytes (64 hex characters), any input size
  3. HexFormat.of().formatHex(bytes) prints digests (Java 17)
  4. Passwords need slow salted hashes (bcrypt, Argon2)
🤯 Did you know?

Version-4 UUIDs have 2¹²² possible values — you'd need to generate about 2.7 quintillion of them to reach a 50% chance of a single collision.

Practice questions

What does this print?

UUID id = UUID.fromString(
    "123e4567-e89b-42d3-a456-556642440000");
System.out.println(id.version());
System.out.println(id.toString().length());
  1. 4 36
  2. 1 32
  3. 4 32
  4. 2 36
Check your answer

4 36. The first digit of the third group (42d3) is the version: 4. The text form is 32 hex digits plus 4 dashes = 36 characters.

What does this print?

void main() throws Exception {
    var md = MessageDigest.getInstance("SHA-256");
    byte[] h = md.digest("hi".getBytes());
    System.out.println(h.length);
    String hex = HexFormat.of().formatHex(h);
    System.out.println(hex.length());
}
  1. 2 4
  2. 32 64
  3. 256 64
  4. 64 32
Check your answer

32 64. SHA-256 always produces 256 bits = 32 bytes, no matter the input size. Each byte is two hex characters, giving 64.

Next: the same code, two countries, two answers — Locale and the famous Turkish "I".