SHA-256 in Base64: raw digest vs. hex text
A SHA-256 value encoded as Base64 can disagree with an API or another tool when the wrong bytes are encoded. The key distinction is between the 32-byte digest and its 64-character hexadecimal representation.
Try the example in the hash generatorCompare three representations derived from abc
The input is abc encoded as UTF-8, with no trailing newline and no HMAC key. SHA-256 produces 256 bits, or 32 bytes. Hex represents those bytes using hexadecimal digits; Base64 represents the same bytes using a different alphabet.
- Digest represented as hex 64 characters
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad- Base64 of the 32-byte digest 44 characters, including the final =
ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=- Base64 of the 64-character hex text 88 characters: a different value
YmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljYjQxMGZmNjFmMjAwMTVhZA==
Base64 is an encoding, not encryption. Decoding the second value gives the 32-byte digest, not the original abc. When an API requests a Base64 SHA-256 value, check which bytes its specification expects you to encode.
Encode the digest bytes in Python
digest() returns bytes; hexdigest() returns hex text. Pass the digest bytes to Base64. The final line encodes the hex text for comparison. The output matches the three examples above, in the same order.
import base64
import hashlib
message = "abc".encode("utf-8")
digest = hashlib.sha256(message).digest()
hex_text = digest.hex()
print(hex_text)
print(base64.b64encode(digest).decode("ascii"))
print(base64.b64encode(hex_text.encode("ascii")).decode("ascii"))
Convert an existing hex digest back to bytes first
If you have a 64-character SHA-256 hex value, use bytes.fromhex() to recover its 32 bytes before encoding them as Base64. Hashing the hex text again is another calculation, rather than a change in representation of the original digest.
import base64
hex_text = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
digest = bytes.fromhex(hex_text)
if len(digest) != 32:
raise ValueError("Expected a 32-byte SHA-256 digest")
print(base64.b64encode(digest).decode("ascii"))
This example allows whitespace between hex bytes. Non-hex characters or an odd number of hex digits raise ValueError. It also stops if the decoded length is not 32 bytes. Length alone does not establish that a value is a SHA-256 digest; check how it was generated.
Reproduce the result in the hash generator
- Enter abc in the text field, without trailing spaces or a newline. Leave the file input empty.
- Select only SHA-256 and leave the optional HMAC key empty.
- Select “Display in Base64” and press “Generate Hash”. The result has 44 characters and begins with ungWv48Bz+.
- Clear the Base64 option and generate again to get the 64-character hex value beginning with ba7816bf.
The SHA-256 calculation in these steps runs in your browser. Selecting SHA-512/256, SHA3-256, SHA3-512 or BLAKE2b also sends the text and any HMAC key to the server. Uploaded files are read as UTF-8 text, so this tool does not verify the original bytes of binary files such as images or ZIP archives.
Try the example in the hash generatorCheck the input bytes and output format when results differ
- Newlines and spaces
- abc, abc followed by LF, and abc followed by CRLF are different byte sequences. A trailing newline added by a command or editor is part of the input to the hash.
- Text encoding and BOM
- The same visible text has different bytes in UTF-8 and UTF-16. If the source contains a byte order mark, both calculations must agree on whether to include it. To compare original file bytes, read the file as binary rather than converting it to text.
- SHA-256 and HMAC-SHA-256
- HMAC uses a key and is a different calculation from ordinary SHA-256. If the protocol requires HMAC, the key bytes must match as well as the message bytes.
- Standard Base64 and Base64url
- Base64url uses - and _ in place of the standard Base64 characters + and /. Follow the receiving specification on whether to omit the final = padding. The hash tool produces standard Base64; this example ends in one =.