testing functionality of extended keys in unit_test.cpp

This commit is contained in:
Cheng 2024-08-04 05:07:37 +00:00
parent 295919fd69
commit 36343e69ba
No known key found for this signature in database
3 changed files with 92 additions and 21 deletions

View File

@ -63,15 +63,32 @@ 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) noexcept: extended_public_key::extended_public_key(point&& p, hash<256>&& h) :
publickey(p),
chain(h) {
};
extended_private_key::extended_private_key(scalar&& s, hash<256>&& h) :
privatekey(s),
chain(h) {
};
extended_private_key::~extended_private_key()noexcept {
wxSecretValue::Wipe(sizeof(*this), this);
};
extended_public_key::~extended_public_key()noexcept {
wxSecretValue::Wipe(sizeof(*this), this);
};
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) noexcept : 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) noexcept : extended_private_key::extended_private_key(const char* const passwd) noexcept :
extended_private_key(DeriveStrongSecretHash(passwd)) extended_private_key(DeriveStrongSecretHash(passwd))

View File

@ -14,6 +14,7 @@ constexpr int rounded_log2(const T val) noexcept {
} }
namespace ristretto255 { namespace ristretto255 {
class extended_public_key;
class extended_private_key { class extended_private_key {
/* 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
@ -30,22 +31,37 @@ namespace ristretto255 {
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>&&)noexcept; extended_private_key(hash<512>&&)noexcept;
extended_private_key(scalar&&, hash<256>&&);
public: public:
friend class extended_public_key;
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:
extended_private_key() = default; extended_private_key() = default;
extended_private_key(extended_private_key& parent, std::span<byte> path) noexcept; extended_private_key(extended_private_key& parent, std::span<byte> path) noexcept;
extended_private_key(const char* const passwd) noexcept; extended_private_key(const char* const passwd) noexcept;
~extended_private_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); } ~extended_private_key()noexcept;
template<class T> auto operator()(T psz) { template<class T> scalar operator()(T psz) {
return privatekey * scalar(hash<512>(chain, psz)); return privatekey * scalar(hash<512>(chain, psz));
} }
bool operator==(const extended_private_key& pt) const& { return this->privatekey == pt.privatekey && this->chain == pt.chain; } template<class T> scalar child_private_key(T psz) {
return this->operator()(psz);
}
template<class T> point child_public_key(T psz) {
return (this->child_private_key(psz)).timesBase();
}
template<class T> auto child_extended_private_key(T psz) {
return extended_private_key(this->child_private_key(psz), hash<256>(chain, psz));
}
template<class T> extended_public_key child_extended_public_key(T psz);
bool operator==(const extended_private_key& pt) const& {
return this->privatekey == pt.privatekey && this->chain == pt.chain;
}
}; };
static_assert(
static_assert(sizeof(extended_private_key) == sizeof(hash<256>) + sizeof(scalar)); sizeof(extended_private_key) == sizeof(hash<256>) + sizeof(scalar),
"assuming efficient packing when we convert to and from base58"
);
class extended_public_key { class extended_public_key {
/* 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
@ -53,22 +69,36 @@ namespace ristretto255 {
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.
*/ */
extended_public_key(point&&, hash<256>&&);
public: public:
friend class extended_private_key;
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) noexcept; extended_public_key(extended_public_key& parent, std::span<byte> path) noexcept;
extended_public_key(extended_private_key&) noexcept; extended_public_key(extended_private_key&) noexcept;
~extended_public_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); } ~extended_public_key()noexcept;
template<class T> auto operator()(T psz) { template<class T> point operator()(T psz) {
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; } template<class T> point child_public_key(T psz) {
return this->operator()(psz);
}
template<class T> auto child_extended_public_key(T psz) {
return extended_public_key(this->child_public_key(psz), hash<256>(chain, psz));
}
bool operator==(const extended_public_key& pt) const& {
return this->publickey == pt.publickey && this->chain == pt.chain;
}
}; };
static_assert(
static_assert(sizeof(extended_public_key) == sizeof(hash<256>) + sizeof(point)); sizeof(extended_public_key) == sizeof(hash<256>) + sizeof(point),
"assuming efficient packing when we convert to and from base58"
);
template<class T> extended_public_key extended_private_key::child_extended_public_key(T psz) {
return extended_public_key(this->child_public_key(psz), hash<256>(chain, psz));
}
std::span<const byte> serialize(const extended_private_key& pt); std::span<const byte> serialize(const extended_private_key& pt);
std::span<const byte> serialize(const extended_public_key& pt); std::span<const byte> serialize(const extended_public_key& pt);
} }

View File

@ -651,6 +651,12 @@ namespace ristretto255 {
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);
} }
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()
);
/* test conversion of public keys to Base58 and expected results*/
extended_public_key p1(s1); extended_public_key p1(s1);
std::string str_p1((char*)base58(p1)); std::string str_p1((char*)base58(p1));
wxLogMessage("\t\textended public key: %s", str_p1); wxLogMessage("\t\textended public key: %s", str_p1);
@ -662,8 +668,26 @@ namespace ristretto255 {
if (p1 != p2) { if (p1 != p2) {
throw MyException("Round trip for extended_public_key to and from base 58 representation failed", __LINE__, __func__, SrcFilename); 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) }; { // test if public extended key tree follows private extended key tree
wxLogMessage("\t\tStrong secret extended private key derivation took %lld microseconds", time_taken.count()); std::array<char, 4> path1, path2;
randombytes_buf(&path1[0], size(path1));
auto p1_path1 = s1.child_extended_public_key(path1);
auto s1_path1 = s1.child_extended_private_key(path1);
randombytes_buf(&path2[0], size(path2));
auto sk_path1_path2 = s1_path1.child_private_key(path2);
auto pk_path1_path2 = s1_path1.child_public_key(path2);
if(
p1_path1 != extended_public_key(s1_path1) ||
p1_path1 != p1.child_extended_public_key(path1) ||
pk_path1_path2 != sk_path1_path2.timesBase() ||
pk_path1_path2 != p1_path1.child_public_key(path2)
) {
throw MyException(
"public and private extended key derivation fails to parallel",
__LINE__, __func__, SrcFilename
);
}
}
} }
} }
else { else {