forked from cheng/wallet
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 {
|
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))
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
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(
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user