wiped scalars on destruction, and added extended public keys to unit_test.cpp

This commit is contained in:
Cheng 2024-08-02 05:36:07 +00:00
parent 133b7d27c8
commit ba84172bbd
No known key found for this signature in database
8 changed files with 38 additions and 34 deletions

View File

@ -56,7 +56,6 @@ namespace ro {
auto st = (*this)->Isqlite3_column_blob(i); auto st = (*this)->Isqlite3_column_blob(i);
if (st.size_bytes() != sizeof(T)) throw BadDataException(); if (st.size_bytes() != sizeof(T)) throw BadDataException();
static_assert (std::is_standard_layout<T>(), "not standard layout"); static_assert (std::is_standard_layout<T>(), "not standard layout");
static_assert (std::is_trivial<T>(), "not trivial");
return reinterpret_cast<const T*>(&st[0]); return reinterpret_cast<const T*>(&st[0]);
} }
else if constexpr (std::is_integral<T>::value) { else if constexpr (std::is_integral<T>::value) {

View File

@ -21,7 +21,7 @@ namespace ristretto255 {
point point::ptBase({ 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}); 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, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }); 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 });
const scalar& scalar::scOrder{ curveOrder }; const scalar& scalar::scOrder{ curveOrder };

View File

@ -334,7 +334,7 @@ namespace ristretto255 {
std::array<uint8_t, crypto_core_ristretto255_SCALARBYTES> blob; std::array<uint8_t, crypto_core_ristretto255_SCALARBYTES> blob;
static_assert(sizeof(blob) == 32, "watch for size and alignment bugs. Everyone should standarize on 256 bit secret keys except for special needs"); 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; explicit scalar() = default;
~scalar() = default; ~scalar() noexcept { wxSecretValue::Wipe(sizeof(*this), this); }
explicit constexpr scalar(std::array<uint8_t, crypto_core_ristretto255_BYTES>&& in) : blob{ in } {}; explicit constexpr scalar(std::array<uint8_t, crypto_core_ristretto255_BYTES>&& in) : blob{ in } {};
explicit constexpr scalar(std::array<uint8_t, crypto_core_ristretto255_BYTES>* in) :blob(*in) {}; explicit constexpr scalar(std::array<uint8_t, crypto_core_ristretto255_BYTES>* in) :blob(*in) {};
explicit constexpr scalar(uintmax_t k){ for (auto& j : blob) { j = k; k = k >> 8; } } 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 // and DBL_MANT_DIG
static_assert(sizeof(decltype(ro::serialize(std::declval<scalar>())[0])) == 1); static_assert(sizeof(decltype(ro::serialize(std::declval<scalar>())[0])) == 1);
static_assert (std::is_standard_layout<scalar>(), "scalar for some reason is not standard layout"); static_assert (std::is_standard_layout<scalar>(), "scalar for some reason is not standard layout");
static_assert (std::is_trivial<scalar>(), "scalar for some reason is not trivial");
static_assert(sizeof(point) == 32, "funny alignment"); static_assert(sizeof(point) == 32, "funny alignment");
static_assert(sizeof(scalar) == 32, "funny alignment"); static_assert(sizeof(scalar) == 32, "funny alignment");

View File

@ -63,26 +63,26 @@ ristretto255::scalar DeriveSecret(const scalar &sc, uint_fast64_t i) {
} }
namespace ristretto255 { namespace ristretto255 {
extended_private_key::extended_private_key(extended_private_key& parent, std::span<byte> path) : extended_private_key::extended_private_key(extended_private_key& parent, std::span<byte> path) noexcept:
privatekey(parent.privatekey* scalar(hash<512>(parent.chain, path))), privatekey(parent.privatekey* scalar(hash<512>(parent.chain, path))),
chain(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), privatekey(s),
chain(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_private_key(DeriveStrongSecretHash(passwd))
{}; {};
extended_public_key::extended_public_key(extended_public_key& parent, std::span<byte> path) : extended_public_key::extended_public_key(extended_public_key& parent, std::span<byte> path) noexcept :
publickey(parent.publickey* scalar(hash<512>(parent.chain, path))), publickey(parent.publickey* scalar(hash<512>(parent.chain, path))),
chain(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() }, publickey{ p.privatekey.timesBase() },
chain{ p.chain } chain{ p.chain }
{}; {};

View File

@ -29,16 +29,16 @@ namespace ristretto255 {
Also, the BIP0032 -- BIP0044 extended keys use 32 bitunsigned integers Also, the BIP0032 -- BIP0044 extended keys use 32 bitunsigned integers
for the path, but since I want to allow names, among other things, for the path, but since I want to allow names, among other things,
I use spans of bytes. */ I use spans of bytes. */
extended_private_key(hash<512>&&); extended_private_key(hash<512>&&)noexcept;
public: public:
static constexpr bool is_machine_independent() { return true; };
scalar privatekey; scalar privatekey;
hash<256> chain; hash<256> chain;
static constexpr unsigned int type_indentifier = 3; static constexpr unsigned int type_indentifier = 3;
public: public:
extended_private_key()=default; extended_private_key()=default;
extended_private_key(extended_private_key& parent, std::span<byte> path); extended_private_key(extended_private_key& parent, std::span<byte> path) noexcept;
extended_private_key(const char* const passwd); extended_private_key(const char* const passwd) noexcept;
~extended_private_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); }
template<class T> auto operator()(T psz) { template<class T> auto operator()(T psz) {
return privatekey*scalar(hash<512>(chain, 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 /* This is the same name and concept as BIP0032 and BIP0044 extended private
and public keys, and used for the same purpose, to deterministically 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 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: public:
static constexpr bool is_machine_independent() { return true; };
point publickey; point publickey;
hash<256> chain; hash<256> chain;
static constexpr unsigned int type_indentifier = 4; static constexpr unsigned int type_indentifier = 4;
extended_public_key()=default; extended_public_key()=default;
extended_public_key(extended_public_key& parent, std::span<byte> path); extended_public_key(extended_public_key& parent, std::span<byte> path) noexcept;
extended_public_key(extended_private_key&); extended_public_key(extended_private_key&) noexcept;
~extended_public_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); }
template<class T> auto operator()(T psz) { template<class T> auto operator()(T psz) {
scalar& t(*this); scalar& t(*this);
return publickey * scalar(hash<512>(chain, psz)); 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)); static_assert(sizeof(extended_public_key) == sizeof(hash<256>) + sizeof(point));

View File

@ -24,24 +24,16 @@
*tsz = '\0'; *tsz = '\0';
} }
} }
operator char* () & { operator char* () {
char* pc = &(static_cast<std::array<char, stringlen + 1>*>(this)->operator[](0)); char* pc = (char*)this;
return pc; return pc;
} }
operator const char* () {
operator const char* () const& { const char* pc = (const char*)this;
const char* pc = &(static_cast<const std::array<char, stringlen + 1>*>(this)->operator[](0));
return pc; return pc;
} }
operator const char* () const&& { operator std::string() {
const char* pc = &(static_cast<const std::array<char, stringlen + 1>*>(this)->operator[](0)); return std::string((const char*)this);
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 wxString() const& { operator wxString() const& {
return wxString::FromUTF8Unchecked((const char*)(*this)); return wxString::FromUTF8Unchecked((const char*)(*this));
@ -50,7 +42,7 @@
return std::span<byte>(static_cast<std::nullptr_t>((char*)*this), stringlen + 1); return std::span<byte>(static_cast<std::nullptr_t>((char*)*this), stringlen + 1);
} }
operator wxString() const&& { operator wxString() const&& {
return wxString::FromUTF8Unchecked((const char*)(*this)); return wxString::FromUTF8Unchecked((const char*)(this));
} }
operator std::span<byte>() const&& { operator std::span<byte>() const&& {
return std::span<byte>(static_cast<std::nullptr_t>((char*)*this), stringlen + 1); return std::span<byte>(static_cast<std::nullptr_t>((char*)*this), stringlen + 1);

View File

@ -25,6 +25,7 @@ constexpr bool b_WINDOWS = false;
#endif #endif
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/modalhook.h> #include <wx/modalhook.h>
#include <wx/secretstore.h>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <array> #include <array>

View File

@ -641,16 +641,27 @@ namespace ristretto255 {
{ auto start_time{ std::chrono::high_resolution_clock::now() }; { auto start_time{ std::chrono::high_resolution_clock::now() };
extended_private_key s1(&text_secret[0]); extended_private_key s1(&text_secret[0]);
auto end_time{ std::chrono::high_resolution_clock::now() }; 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); wxLogMessage("\t\textended private key: %s", str_s1);
const char* str_s2 = "jyRioJfob242toZDETkd7nG4YW6oYeGBEVEw4KLGWZaJfCPV2hQbT3AFUcnu6ZXEvDPPpSmM5ivMJ2awJxSBS5DoE"; const char* str_s2 = "jyRioJfob242toZDETkd7nG4YW6oYeGBEVEw4KLGWZaJfCPV2hQbT3AFUcnu6ZXEvDPPpSmM5ivMJ2awJxSBS5DoE";
if (str_s2 != str_s1) { 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<extended_private_key>::bin(str_s2); auto s2 = base58<extended_private_key>::bin(str_s2);
if (s1 != s2) { if (s1 != s2) {
throw MyException("Round trip for extended_private_key to and from base 58 representation failed", __LINE__, __func__, SrcFilename); 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<extended_public_key>::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<std::chrono::microseconds> (end_time - start_time) }; auto time_taken{ std::chrono::duration_cast<std::chrono::microseconds> (end_time - start_time) };
wxLogMessage("\t\tStrong secret extended private key derivation took %lld microseconds", time_taken.count()); wxLogMessage("\t\tStrong secret extended private key derivation took %lld microseconds", time_taken.count());
} }