testing functionality of extended keys in unit_test.cpp
This commit is contained in:
parent
295919fd69
commit
36343e69ba
@ -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))
|
||||
|
@ -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(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) {
|
||||
~extended_private_key()noexcept;
|
||||
template<class T> scalar operator()(T 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(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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user