Running bitcoin 30
#include <sodium.h> #include <iostream> #include <string> #include <vector> static void die(const char* m){ std::cerr << m << "\n"; std::exit(1); } static std::vector<unsigned char> hex2bin(const std::string& hex){ std::vector<unsigned char> out(hex.size()/2); size_t bin_len=0; if (sodium_hex2bin(out.data(), out.size(), hex.c_str(), hex.size(), nullptr, &bin_len, nullptr) != 0) die("bad hex"); out.resize(bin_len); return out; } int main(int argc, char** argv){ if (sodium_init() < 0) die("sodium_init failed"); bool decrypt=false; int argi=1; if (argc>=2 && std::string(argv[1])=="-d"){ decrypt=true; argi=2; } if ((decrypt && argc-argi!=2) || (!decrypt && argc-argi!=2)){ std::cerr << "Usage:\n Encrypt: " << argv[0] << " <message> <privkey_hex>\n" << " Decrypt: " << argv[0] << " -d <base64> <privkey_hex>\n"; return 1; } std::string a = argv[argi]; std::string priv_hex = argv[argi+1]; auto priv = hex2bin(priv_hex); if (priv.size()!=32) die("privkey must be 32 bytes (64 hex chars)"); // Key derivation: k = BLAKE2b("BTC-LOVE-1" || privkey) const std::string ctx = "BTC-LOVE-1"; std::vector<unsigned char> k(crypto_aead_xchacha20poly1305_ietf_KEYBYTES); crypto_generichash_state st; crypto_generichash_init(&st, nullptr, 0, k.size()); crypto_generichash_update(&st, reinterpret_cast<const unsigned char*>(ctx.data()), ctx.size()); crypto_generichash_update(&st, priv.data(), priv.size()); crypto_generichash_final(&st, k.data(), k.size()); if (!decrypt){ const size_t NONCE_LEN = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES; // 24 std::vector<unsigned char> nonce(NONCE_LEN); randombytes_buf(nonce.data(), nonce.size()); const unsigned char* ad = reinterpret_cast<const unsigned char*>("Chief Hodler"); const size_t ad_len = 12; const unsigned char* msg = reinterpret_cast<const unsigned char*>(a.data()); size_t mlen = a.size(); std::vector<unsigned char> ct(mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES); unsigned long long clen=0; if (crypto_aead_xchacha20poly1305_ietf_encrypt( ct.data(), &clen, msg, mlen, ad, ad_len, nullptr, nonce.data(), k.data()) != 0) die("encrypt failed"); ct.resize(clen); // package: nonce || ct std::vector<unsigned char> pack; pack.reserve(nonce.size()+ct.size()); pack.insert(pack.end(), nonce.begin(), nonce.end()); pack.insert(pack.end(), ct.begin(), ct.end()); // base64 size_t b64_len = sodium_base64_ENCODED_LEN(pack.size(), sodium_base64_VARIANT_ORIGINAL); std::vector<char> b64(b64_len); sodium_bin2base64(b64.data(), b64.size(), pack.data(), pack.size(), sodium_base64_VARIANT_ORIGINAL); std::cout << b64.data() << "\n"; } else { // input is base64 pack const std::string b64 = a; std::vector<unsigned char> pack(b64.size()); size_t pack_len=0; if (sodium_base642bin(pack.data(), pack.size(), b64.c_str(), b64.size(), nullptr, &pack_len, nullptr, sodium_base64_VARIANT_ORIGINAL) != 0) die("bad base64"); pack.resize(pack_len); const size_t NONCE_LEN = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES; if (pack.size() < NONCE_LEN + crypto_aead_xchacha20poly1305_ietf_ABYTES) die("cipher too short"); std::vector<unsigned char> nonce(pack.begin(), pack.begin()+NONCE_LEN); std::vector<unsigned char> ct(pack.begin()+NONCE_LEN, pack.end()); const unsigned char* ad = reinterpret_cast<const unsigned char*>("Chief Hodler"); const size_t ad_len = 12; std::vector<unsigned char> pt(ct.size()); unsigned long long plen=0; if (crypto_aead_xchacha20poly1305_ietf_decrypt( pt.data(), &plen, nullptr, ct.data(), ct.size(), ad, ad_len, nonce.data(), k.data()) != 0) die("decryption failed (wrong key or corrupted data)"); pt.resize(plen); std::cout.write(reinterpret_cast<const char*>(pt.data()), pt.size()); std::cout << "\n"; } return 0; }
image
Show your face
Bitcoin is a machine that turns energy + time + game theory into immutable history.
Time and space, the sun, consciousness - all are real gods, although the correct order of their importance remains a mystery.
image
Building stuff with Nostr 🙂
I love code