1
0
Fork 0
mirror of https://github.com/eosswedenorg/libantelope synced 2026-06-16 03:34:56 +02:00

Merge branch '3-support-new-key-format' into devel

This commit is contained in:
Henrik Hautakoski 2023-03-26 15:08:01 +02:00
commit 6026114869
10 changed files with 468 additions and 98 deletions

View file

@ -53,6 +53,8 @@ add_library( ${LIB_NAME} STATIC
src/base58.cpp
src/ec.cpp
src/WIF.cpp
src/wif/k1.cpp
src/wif/legacy.cpp
src/openssl/hash.cpp
)

View file

@ -29,10 +29,19 @@
namespace libeosio {
/**
* Key prefixes. (strings that is not equal to these prefixes are treated as legacy format.)
*/
const std::string WIF_PUB_LEG = "EOS";
const std::string WIF_PUB_K1 = "PUB_K1_";
const std::string WIF_PVT_LEG = "";
const std::string WIF_PVT_K1 = "PVT_K1_";
const std::string WIF_SIG_K1 = "SIG_K1_";
/**
* Encode an EC private key to WIF String.
*/
std::string wif_priv_encode(const ec_privkey_t& priv);
std::string wif_priv_encode(const ec_privkey_t& priv, const std::string& prefix = WIF_PVT_LEG);
/**
* Decode an WIF String to EC private key
@ -42,17 +51,17 @@ bool wif_priv_decode(ec_privkey_t& priv, const std::string& data);
/**
* Encode an EC public key to WIF String.
*/
std::string wif_pub_encode(const ec_pubkey_t& pub, const std::string& prefix = "EOS");
std::string wif_pub_encode(const ec_pubkey_t& pub, const std::string& prefix = WIF_PUB_LEG);
/**
* Decode an WIF String to EC public key
*/
bool wif_pub_decode(ec_pubkey_t& pub, const std::string& data, size_t prefix_length = 3);
bool wif_pub_decode(ec_pubkey_t& pub, const std::string& data);
/**
* Prints an EC keypair in WIF format to standard out.
*/
void wif_print_key(const struct ec_keypair *key, const std::string& prefix = "EOS");
void wif_print_key(const struct ec_keypair *key, const std::string& prefix = WIF_PUB_LEG);
/**
* Signatures

View file

@ -26,69 +26,84 @@
#include <libeosio/base58.hpp>
#include <libeosio/checksum.hpp>
#include <libeosio/WIF.hpp>
#include "wif/codec.hpp"
namespace libeosio {
#define PRIV_KEY_PREFIX 0x80 /* 0x80 for "Bitcoin mainnet". Always used by EOS. */
std::string wif_priv_encode(const ec_privkey_t& priv) {
std::string wif_priv_encode(const ec_privkey_t& priv, const std::string& prefix) {
checksum_t check;
// 1 byte extra for prefix.
unsigned char buf[1 + EC_PRIVKEY_SIZE + CHECKSUM_SIZE] = { PRIV_KEY_PREFIX };
// 1 byte extra for legacy prefix prefix.
unsigned char buf[1 + EC_PRIVKEY_SIZE + CHECKSUM_SIZE] = { 0 };
size_t len;
memcpy(buf + 1, priv.data(), priv.size());
if (prefix == WIF_PVT_K1) {
len = internal::priv_encoder_k1(priv, buf);
} else if (prefix == WIF_PVT_LEG) {
len = internal::priv_encoder_legacy(priv, buf);
} else {
return "";
}
// Checksum
check = checksum_sha256d(buf, 1 + EC_PRIVKEY_SIZE);
memcpy(buf + 1 + EC_PRIVKEY_SIZE, check.data(), check.size());
return base58_encode(buf, buf + sizeof(buf));
return prefix + base58_encode(buf, buf + len);
}
bool wif_priv_decode(ec_privkey_t& priv, const std::string& data) {
uint8_t offset;
std::vector<unsigned char> buf;
internal::priv_decoder_t decoder = internal::priv_decoder_legacy;
if (!base58_decode(data, buf)) {
// Check prefix
if (data.substr(0, WIF_PVT_K1.size()) == WIF_PVT_K1) {
offset = WIF_PVT_K1.size();
decoder = internal::priv_decoder_k1;
} else {
// Legacy
offset = 0;
}
if (!base58_decode(data.c_str() + offset, buf)) {
return false;
}
if (buf.size() != 1 + EC_PRIVKEY_SIZE + CHECKSUM_SIZE) {
return false;
}
// First byte is the prefix
if (buf[0] != PRIV_KEY_PREFIX) {
return false;
}
// Calculate and validate checksum
if (!checksum_validate<checksum_sha256d>(buf.data(), buf.size())) {
return false;
}
// Copy data to output
memcpy(priv.data(), buf.data() + 1, priv.size());
return true;
return decoder(buf, priv);
}
std::string wif_pub_encode(const ec_pubkey_t& pub, const std::string& prefix) {
checksum_t check = checksum_ripemd160(pub.data(), pub.size());
unsigned char buf[EC_PUBKEY_SIZE + CHECKSUM_SIZE];
internal::pub_encoder_t encoder;
memcpy(buf, pub.data(), pub.size());
memcpy(buf + EC_PUBKEY_SIZE, check.data(), check.size());
if (prefix == WIF_PUB_K1) {
encoder = internal::pub_encoder_k1;
}
// Legacy
else {
encoder = internal::pub_encoder_legacy;
}
return prefix.substr(0, 3) + base58_encode(buf, buf + sizeof(buf));
encoder(pub, buf);
return prefix + base58_encode(buf, buf + sizeof(buf));
}
bool wif_pub_decode(ec_pubkey_t& pub, const std::string& data, size_t prefix_length) {
bool wif_pub_decode(ec_pubkey_t& pub, const std::string& data) {
internal::pub_decoder_t decoder = internal::pub_decoder_legacy;
int offset;
std::vector<unsigned char> buf;
if (!base58_decode(data.c_str() + prefix_length, buf)) {
// Check prefix
if (data.substr(0, WIF_PUB_K1.size()) == WIF_PUB_K1) {
decoder = internal::pub_decoder_k1;
offset = WIF_PUB_K1.size();
} else {
// Legacy
offset = 3;
}
if (!base58_decode(data.c_str() + offset, buf)) {
return false;
}
@ -96,34 +111,13 @@ bool wif_pub_decode(ec_pubkey_t& pub, const std::string& data, size_t prefix_len
return false;
}
// Calculate and validate checksum
if (!checksum_validate<checksum_ripemd160>(buf.data(), buf.size())) {
return false;
}
// Copy data to output
memcpy(pub.data(), buf.data(), pub.size());
return true;
return decoder(buf, pub);
}
void wif_print_key(const struct ec_keypair *key, const std::string& prefix) {
std::cout << "Public: " << wif_pub_encode(key->pub, prefix) << std::endl;
std::cout << "Private: " << wif_priv_encode(key->secret) << std::endl;
}
// Just to make it "harder" the calculated checksum for a signature
// has a "K1" suffix that is not present in the WIF encoded string.
// So this function is a quick hack to calculate it.
//
// Should implement and use Init/Update/Finalize hash functions to do it inplace.
checksum_t _calculate_sig_checksum(const unsigned char *in) {
unsigned char buf[EC_SIGNATURE_SIZE + 2];
memcpy(buf, in, EC_SIGNATURE_SIZE);
memcpy(buf + EC_SIGNATURE_SIZE, "K1", 2);
return checksum_ripemd160(buf, EC_SIGNATURE_SIZE + 2);
std::cout << "Private: " << wif_priv_encode(key->secret, prefix) << std::endl;
}
bool wif_sig_decode(ec_signature_t& sig, const std::string& data) {
@ -131,41 +125,24 @@ bool wif_sig_decode(ec_signature_t& sig, const std::string& data) {
checksum_t checksum;
std::vector<unsigned char> buf;
if (data.substr(0, 7) != "SIG_K1_") {
if (data.substr(0, WIF_SIG_K1.length()) != WIF_SIG_K1) {
// Invalid prefix
return false;
}
if (!base58_decode(data.c_str() + 7, buf)) {
if (!base58_decode(data.c_str() + WIF_SIG_K1.length(), buf)) {
return false;
}
if (buf.size() != EC_SIGNATURE_SIZE + CHECKSUM_SIZE) {
return false;
}
// Calculate checksum
checksum = _calculate_sig_checksum(buf.data());
// And validate
if (memcmp(buf.data() + EC_SIGNATURE_SIZE, checksum.data(), CHECKSUM_SIZE)) {
return false;
}
// Copy data to output
memcpy(sig.data(), buf.data(), sig.size());
return true;
return internal::sig_decoder_k1(buf, sig);
}
std::string wif_sig_encode(const ec_signature_t& sig) {
unsigned char buf[EC_SIGNATURE_SIZE + CHECKSUM_SIZE];
checksum_t check = _calculate_sig_checksum(sig.data());
internal::sig_encoder_k1(sig, buf);
memcpy(buf, sig.data(), sig.size());
memcpy(buf + EC_SIGNATURE_SIZE, check.data(), check.size());
return "SIG_K1_" + base58_encode(buf, buf + sizeof(buf));
return WIF_SIG_K1 + base58_encode(buf, buf + sizeof(buf));
}
} // namespace libeosio

84
src/wif/codec.hpp Normal file
View file

@ -0,0 +1,84 @@
/**
* MIT License
*
* Copyright (c) 2019-2021 EOS Sw/eden
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef LIBEOSIO_CODEC_H
#define LIBEOSIO_CODEC_H
#include <libeosio/WIF.hpp>
#include <vector>
namespace libeosio { namespace internal {
/**
* Public-key encoders
*/
typedef void (*pub_encoder_t)(const ec_pubkey_t& key, unsigned char *buf);
void pub_encoder_legacy(const ec_pubkey_t& key, unsigned char *buf);
void pub_encoder_k1(const ec_pubkey_t& key, unsigned char *buf);
/**
* Public-key decoders
*/
typedef bool (*pub_decoder_t)(const std::vector<unsigned char>& buf, ec_pubkey_t& key);
bool pub_decoder_legacy(const std::vector<unsigned char>& buf, ec_pubkey_t& key);
bool pub_decoder_k1(const std::vector<unsigned char>& buf, ec_pubkey_t& key);
/**
* Private-key encoders
*/
typedef size_t (*priv_encoder_t)(const ec_privkey_t&, unsigned char *);
size_t priv_encoder_legacy(const ec_privkey_t& priv, unsigned char *buf);
size_t priv_encoder_k1(const ec_privkey_t& priv, unsigned char *buf);
/**
* Private-key decoders
*/
typedef bool (*priv_decoder_t)(const std::vector<unsigned char>&, ec_privkey_t&);
bool priv_decoder_legacy(const std::vector<unsigned char>& buf, ec_privkey_t& priv);
bool priv_decoder_k1(const std::vector<unsigned char>& buf, ec_privkey_t& priv);
/**
* Signature encoders
*/
typedef void (*sig_encoder_t)(const ec_signature_t& sig, unsigned char *buf);
void sig_encoder_k1(const ec_signature_t& sig, unsigned char *buf);
/**
* Signature decoders
*/
typedef bool (*sig_decoder_t)(const std::vector<unsigned char>& buf, ec_signature_t& sig);
bool sig_decoder_k1(const std::vector<unsigned char>& buf, ec_signature_t& sig);
}} // namespace libeosio::internal
#endif /* LIBEOSIO_CODEC_H */

119
src/wif/k1.cpp Normal file
View file

@ -0,0 +1,119 @@
/**
* MIT License
*
* Copyright (c) 2019-2021 EOS Sw/eden
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <libeosio/checksum.hpp>
#include <vector>
#include "codec.hpp"
namespace libeosio { namespace internal {
// Just to make it "harder" the calculated checksum for a signature (k1) and pub/priv keys in k1/r1 format.
// has a suffix that is not present in the WIF encoded string.
// So this function is a quick hack to calculate it.
//
// Should implement and use Init/Update/Finalize hash functions to do it inplace.
checksum_t _checksum_suffix(const unsigned char *in, size_t size, const char *suffix) {
std::vector<unsigned char> buf(size + 2);
memcpy(buf.data(), in, size);
memcpy(buf.data() + size, suffix, 2);
return checksum_ripemd160(buf.data(), buf.size());
}
void pub_encoder_k1(const ec_pubkey_t& key, unsigned char *buf) {
checksum_t check = _checksum_suffix(key.data(), EC_PUBKEY_SIZE, "K1");
memcpy(buf, key.data(), EC_PUBKEY_SIZE);
memcpy(buf + EC_PUBKEY_SIZE, check.data(), check.size());
}
bool pub_decoder_k1(const std::vector<unsigned char>& buf, ec_pubkey_t& key) {
checksum_t check = _checksum_suffix(buf.data(), EC_PUBKEY_SIZE, "K1");
if (memcmp(buf.data() + EC_PUBKEY_SIZE, check.data(), CHECKSUM_SIZE)) {
return false;
}
memcpy(key.data(), buf.data(), EC_PUBKEY_SIZE);
return true;
}
size_t priv_encoder_k1(const ec_privkey_t& priv, unsigned char *buf) {
checksum_t check = _checksum_suffix(priv.data(), EC_PRIVKEY_SIZE, "K1");
memcpy(buf, priv.data(), priv.size());
memcpy(buf + EC_PRIVKEY_SIZE, check.data(), check.size());
return EC_PRIVKEY_SIZE + CHECKSUM_SIZE;
}
bool priv_decoder_k1(const std::vector<unsigned char>& buf, ec_privkey_t& priv) {
if (buf.size() != EC_PRIVKEY_SIZE + CHECKSUM_SIZE) {
return false;
}
checksum_t check = _checksum_suffix(buf.data(), EC_PRIVKEY_SIZE, "K1");
if (memcmp(buf.data() + EC_PRIVKEY_SIZE, check.data(), CHECKSUM_SIZE)) {
return false;
}
memcpy(priv.data(), buf.data(), priv.size());
return true;
}
void sig_encoder_k1(const ec_signature_t& sig, unsigned char *buf) {
checksum_t check = _checksum_suffix(sig.data(), EC_SIGNATURE_SIZE, "K1");
memcpy(buf, sig.data(), sig.size());
memcpy(buf + EC_SIGNATURE_SIZE, check.data(), check.size());
}
bool sig_decoder_k1(const std::vector<unsigned char>& buf, ec_signature_t& sig) {
checksum_t check;
if (buf.size() != EC_SIGNATURE_SIZE + CHECKSUM_SIZE) {
return false;
}
// Calculate checksum
check = _checksum_suffix(buf.data(), EC_SIGNATURE_SIZE, "K1");
// And validate
if (memcmp(buf.data() + EC_SIGNATURE_SIZE, check.data(), CHECKSUM_SIZE)) {
return false;
}
// Copy data to output
memcpy(sig.data(), buf.data(), sig.size());
return true;
}
}} // namespace libeosio::internal

78
src/wif/legacy.cpp Normal file
View file

@ -0,0 +1,78 @@
/**
* MIT License
*
* Copyright (c) 2019-2021 EOS Sw/eden
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <libeosio/checksum.hpp>
#include "codec.hpp"
namespace libeosio { namespace internal {
#define PRIV_KEY_PREFIX 0x80 /* 0x80 for "Bitcoin mainnet". Always used by EOS. */
void pub_encoder_legacy(const ec_pubkey_t& key, unsigned char *buf) {
checksum_t check = checksum_ripemd160(key.data(), EC_PUBKEY_SIZE);
memcpy(buf, key.data(), EC_PUBKEY_SIZE);
memcpy(buf + EC_PUBKEY_SIZE, check.data(), check.size());
}
bool pub_decoder_legacy(const std::vector<unsigned char>& buf, ec_pubkey_t& key) {
if (!checksum_validate<checksum_ripemd160>(buf.data(), buf.size())) {
return false;
}
memcpy(key.data(), buf.data(), EC_PUBKEY_SIZE);
return true;
}
size_t priv_encoder_legacy(const ec_privkey_t& priv, unsigned char *buf) {
checksum_t check;
buf[0] = PRIV_KEY_PREFIX;
memcpy(buf + 1, priv.data(), EC_PRIVKEY_SIZE);
check = checksum_sha256d(buf, 1 + EC_PRIVKEY_SIZE);
memcpy(buf + 1 + EC_PRIVKEY_SIZE, check.data(), check.size());
return 1 + EC_PRIVKEY_SIZE + CHECKSUM_SIZE;
}
bool priv_decoder_legacy(const std::vector<unsigned char>& buf, ec_privkey_t& priv) {
if (buf[0] != PRIV_KEY_PREFIX) {
return false;
}
if (buf.size() != 1 + EC_PRIVKEY_SIZE + CHECKSUM_SIZE) {
return false;
}
if (!checksum_validate<checksum_sha256d>(buf.data(), buf.size())) {
return false;
}
memcpy(priv.data(), buf.data() + 1, priv.size());
return true;
}
}} // namespace libeosio::internal

View file

@ -4,7 +4,7 @@
#include <vector>
#include <doctest.h>
TEST_CASE("WIF::wif_priv_decode") {
TEST_CASE("WIF::wif_priv_decode [legacy]") {
struct testcase {
std::string name;
std::string key;
@ -29,4 +29,31 @@ TEST_CASE("WIF::wif_priv_decode") {
}
}
}
TEST_CASE("WIF::wif_priv_decode [K1]") {
struct testcase {
std::string name;
std::string key;
libeosio::ec_privkey_t expected;
};
std::vector<struct testcase> tests {
{ "one", "PVT_K1_6Mcb23muAxyXaSMhmB6B1mqkvLdWhtuFZmnZsxDczHRvQdp32", { 0x0C, 0x28, 0xFC, 0xA3, 0x86, 0xC7, 0xA2, 0x27, 0x60, 0x0B, 0x2F, 0xE5, 0x0B, 0x7C, 0xAE, 0x11, 0xEC, 0x86, 0xD3, 0xBF, 0x1F, 0xBE, 0x47, 0x1B, 0xE8, 0x98, 0x27, 0xE1, 0x9D, 0x72, 0xAA, 0x1D } },
{ "two", "PVT_K1_2DRBT8jmXT8k9ywNSSbufvhk1hLFhPzWJBpsE2jo12CDoFhcc1", { 0x9F, 0xE3, 0xE3, 0x2B, 0x3C, 0x4B, 0x6B, 0x91, 0x6E, 0x20, 0x6C, 0xB0, 0x91, 0xDF, 0x1F, 0x5E, 0x34, 0x32, 0x88, 0x0B, 0x41, 0x33, 0x86, 0xBD, 0xF2, 0x92, 0xFF, 0x23, 0x06, 0x43, 0xF2, 0x8C } },
{ "three", "PVT_K1_gJCsP4CwMv4gTkDXiZT8QFhs3NrSB7Sv22ANGrc8Svun9uC9C", { 0x59, 0x3A, 0x51, 0xB5, 0x5D, 0x56, 0xAA, 0xF0, 0x5B, 0xD9, 0xD1, 0x0E, 0x6B, 0x88, 0x6D, 0xF9, 0xC4, 0x37, 0x09, 0xB2, 0x4C, 0xEC, 0xBB, 0x63, 0x68, 0x92, 0xC2, 0x94, 0x31, 0x48, 0x71, 0x8C } }
};
for(auto it = tests.begin(); it != tests.end(); it++) {
SUBCASE(it->name.c_str()) {
libeosio::ec_privkey_t result;
CHECK( libeosio::wif_priv_decode(result, it->key) );
CHECK( result == it->expected );
}
}
}

View file

@ -4,24 +4,48 @@
#include <vector>
#include <doctest.h>
TEST_CASE("WIF::wif_priv_encode") {
TEST_CASE("WIF::wif_priv_encode [Legacy]") {
struct testcase {
std::string name;
const std::string prefix;
libeosio::ec_privkey_t key;
std::string expected;
};
std::vector<struct testcase> tests {
{ "one", { 0x0C, 0x28, 0xFC, 0xA3, 0x86, 0xC7, 0xA2, 0x27, 0x60, 0x0B, 0x2F, 0xE5, 0x0B, 0x7C, 0xAE, 0x11, 0xEC, 0x86, 0xD3, 0xBF, 0x1F, 0xBE, 0x47, 0x1B, 0xE8, 0x98, 0x27, 0xE1, 0x9D,0x72,0xAA,0x1D}, "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ" },
{ "two", { 0x9F, 0xE3, 0xE3, 0x2B, 0x3C, 0x4B, 0x6B, 0x91, 0x6E, 0x20, 0x6C, 0xB0, 0x91, 0xDF, 0x1F, 0x5E, 0x34, 0x32, 0x88, 0x0B, 0x41, 0x33, 0x86, 0xBD, 0xF2, 0x92, 0xFF, 0x23, 0x06, 0x43, 0xF2, 0x8C}, "5K2hm8apqz281ANDQdtVzifpxcXFTqG5E7Fc6Q5V2ssqPRQ3urJ" },
{ "three", { 0x59, 0x3A, 0x51, 0xB5, 0x5D, 0x56, 0xAA, 0xF0, 0x5B, 0xD9, 0xD1, 0x0E, 0x6B, 0x88, 0x6D, 0xF9, 0xC4, 0x37, 0x09, 0xB2, 0x4C, 0xEC, 0xBB, 0x63, 0x68, 0x92, 0xC2, 0x94, 0x31, 0x48, 0x71, 0x8C}, "5JVanYq9HPvuKgr2FjATYB9NvTsJ4a3CAj5oPYKbr1Ja5MRLsZX" }
{ "one", libeosio::WIF_PVT_LEG, { 0x0C, 0x28, 0xFC, 0xA3, 0x86, 0xC7, 0xA2, 0x27, 0x60, 0x0B, 0x2F, 0xE5, 0x0B, 0x7C, 0xAE, 0x11, 0xEC, 0x86, 0xD3, 0xBF, 0x1F, 0xBE, 0x47, 0x1B, 0xE8, 0x98, 0x27, 0xE1, 0x9D,0x72,0xAA,0x1D}, "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ" },
{ "two", libeosio::WIF_PVT_LEG, { 0x9F, 0xE3, 0xE3, 0x2B, 0x3C, 0x4B, 0x6B, 0x91, 0x6E, 0x20, 0x6C, 0xB0, 0x91, 0xDF, 0x1F, 0x5E, 0x34, 0x32, 0x88, 0x0B, 0x41, 0x33, 0x86, 0xBD, 0xF2, 0x92, 0xFF, 0x23, 0x06, 0x43, 0xF2, 0x8C}, "5K2hm8apqz281ANDQdtVzifpxcXFTqG5E7Fc6Q5V2ssqPRQ3urJ" },
{ "three", libeosio::WIF_PVT_LEG, { 0x59, 0x3A, 0x51, 0xB5, 0x5D, 0x56, 0xAA, 0xF0, 0x5B, 0xD9, 0xD1, 0x0E, 0x6B, 0x88, 0x6D, 0xF9, 0xC4, 0x37, 0x09, 0xB2, 0x4C, 0xEC, 0xBB, 0x63, 0x68, 0x92, 0xC2, 0x94, 0x31, 0x48, 0x71, 0x8C}, "5JVanYq9HPvuKgr2FjATYB9NvTsJ4a3CAj5oPYKbr1Ja5MRLsZX" }
};
for(auto it = tests.begin(); it != tests.end(); it++) {
SUBCASE(it->name.c_str()) {
CHECK( libeosio::wif_priv_encode(it->key) == it->expected );
CHECK( libeosio::wif_priv_encode(it->key, it->prefix) == it->expected );
}
}
}
TEST_CASE("WIF::wif_priv_encode [K1]") {
struct testcase {
std::string name;
const std::string prefix;
libeosio::ec_privkey_t key;
std::string expected;
};
std::vector<struct testcase> tests {
{ "one", libeosio::WIF_PVT_K1, { 0x0C, 0x28, 0xFC, 0xA3, 0x86, 0xC7, 0xA2, 0x27, 0x60, 0x0B, 0x2F, 0xE5, 0x0B, 0x7C, 0xAE, 0x11, 0xEC, 0x86, 0xD3, 0xBF, 0x1F, 0xBE, 0x47, 0x1B, 0xE8, 0x98, 0x27, 0xE1, 0x9D,0x72,0xAA,0x1D}, "PVT_K1_6Mcb23muAxyXaSMhmB6B1mqkvLdWhtuFZmnZsxDczHRvQdp32" },
{ "two", libeosio::WIF_PVT_K1, { 0x9F, 0xE3, 0xE3, 0x2B, 0x3C, 0x4B, 0x6B, 0x91, 0x6E, 0x20, 0x6C, 0xB0, 0x91, 0xDF, 0x1F, 0x5E, 0x34, 0x32, 0x88, 0x0B, 0x41, 0x33, 0x86, 0xBD, 0xF2, 0x92, 0xFF, 0x23, 0x06, 0x43, 0xF2, 0x8C}, "PVT_K1_2DRBT8jmXT8k9ywNSSbufvhk1hLFhPzWJBpsE2jo12CDoFhcc1" },
{ "three", libeosio::WIF_PVT_K1, { 0x59, 0x3A, 0x51, 0xB5, 0x5D, 0x56, 0xAA, 0xF0, 0x5B, 0xD9, 0xD1, 0x0E, 0x6B, 0x88, 0x6D, 0xF9, 0xC4, 0x37, 0x09, 0xB2, 0x4C, 0xEC, 0xBB, 0x63, 0x68, 0x92, 0xC2, 0x94, 0x31, 0x48, 0x71, 0x8C}, "PVT_K1_gJCsP4CwMv4gTkDXiZT8QFhs3NrSB7Sv22ANGrc8Svun9uC9C" }
};
for(auto it = tests.begin(); it != tests.end(); it++) {
SUBCASE(it->name.c_str()) {
CHECK( libeosio::wif_priv_encode(it->key, it->prefix) == it->expected );
}
}
}

View file

@ -4,7 +4,7 @@
#include <vector>
#include <doctest.h>
TEST_CASE("WIF::wif_pub_encode") {
TEST_CASE("WIF::wif_pub_decode [legacy]") {
struct testcase {
const char* name;
std::string key;
@ -31,3 +31,31 @@ TEST_CASE("WIF::wif_pub_encode") {
}
}
}
TEST_CASE("WIF::wif_pub_decode [k1]") {
struct testcase {
const char* name;
std::string key;
libeosio::ec_pubkey_t expected;
bool expectedRet;
};
std::vector<struct testcase> tests {
{ "one", "PUB_K1_7kzJ5iFBmQWWT1LiWgAiocESD7TTNuuPCdYREUQysruq7AxzWu", { 0x03, 0x7a, 0x0e, 0x6b, 0xfd, 0xe4, 0xf1, 0xad, 0x36, 0x3f, 0x3a, 0xf9, 0xe0, 0x93, 0x63, 0x5a, 0xa9, 0x99, 0x21, 0x15, 0xbc, 0x23, 0x35, 0x75, 0x13, 0x69, 0x55, 0xee, 0x3f, 0xf8, 0xfd, 0x97, 0xec }, true },
{ "two", "PUB_K1_5c9HkNCJLDebe2Wvapp8bpB38Pf1QWNpkrsFy3mshg7DViSUUa", { 0x02, 0x5e, 0x94, 0xa5, 0xe7, 0x9f, 0x66, 0x37, 0x55, 0x7e, 0xc2, 0x28, 0x30, 0x40, 0x82, 0x9a, 0x38, 0x72, 0x10, 0x96, 0x6e, 0x15, 0xb7, 0xa5, 0x8a, 0x27, 0x9a, 0x71, 0x06, 0xa7, 0x64, 0x23, 0x30 }, true },
{ "three", "PUB_K1_8SwZMY8DChbbmRKS3wdHCAbv1VWgTRmQEDSaLyJk8pG4wKBXpw", { 0x03, 0xd4, 0xc6, 0x2a, 0xdc, 0x11, 0x1c, 0x65, 0x7a, 0x9f, 0x5b, 0xba, 0x96, 0x3f, 0xbb, 0x2a, 0x69, 0x2e, 0xc5, 0x4a, 0x48, 0x3b, 0xa3, 0x5f, 0x2a, 0x37, 0x6c, 0x59, 0x95, 0xb1, 0x95, 0x1c, 0xc9 }, true },
{ "wrong_checksum", "PUB_K1_8SwZMY8DChbbmRKS3wdHCAbv1VWgTRmQEDSaLyJk8pG4wKBXgE", { 0x0 }, false },
{ "wrong_length", "PUB_K1_7kzJ5iFBmQWWT1LiWgAiocESD7TT", { 0x0 }, false },
{ "not_base58", "PUB_K1_7IIIIIOOOO", { 0x0 }, false }
};
for(auto it = tests.begin(); it != tests.end(); it++) {
SUBCASE(it->name) {
libeosio::ec_pubkey_t result = { 0x0 };
CHECK( libeosio::wif_pub_decode(result, it->key) == it->expectedRet );
CHECK( result == it->expected );
}
}
}

View file

@ -4,29 +4,29 @@
#include <vector>
#include <doctest.h>
TEST_CASE("WIF::wif_pub_encode") {
TEST_CASE("WIF::wif_pub_encode [legacy]") {
struct testcase {
std::string name;
const std::string prefix;
libeosio::ec_pubkey_t key;
std::string expected;
};
std::vector<struct testcase> tests {
{ "one", { 0x03, 0x7a, 0x0e, 0x6b, 0xfd, 0xe4, 0xf1, 0xad, 0x36, 0x3f, 0x3a, 0xf9, 0xe0, 0x93, 0x63, 0x5a, 0xa9, 0x99, 0x21, 0x15, 0xbc, 0x23, 0x35, 0x75, 0x13, 0x69, 0x55, 0xee, 0x3f, 0xf8, 0xfd, 0x97, 0xec }, "EOS7kzJ5iFBmQWWT1LiWgAiocESD7TTNuuPCdYREUQysruq8VeFKy" },
{ "two", { 0x02, 0x5e, 0x94, 0xa5, 0xe7, 0x9f, 0x66, 0x37, 0x55, 0x7e, 0xc2, 0x28, 0x30, 0x40, 0x82, 0x9a, 0x38, 0x72, 0x10, 0x96, 0x6e, 0x15, 0xb7, 0xa5, 0x8a, 0x27, 0x9a, 0x71, 0x06, 0xa7, 0x64, 0x23, 0x30 }, "EOS5c9HkNCJLDebe2Wvapp8bpB38Pf1QWNpkrsFy3mshg7DZfPNeA" },
{ "three", { 0x03, 0xd4, 0xc6, 0x2a, 0xdc, 0x11, 0x1c, 0x65, 0x7a, 0x9f, 0x5b, 0xba, 0x96, 0x3f, 0xbb, 0x2a, 0x69, 0x2e, 0xc5, 0x4a, 0x48, 0x3b, 0xa3, 0x5f, 0x2a, 0x37, 0x6c, 0x59, 0x95, 0xb1, 0x95, 0x1c, 0xc9 }, "EOS8SwZMY8DChbbmRKS3wdHCAbv1VWgTRmQEDSaLyJk8pG4wm8BJF" }
{ "one", libeosio::WIF_PUB_LEG, { 0x03, 0x7a, 0x0e, 0x6b, 0xfd, 0xe4, 0xf1, 0xad, 0x36, 0x3f, 0x3a, 0xf9, 0xe0, 0x93, 0x63, 0x5a, 0xa9, 0x99, 0x21, 0x15, 0xbc, 0x23, 0x35, 0x75, 0x13, 0x69, 0x55, 0xee, 0x3f, 0xf8, 0xfd, 0x97, 0xec }, "EOS7kzJ5iFBmQWWT1LiWgAiocESD7TTNuuPCdYREUQysruq8VeFKy" },
{ "two", libeosio::WIF_PUB_LEG, { 0x02, 0x5e, 0x94, 0xa5, 0xe7, 0x9f, 0x66, 0x37, 0x55, 0x7e, 0xc2, 0x28, 0x30, 0x40, 0x82, 0x9a, 0x38, 0x72, 0x10, 0x96, 0x6e, 0x15, 0xb7, 0xa5, 0x8a, 0x27, 0x9a, 0x71, 0x06, 0xa7, 0x64, 0x23, 0x30 }, "EOS5c9HkNCJLDebe2Wvapp8bpB38Pf1QWNpkrsFy3mshg7DZfPNeA" },
{ "three", libeosio::WIF_PUB_LEG, { 0x03, 0xd4, 0xc6, 0x2a, 0xdc, 0x11, 0x1c, 0x65, 0x7a, 0x9f, 0x5b, 0xba, 0x96, 0x3f, 0xbb, 0x2a, 0x69, 0x2e, 0xc5, 0x4a, 0x48, 0x3b, 0xa3, 0x5f, 0x2a, 0x37, 0x6c, 0x59, 0x95, 0xb1, 0x95, 0x1c, 0xc9 }, "EOS8SwZMY8DChbbmRKS3wdHCAbv1VWgTRmQEDSaLyJk8pG4wm8BJF" }
};
for(auto it = tests.begin(); it != tests.end(); it++) {
SUBCASE(it->name.c_str()) {
CHECK( libeosio::wif_pub_encode(it->key) == it->expected );
CHECK( libeosio::wif_pub_encode(it->key, it->prefix) == it->expected );
}
}
}
TEST_CASE("WIF::wif_pub_encode [prefix]") {
TEST_CASE("WIF::wif_pub_encode [custom prefix]") {
struct testcase {
std::string name;
@ -47,3 +47,25 @@ TEST_CASE("WIF::wif_pub_encode [prefix]") {
}
}
}
TEST_CASE("WIF::wif_pub_encode [k1]") {
struct testcase {
std::string name;
const std::string prefix;
libeosio::ec_pubkey_t key;
std::string expected;
};
std::vector<struct testcase> tests {
{ "one", libeosio::WIF_PUB_K1, { 0x03, 0x7a, 0x0e, 0x6b, 0xfd, 0xe4, 0xf1, 0xad, 0x36, 0x3f, 0x3a, 0xf9, 0xe0, 0x93, 0x63, 0x5a, 0xa9, 0x99, 0x21, 0x15, 0xbc, 0x23, 0x35, 0x75, 0x13, 0x69, 0x55, 0xee, 0x3f, 0xf8, 0xfd, 0x97, 0xec }, "PUB_K1_7kzJ5iFBmQWWT1LiWgAiocESD7TTNuuPCdYREUQysruq7AxzWu" },
{ "two", libeosio::WIF_PUB_K1, { 0x02, 0x5e, 0x94, 0xa5, 0xe7, 0x9f, 0x66, 0x37, 0x55, 0x7e, 0xc2, 0x28, 0x30, 0x40, 0x82, 0x9a, 0x38, 0x72, 0x10, 0x96, 0x6e, 0x15, 0xb7, 0xa5, 0x8a, 0x27, 0x9a, 0x71, 0x06, 0xa7, 0x64, 0x23, 0x30 }, "PUB_K1_5c9HkNCJLDebe2Wvapp8bpB38Pf1QWNpkrsFy3mshg7DViSUUa" },
{ "three", libeosio::WIF_PUB_K1, { 0x03, 0xd4, 0xc6, 0x2a, 0xdc, 0x11, 0x1c, 0x65, 0x7a, 0x9f, 0x5b, 0xba, 0x96, 0x3f, 0xbb, 0x2a, 0x69, 0x2e, 0xc5, 0x4a, 0x48, 0x3b, 0xa3, 0x5f, 0x2a, 0x37, 0x6c, 0x59, 0x95, 0xb1, 0x95, 0x1c, 0xc9 }, "PUB_K1_8SwZMY8DChbbmRKS3wdHCAbv1VWgTRmQEDSaLyJk8pG4wKBXpw" }
};
for(auto it = tests.begin(); it != tests.end(); it++) {
SUBCASE(it->name.c_str()) {
CHECK( libeosio::wif_pub_encode(it->key, it->prefix) == it->expected );
}
}
}