You paste an Ethereum address into a SHA-3 library, run the verification against a known Keccak-256 hash, and the bytes come back wrong. Not obviously wrong, either. The output looks plausible, the algorithm name is almost right, and the code runs clean with no exceptions thrown. That specific flavor of silent wrongness has quietly broken more than a few Ethereum tooling projects, and the explanation is, at its root, bureaucratic.

Ethereum adopted Keccak-256 before NIST finished standardizing it. NIST then changed the padding scheme in the final spec. Same sponge, different padding, different output. The two algorithms are siblings, not twins.

The sponge construction, in one paragraph

Both algorithms are built on a structure called a sponge. You feed input into a fixed-size state (1600 bits), absorbing it in chunks through a permutation function called Keccak-f. Once all the input is absorbed, you squeeze output bytes out of the state. The permutation itself, the five-step theta-rho-pi-chi-iota round applied 24 times, is identical between Keccak-256 and SHA-3-256. The rate is the same: 1088 bits. The capacity is the same: 512 bits. If you fed both algorithms an identical sequence of bits, they would run the same internal math on the same state.

Except they don't receive identical bits.

Before any of that math runs, the input gets padded to a block boundary, and this is where the two algorithms split. Think of it like two water mains built from the same pipe spec but fitted with different couplings at the source: everything downstream is identical, but the flow never meets.

Keccak's original NIST submission used a padding rule called multi-rate padding, sometimes written as pad10*1. It appends a single 1 bit, then as many 0 bits as needed, then a final 1 bit. During the standardization process that concluded with FIPS 202, NIST added a two-bit domain separation suffix (0x06) before applying that same multi-rate padding. The intent was sound: domain separation lets you safely use the same permutation for hashing, extendable-output functions (the XOFs called SHAKE128 and SHAKE256), and other modes, so outputs from one mode can't be mistaken for another. The suffix for plain SHA-3 is 0x06; for SHAKE it's 0x1F. Keccak-256 as Ethereum uses it applies 0x01 instead, the original submission's suffix.

One byte of difference in the padding. Completely different 256-bit output.

Why Ethereum never updated

The early Ethereum developers chose Keccak-256 before FIPS 202 was published. The Yellow Paper formalized the hash function as the original Keccak submission. By the time the standard diverged, Ethereum's address format, its transaction hashing, its Merkle Patricia Trie, and its EVM opcode KECCAK256 (originally, confusingly, named SHA3 in the bytecode) were all built on the pre-NIST variant. Changing the hash function at that point would have meant changing which blocks were valid: a hard fork, pure chaos, zero gain.

So the ecosystem froze on Keccak-256. The EVM opcode is still called SHA3 in older documentation. Solidity exposes it as keccak256(). The split is permanent, and honestly, that was the right call. You don't re-lay the pipes because the fitting standard got updated after construction.

The scenario that actually bites people is straightforward to describe and maddeningly easy to stumble into. Two developers, Priya and Marcus, are both building Ethereum signature verification tools. Priya reaches for Python's standard library, calls hashlib.sha3_256(), and gets FIPS 202 output. Marcus finds a library explicitly named pysha3 that implements the pre-standard Keccak and calls sha3.keccak_256(). Their outputs for the same input will differ in essentially every bit. Priya's code will fail to verify any real Ethereum transaction. Marcus's will work. The library name is the only visible difference in their code, and there's no error message to point the way.

The caveat worth keeping close

Some developers assume that because the padding difference is small, the security properties must differ meaningfully too. They don't. Both variants inherit the same collision resistance and preimage resistance from the Keccak-f permutation. The 256-bit output gives roughly 128 bits of collision resistance by the birthday bound, and neither padding scheme weakens that. The domain separation NIST added is a feature for multi-mode deployments, not a patch for a flaw.

Keccak-256 is not broken. It is not weakened. It is simply a slightly older member of the same family, and conflating it with SHA-3 is a category error, not a security instinct.

What's actually dangerous is the naming confusion. A developer who reaches for any library advertising "SHA-3" without checking whether it implements FIPS 202 or the original Keccak submission will silently produce wrong hashes. No error. No exception. Just incorrect bytes that will never match an on-chain value. So: when you're auditing Ethereum tooling, do you actually know which variant the hashing dependency implements? Check the library, not the label.

Found it labeled correctly? You're already ahead of a surprising number of production codebases.