Web3j is 8 MB. My APK is 4.5 MB. So I wrote the Ethereum hash function from scratch.
Why Not Just Import Web3j?
I was building a native Ethereum wallet inside an Android Capacitor app. The goal: sign transactions without MetaMask, without WalletConnect, without any external app.
Web3j handles everything — key generation, signing, ABI encoding, RLP. But it pulls in 8+ MB of dependencies. My entire APK is 4.5 MB.
So I implemented Keccak256 directly. 200 lines of Kotlin. Zero dependencies beyond what Android already ships.
What Is Keccak256?
Ethereum uses Keccak-256, a variant of SHA-3. It's a sponge construction — data is absorbed in 136-byte blocks, then squeezed out as a 32-byte hash.
The core is Keccak-f[1600]: 24 rounds of five transformation steps on a 5×5 matrix of 64-bit words.
The Round Constants
Each round XORs a different constant into the first lane. These overflow Long.MAX_VALUE in Kotlin, so they must be expressed as signed two's complement:
private val RC = longArrayOf(
0x0000000000000001L,
0x0000000000008082L,
-0x7fffffff7fff7f76L, // 0x800000000000808A
-0x7fffffff80008000L, // 0x8000000080008000
// ... 20 more
)
The Five Steps
Theta: XOR parity into each lane.
Rho+Pi: Rotate and permute in one pass.
Chi: Non-linear row mixing.
Iota: XOR round constant.
All implemented with primitive LongArray operations — no objects, no allocations inside the round loop.
Results
| Approach | Size Impact | Dependencies |
|---|---|---|
| Web3j | +8 MB | Full Web3j stack |
| ethers.js via WebView | +800 KB | JS bridge |
| Pure Kotlin | +18 KB | Zero |
The entire crypto layer — Keccak256, RLP encoder, ECDSA wrapper — fits in under 50 KB. No Gradle dependency beyond BouncyCastle, which Android ships natively.
Sometimes the best library is the one you don't import.
📂 Source: AtlasNexusTech/ai2work-android





















