From ba84172bbd9dcc388163777d39e2d902da5fb19d Mon Sep 17 00:00:00 2001 From: Cheng Date: Fri, 2 Aug 2024 05:36:07 +0000 Subject: [PATCH] wiped scalars on destruction, and added extended public keys to unit_test.cpp --- src/db_accessors.h | 1 - src/ristretto255.cpp | 2 +- src/ristretto255.h | 3 +-- src/secrets.cpp | 10 +++++----- src/secrets.h | 18 ++++++++++-------- src/serialization.h | 22 +++++++--------------- src/stdafx.h | 1 + src/unit_test.cpp | 15 +++++++++++++-- 8 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/db_accessors.h b/src/db_accessors.h index 9759d42..e732aa5 100644 --- a/src/db_accessors.h +++ b/src/db_accessors.h @@ -56,7 +56,6 @@ namespace ro { auto st = (*this)->Isqlite3_column_blob(i); if (st.size_bytes() != sizeof(T)) throw BadDataException(); static_assert (std::is_standard_layout(), "not standard layout"); - static_assert (std::is_trivial(), "not trivial"); return reinterpret_cast(&st[0]); } else if constexpr (std::is_integral::value) { diff --git a/src/ristretto255.cpp b/src/ristretto255.cpp index 620610a..e58cbf9 100644 --- a/src/ristretto255.cpp +++ b/src/ristretto255.cpp @@ -21,7 +21,7 @@ namespace ristretto255 { point point::ptBase({ 0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71, 0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f, 0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d, 0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76}); - static constexpr scalar curveOrder({ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, + static const scalar curveOrder({ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }); const scalar& scalar::scOrder{ curveOrder }; diff --git a/src/ristretto255.h b/src/ristretto255.h index 2b92041..2247bc3 100644 --- a/src/ristretto255.h +++ b/src/ristretto255.h @@ -334,7 +334,7 @@ namespace ristretto255 { std::array blob; static_assert(sizeof(blob) == 32, "watch for size and alignment bugs. Everyone should standarize on 256 bit secret keys except for special needs"); explicit scalar() = default; - ~scalar() = default; + ~scalar() noexcept { wxSecretValue::Wipe(sizeof(*this), this); } explicit constexpr scalar(std::array&& in) : blob{ in } {}; explicit constexpr scalar(std::array* in) :blob(*in) {}; explicit constexpr scalar(uintmax_t k){ for (auto& j : blob) { j = k; k = k >> 8; } } @@ -480,7 +480,6 @@ namespace ristretto255 { // and DBL_MANT_DIG static_assert(sizeof(decltype(ro::serialize(std::declval())[0])) == 1); static_assert (std::is_standard_layout(), "scalar for some reason is not standard layout"); - static_assert (std::is_trivial(), "scalar for some reason is not trivial"); static_assert(sizeof(point) == 32, "funny alignment"); static_assert(sizeof(scalar) == 32, "funny alignment"); diff --git a/src/secrets.cpp b/src/secrets.cpp index 6e8c8b5..07f3567 100644 --- a/src/secrets.cpp +++ b/src/secrets.cpp @@ -63,26 +63,26 @@ ristretto255::scalar DeriveSecret(const scalar &sc, uint_fast64_t i) { } namespace ristretto255 { - extended_private_key::extended_private_key(extended_private_key& parent, std::span path) : + extended_private_key::extended_private_key(extended_private_key& parent, std::span path) noexcept: privatekey(parent.privatekey* scalar(hash<512>(parent.chain, path))), chain(parent.chain, path) {}; - extended_private_key::extended_private_key(hash<512>&& s) : + extended_private_key::extended_private_key(hash<512>&& s) noexcept : privatekey(s), chain(s) {}; - extended_private_key::extended_private_key(const char* const passwd) : + extended_private_key::extended_private_key(const char* const passwd) noexcept : extended_private_key(DeriveStrongSecretHash(passwd)) {}; - extended_public_key::extended_public_key(extended_public_key& parent, std::span path) : + extended_public_key::extended_public_key(extended_public_key& parent, std::span path) noexcept : publickey(parent.publickey* scalar(hash<512>(parent.chain, path))), chain(parent.chain, path) {}; - extended_public_key::extended_public_key(extended_private_key& p) : + extended_public_key::extended_public_key(extended_private_key& p) noexcept : publickey{ p.privatekey.timesBase() }, chain{ p.chain } {}; diff --git a/src/secrets.h b/src/secrets.h index 213d0a2..b3ffad8 100644 --- a/src/secrets.h +++ b/src/secrets.h @@ -29,16 +29,16 @@ namespace ristretto255 { Also, the BIP0032 -- BIP0044 extended keys use 32 bitunsigned integers for the path, but since I want to allow names, among other things, I use spans of bytes. */ - extended_private_key(hash<512>&&); + extended_private_key(hash<512>&&)noexcept; public: - static constexpr bool is_machine_independent() { return true; }; scalar privatekey; hash<256> chain; static constexpr unsigned int type_indentifier = 3; public: extended_private_key()=default; - extended_private_key(extended_private_key& parent, std::span path); - extended_private_key(const char* const passwd); + extended_private_key(extended_private_key& parent, std::span path) noexcept; + extended_private_key(const char* const passwd) noexcept; + ~extended_private_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); } template auto operator()(T psz) { return privatekey*scalar(hash<512>(chain, psz)); } @@ -51,19 +51,21 @@ namespace ristretto255 { /* This is the same name and concept as BIP0032 and BIP0044 extended private and public keys, and used for the same purpose, to deterministically create a hierarchical tree of secrets each defined by a path from the master - extended key, but utterly incompatible */ + extended key, but utterly incompatible. + */ public: - static constexpr bool is_machine_independent() { return true; }; point publickey; hash<256> chain; static constexpr unsigned int type_indentifier = 4; extended_public_key()=default; - extended_public_key(extended_public_key& parent, std::span path); - extended_public_key(extended_private_key&); + extended_public_key(extended_public_key& parent, std::span path) noexcept; + extended_public_key(extended_private_key&) noexcept; + ~extended_public_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); } template auto operator()(T psz) { scalar& t(*this); return publickey * scalar(hash<512>(chain, psz)); } + bool operator==(const extended_public_key& pt) const& { return this->publickey == pt.publickey && this->chain == pt.chain; } }; static_assert(sizeof(extended_public_key) == sizeof(hash<256>) + sizeof(point)); diff --git a/src/serialization.h b/src/serialization.h index a026d88..4ea27e2 100644 --- a/src/serialization.h +++ b/src/serialization.h @@ -24,24 +24,16 @@ *tsz = '\0'; } } - operator char* () & { - char* pc = &(static_cast*>(this)->operator[](0)); + operator char* () { + char* pc = (char*)this; return pc; } - - operator const char* () const& { - const char* pc = &(static_cast*>(this)->operator[](0)); + operator const char* () { + const char* pc = (const char*)this; return pc; } - operator const char* () const&& { - const char* pc = &(static_cast*>(this)->operator[](0)); - return pc; - } - operator std::string() const& { - return std::string((const char*)*this, this->length); - } - operator std::string() const&& { - return std::string((const char*)*this, this->length); + operator std::string() { + return std::string((const char*)this); } operator wxString() const& { return wxString::FromUTF8Unchecked((const char*)(*this)); @@ -50,7 +42,7 @@ return std::span(static_cast((char*)*this), stringlen + 1); } operator wxString() const&& { - return wxString::FromUTF8Unchecked((const char*)(*this)); + return wxString::FromUTF8Unchecked((const char*)(this)); } operator std::span() const&& { return std::span(static_cast((char*)*this), stringlen + 1); diff --git a/src/stdafx.h b/src/stdafx.h index 558ff2e..b9b5757 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -25,6 +25,7 @@ constexpr bool b_WINDOWS = false; #endif #include #include +#include #include #include #include diff --git a/src/unit_test.cpp b/src/unit_test.cpp index 579b909..3fac73e 100644 --- a/src/unit_test.cpp +++ b/src/unit_test.cpp @@ -641,16 +641,27 @@ namespace ristretto255 { { auto start_time{ std::chrono::high_resolution_clock::now() }; extended_private_key s1(&text_secret[0]); auto end_time{ std::chrono::high_resolution_clock::now() }; - std::string str_s1{ &(base58(s1))[0] }; + std::string str_s1((char*)base58(s1) ); wxLogMessage("\t\textended private key: %s", str_s1); const char* str_s2 = "jyRioJfob242toZDETkd7nG4YW6oYeGBEVEw4KLGWZaJfCPV2hQbT3AFUcnu6ZXEvDPPpSmM5ivMJ2awJxSBS5DoE"; if (str_s2 != str_s1) { - throw MyException("unexpected value of private key", __LINE__, __func__, SrcFilename); + throw MyException("unexpected value of extended private key", __LINE__, __func__, SrcFilename); } auto s2 = base58::bin(str_s2); if (s1 != s2) { throw MyException("Round trip for extended_private_key to and from base 58 representation failed", __LINE__, __func__, SrcFilename); } + extended_public_key p1(s1); + std::string str_p1((char*)base58(p1)); + wxLogMessage("\t\textended public key: %s", str_p1); + const char* sz_p2 = "W7rr3Egaf9eqs6km7RfYSuh6ydxN2ucHe6iEm7P3YUcFzmirQFRJEQm8Q9KUiQMpZjz1Km6wD2GLgTWp8CBWQRLKo"; + if (sz_p2 != str_p1) { + throw MyException("unexpected value of extended public key", __LINE__, __func__, SrcFilename); + } + auto p2 = base58::bin(sz_p2); + if (p1 != p2) { + throw MyException("Round trip for extended_public_key to and from base 58 representation failed", __LINE__, __func__, SrcFilename); + } auto time_taken{ std::chrono::duration_cast (end_time - start_time) }; wxLogMessage("\t\tStrong secret extended private key derivation took %lld microseconds", time_taken.count()); }