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 {
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))),
chain(parent.chain, path)
{};
chain(parent.chain, path){
};
extended_private_key::extended_private_key(hash<512>&& s) noexcept :
privatekey(s),
chain(s)
{};
chain(s){
};
extended_private_key::extended_private_key(const char* const passwd) noexcept :
extended_private_key(DeriveStrongSecretHash(passwd))

View File

@ -14,6 +14,7 @@ constexpr int rounded_log2(const T val) noexcept {
}
namespace ristretto255 {
class extended_public_key;
class extended_private_key {
/* This is the same name and concept as BIP0032 and BIP0044 extended private
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,
I use spans of bytes. */
extended_private_key(hash<512>&&)noexcept;
extended_private_key(scalar&&, hash<256>&&);
public:
friend class extended_public_key;
scalar privatekey;
hash<256> chain;
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(const char* const passwd) noexcept;
~extended_private_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); }
template<class T> auto operator()(T psz) {
return privatekey*scalar(hash<512>(chain, psz));
~extended_private_key()noexcept;
template<class T> scalar operator()(T psz) {
return privatekey * scalar(hash<512>(chain, psz));
}
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;
}
bool operator==(const extended_private_key& pt) const& { return this->privatekey == pt.privatekey && this->chain == pt.chain; }
};
static_assert(sizeof(extended_private_key) == sizeof(hash<256>) + sizeof(scalar));
static_assert(
sizeof(extended_private_key) == sizeof(hash<256>) + sizeof(scalar),
"assuming efficient packing when we convert to and from base58"
);
class extended_public_key {
/* 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
extended key, but utterly incompatible.
*/
extended_public_key(point&&, hash<256>&&);
public:
friend class extended_private_key;
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<byte> path) noexcept;
extended_public_key(extended_private_key&) noexcept;
~extended_public_key()noexcept { wxSecretValue::Wipe(sizeof(*this), this); }
template<class T> auto operator()(T psz) {
scalar& t(*this);
~extended_public_key()noexcept;
template<class T> point operator()(T 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(sizeof(extended_public_key) == sizeof(hash<256>) + sizeof(point));
static_assert(
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_public_key& pt);
}

View File

@ -651,6 +651,12 @@ namespace ristretto255 {
if (s1 != s2) {
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);
std::string str_p1((char*)base58(p1));
wxLogMessage("\t\textended public key: %s", str_p1);
@ -662,8 +668,26 @@ namespace ristretto255 {
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) };
wxLogMessage("\t\tStrong secret extended private key derivation took %lld microseconds", time_taken.count());
{ // test if public extended key tree follows private extended key tree
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 {