Base64 Input

Hex Output

Success
Warning

The same bytes, written two different ways

This one is almost never about conversion for its own sake. It is about a mismatch: you have a checksum from one place and a checksum from another, they look nothing alike, and you need to know whether the file is corrupt or the two systems simply chose different notation. S3 hands you an ETag in hex and a Content-MD5 header in Base64 for the same object. A certificate fingerprint from openssl is colon-separated hex; the same key in a JWK is Base64. Neither pairing is comparable by eye.

Paste the Base64 on the left and the hex appears on the right. If you have the value you are checking against, put it in the compare box under the output and the page tells you whether the bytes are identical rather than making you scan 32 characters.

Two encodings, one purpose. Hex spends two characters on every byte, so it is exactly twice the size and trivially readable a byte at a time — which is why hex dumps, fingerprints and sha256sum use it. Base64 spends four characters on every three bytes, about 33% overhead instead of 100%, which is why headers and JSON fields use it. RFC 4648 defines both in the same document, which tells you they were always meant as alternatives for the same job.

The byte count is the other thing worth reading. A digest has a fixed size, so 16 bytes means MD5, 20 means SHA-1, 32 means SHA-256 and 64 means SHA-512 — when someone hands you an unlabelled hash, the length is usually enough to identify it. Treat it as evidence rather than proof, though: a UUID is also 16 bytes, and so is any other sixteen bytes. The chip says "MD5 length" rather than "MD5" for that reason.

Converting and comparing

  1. Paste the Base64 valueA Content-MD5 header, a digest field, an SRI hash with its sha384- prefix removed. Padding, the URL-safe alphabet and wrapped lines are all handled. Sample loads a real Content-MD5.
  2. Read the hex and the byte countThe chip beside the title names the digest when the length matches a known one. That is often the answer on its own — "32 bytes, so it is a SHA-256" resolves most unlabelled-hash questions.
  3. Pick the shape you needLowercase with no separator is what sha256sum, git and most APIs produce. Uppercase with colons is the openssl x509 -fingerprint shape, and it is what you paste into a certificate pinning config.
  4. Compare against the other valuePut the hex you are checking against into the compare box. It says match or differ, and states which way it read your input — because a string like deadbeef is valid hex and valid Base64, and knowing which reading was used is the difference between an answer and a puzzle.

If the byte counts differ, stop comparing and look at the lengths. A 16-byte value against a 32-byte one is not a corrupted file — it is an MD5 being compared against a SHA-256, which happens constantly when a config was migrated and one side still specifies the old algorithm. The compare box prints both counts on a mismatch for exactly this reason.

One S3 object, two checksums that look unrelated

Both of these describe the same 16 bytes. The header carries the MD5 in Base64 because RFC 1864 specifies it that way; the ETag prints the same digest in hex. Convert one and they line up exactly.

Content-MD5 → ETag same 16 bytes
response headersTwo notations
# what S3 returns in the header
Content-MD5: Q+FQWTHCcLSnXVe40Le1tQ==

# what the same object's ETag says
ETag: "43e1505931c270b4a75d57b8d0b7b5b5"

# 24 characters vs 32. same 16 bytes.
hexNow comparable
43e1505931c270b4a75d57b8d0b7b5b5

# 16 bytes -> the right length for an MD5

# colon form, for openssl fingerprints:
43:E1:50:59:31:C2:70:B4:
A7:5D:57:B8:D0:B7:B5:B5

When this comes up

Checking an upload actually arrived intact

You computed an MD5 locally, sent it as Content-MD5, and the storage service reports an ETag. One is Base64 and one is hex, so confirming they agree needs a conversion. Worth knowing that a multipart S3 upload produces an ETag ending in -N, which is a digest of digests and will never match a plain MD5 of the file.

Comparing a certificate fingerprint

Browsers and openssl show fingerprints as colon-separated uppercase hex; monitoring tools and pinning configs frequently store Base64. Converting one form settles whether the certificate in front of you is the one you pinned, which is not a question to answer by squinting.

Reading a Subresource Integrity hash

An SRI attribute looks like sha384-oqVuAfXR…. Strip the algorithm prefix and the rest is Base64. Converting it to hex lets you compare it against a checksum published on a release page, which is almost always hex.

Making sense of a key or nonce from a config

Encryption keys, HMAC secrets and IVs get stored in whichever encoding the library that wrote them preferred. When the docs say "32-byte key" and your config holds a 44-character string, converting shows you it is a 32-byte value in Base64 and everything is fine.

What it does

  • Names the digest from its length. 16 bytes, 20, 28, 32, 48 and 64 map to MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512.
  • Compares two values properly. The compare box normalises both sides to bytes, so notation stops mattering — and it says which way it read an ambiguous input.
  • Three output shapes. Lowercase compact for tooling, uppercase for readability, colon-separated for certificate fingerprints.
  • Accepts Base64 in any state. URL-safe, unpadded, wrapped across lines, or with a data: prefix still attached.
  • Byte counts on a mismatch. Different lengths mean a different algorithm, not a corrupt file, and the page says so instead of just "no".
  • Nothing is uploaded. Keys and hashes stay in the tab.

Questions that come up

Why is the hex exactly twice as long?

Hex spends two characters on each byte — one per four bits — so the size is always doubled with no remainder. Base64 packs three bytes into four characters, so it grows by about a third. That difference is the whole reason both exist: hex is readable a byte at a time, Base64 is compact enough for a header.

My two values have different byte counts.

Then they are not the same kind of thing, and no amount of conversion will make them match. The usual cause is one side using MD5 (16 bytes) and the other SHA-256 (32) — a config that was half-migrated. Check which algorithm each system is configured for before assuming corruption.

The compare box says my values differ but they look identical.

Read the note underneath it. A value made only of the characters a-f and digits is valid hex and valid Base64, and the two readings give completely different bytes — deadbeef is 4 bytes as hex and 6 as Base64. This page reads the compare value as hex first, since that is what it produces, and tells you when it fell back.

Can I convert a hex string back?

Hex to Base64 goes the other way, and it accepts the colon-separated and 0x-prefixed forms as pasted.

Does this verify a hash?

No. It converts notation and compares two values you supply. Computing a digest from a file is a different operation — sha256sum at a terminal, or certutil -hashfile on Windows. This page is for when you already have two hashes and need to know whether they agree.

What about an odd-looking ETag with a dash in it?

That is a multipart upload. S3 concatenates the MD5 of every part, hashes that, and appends the part count — so d41d8cd9…-12 is a digest of digests and cannot equal the MD5 of the whole file. Amazon documents this, and it catches people out every time they switch to multipart uploads for large objects.

Related tools

Worth reading