Skip to content

Instantly share code, notes, and snippets.

@thecompez
Last active November 26, 2025 12:56
Show Gist options
  • Select an option

  • Save thecompez/d63b38f8d9900d27719074f481b3a653 to your computer and use it in GitHub Desktop.

Select an option

Save thecompez/d63b38f8d9900d27719074f481b3a653 to your computer and use it in GitHub Desktop.
Keccak-256-Cpp
module;
import <array>;
import <string>;
import <string_view>;
import <iostream>;
import <algorithm>;
import <cctype>;
import <sstream>;
import <iomanip>;
import <concepts>;
import <vector>;
export module eth.checksum;
/* ========================= Utility ========================= */
constexpr int hexCharToInt(const char c) noexcept {
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'a' && c <= 'f') return c - 'a' + 10;
if(c >= 'A' && c <= 'F') return c - 'A' + 10;
return 0;
}
constexpr char safeToUpper(const char c) noexcept {
if(c >= 'a' && c <= 'z') return c - 'a' + 'A';
return c;
}
constexpr char safeToLower(const char c) noexcept {
if(c >= 'A' && c <= 'Z') return c - 'A' + 'a';
return c;
}
/* ========================= Keccak-256 Implementation ========================= */
export class Keccak256 {
static constexpr std::array<uint64_t, 24> RC = {
0x0000000000000001ULL,0x0000000000008082ULL,0x800000000000808aULL,0x8000000080008000ULL,
0x000000000000808bULL,0x0000000080000001ULL,0x8000000080008081ULL,0x8000000000008009ULL,
0x000000000000008aULL,0x0000000000000088ULL,0x0000000080008009ULL,0x000000008000000aULL,
0x000000008000808bULL,0x800000000000008bULL,0x8000000000008089ULL,0x8000000000008003ULL,
0x8000000000008002ULL,0x8000000000000080ULL,0x000000000000800aULL,0x800000008000000aULL,
0x8000000080008081ULL,0x8000000000008080ULL,0x0000000080000001ULL,0x8000000080008008ULL
};
static constexpr uint64_t ROL(const uint64_t x, const uint8_t n) noexcept {
return (x << n) | (x >> (64 - n));
}
public:
static std::string hash(const std::string_view input) {
constexpr size_t r = 136;
uint64_t st[5][5]{};
std::string msg(input);
msg.push_back(0x01);
while((msg.size() % r) != r - 1) msg.push_back(0x00);
msg.push_back(0x80);
for(size_t o = 0; o < msg.size(); o += r) {
for(int i=0;i<17;i++){
uint64_t v=0;
for(int b=0;b<8;b++) v|= static_cast<uint64_t>(static_cast<uint8_t>(msg[o + i * 8 + b])) <<(8*b);
st[i%5][i/5]^=v;
}
for(int rnd=0;rnd<24;rnd++){
uint64_t B[5][5]{}, C[5]{}, D[5]{};
for(int x=0;x<5;x++)
C[x]=st[x][0]^st[x][1]^st[x][2]^st[x][3]^st[x][4];
for(int x=0;x<5;x++)
D[x]=C[(x+4)%5]^ROL(C[(x+1)%5],1);
for(int x=0;x<5;x++)
for(int y=0;y<5;y++)
st[x][y]^=D[x];
constexpr uint8_t ROTC[5][5]={
{ 0,36, 3,41,18},{ 1,44,10,45, 2},{62, 6,43,15,61},
{28,55,25,21,56},{27,20,39, 8,14}
};
for(int x=0;x<5;x++)
for(int y=0;y<5;y++)
B[y][(2*x+3*y)%5]=ROL(st[x][y],ROTC[x][y]);
for(int x=0;x<5;x++)
for(int y=0;y<5;y++)
st[x][y]=B[x][y]^((~B[(x+1)%5][y])&B[(x+2)%5][y]);
st[0][0]^=RC[rnd];
}
}
std::ostringstream out;
for(int i=0;i<4;i++){
uint64_t v=st[i%5][i/5];
for(int b=0;b<8;b++)
out << std::hex << std::setfill('0') << std::setw(2) << ((v >> (8*b)) & 0xff);
}
return out.str();
}
};
/* ========================= EIP-55 Checksum ========================= */
export template<typename T>
concept StringLike = requires(T a) { { std::string(a) } -> std::convertible_to<std::string>; };
export template<StringLike S>
std::string toChecksum(S address) {
std::string addr(address);
if(addr.rfind("0x",0)==0) addr=addr.substr(2);
std::string lower;
lower.reserve(addr.size());
for (const char c : addr)
lower += safeToLower(c);
const std::string hash=Keccak256::hash(lower);
std::string out;
out.reserve(addr.size());
for(size_t i=0;i<lower.size();i++){
if(std::isalpha(lower[i]) && hexCharToInt(hash[i]) >= 8)
out += safeToUpper(lower[i]);
else
out += lower[i];
}
return "0x"+out;
}
Usage example:
import eth.checksum;
auto main() -> int {
std::vector<std::string> addresses = {
"0x...",
"0x..."
};
for(const auto &a : addresses) {
std::cout << "Checksum: " << toChecksum(a) << "\n";
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment