Last active
November 26, 2025 12:56
-
-
Save thecompez/d63b38f8d9900d27719074f481b3a653 to your computer and use it in GitHub Desktop.
Keccak-256-Cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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