未验证 提交 f537bc50 编写于 作者: M Matt Witherspoon 提交者: GitHub

Merge pull request #2441 from wanderingbort/feature/2416-prefix-fixup

Fix for 2416 : discriminating prefixes 
......@@ -34,15 +34,14 @@ namespace fc { namespace crypto {
template<typename Result, const char * const * Prefixes, int Position, typename KeyType, typename ...Rem>
struct base58_str_parser_impl<Result, Prefixes, Position, KeyType, Rem...> {
static Result apply(const std::string& base58str)
static Result apply(const std::string& prefix_str, const std::string& data_str)
{
using data_type = typename KeyType::data_type;
using wrapper = checksummed_data<data_type>;
constexpr auto prefix = Prefixes[Position];
if (prefix_matches(prefix, base58str)) {
auto str = base58str.substr(const_strlen(prefix));
auto bin = fc::from_base58(str);
if (prefix == prefix_str) {
auto bin = fc::from_base58(data_str);
FC_ASSERT(bin.size() >= sizeof(data_type) + sizeof(uint32_t));
auto wrapped = fc::raw::unpack<wrapper>(bin);
auto checksum = wrapper::calculate_checksum(wrapped.data, prefix);
......@@ -50,14 +49,14 @@ namespace fc { namespace crypto {
return Result(KeyType(wrapped.data));
}
return base58_str_parser_impl<Result, Prefixes, Position + 1, Rem...>::apply(base58str);
return base58_str_parser_impl<Result, Prefixes, Position + 1, Rem...>::apply(prefix_str, data_str);
}
};
template<typename Result, const char * const * Prefixes, int Position>
struct base58_str_parser_impl<Result, Prefixes, Position> {
static Result apply(const std::string& base58str) {
FC_ASSERT(false, "No matching prefix for ${str}", ("str", base58str));
static Result apply(const std::string& prefix_str, const std::string& data_str ) {
FC_ASSERT(false, "No matching suite type for ${prefix}_${data}", ("prefix", prefix_str)("data",data_str));
}
};
......@@ -73,7 +72,14 @@ namespace fc { namespace crypto {
template<const char * const * Prefixes, typename ...Ts>
struct base58_str_parser<fc::static_variant<Ts...>, Prefixes> {
static fc::static_variant<Ts...> apply(const std::string& base58str) {
return base58_str_parser_impl<fc::static_variant<Ts...>, Prefixes, 0, Ts...>::apply(base58str);
const auto pivot = base58str.find('_');
FC_ASSERT(pivot != std::string::npos, "No delimiter in data, cannot determine suite type: ${str}", ("str", base58str));
const auto prefix_str = base58str.substr(0, pivot);
auto data_str = base58str.substr(pivot + 1);
FC_ASSERT(!data_str.empty(), "Data only has suite type prefix: ${str}", ("str", base58str));
return base58_str_parser_impl<fc::static_variant<Ts...>, Prefixes, 0, Ts...>::apply(prefix_str, data_str);
}
};
......@@ -91,7 +97,7 @@ namespace fc { namespace crypto {
auto packed = raw::pack( wrapper );
auto data_str = to_base58( packed.data(), packed.size() );
if (!is_default) {
data_str = string(Prefixes[position]) + data_str;
data_str = string(Prefixes[position]) + "_" + data_str;
}
return data_str;
......
......@@ -9,7 +9,7 @@
namespace fc { namespace crypto {
namespace config {
constexpr const char* private_key_base_prefix = "EOS";
constexpr const char* private_key_base_prefix = "PVT";
constexpr const char* private_key_prefix[] = {
"K1",
"R1"
......
......@@ -8,7 +8,8 @@
namespace fc { namespace crypto {
namespace config {
constexpr const char* public_key_base_prefix = "EOS";
constexpr const char* public_key_legacy_prefix = "EOS";
constexpr const char* public_key_base_prefix = "PUB";
constexpr const char* public_key_prefix[] = {
"K1",
"R1"
......
......@@ -7,7 +7,7 @@
namespace fc { namespace crypto {
namespace config {
constexpr const char* signature_base_prefix = "EOS";
constexpr const char* signature_base_prefix = "SIG";
constexpr const char* signature_prefix[] = {
"K1",
"R1"
......
......@@ -90,18 +90,23 @@ namespace fc { namespace crypto {
static private_key::storage_type parse_base58(const string& base58str)
{
try {
if (base58str.find('_') == std::string::npos) {
// wif import
using default_type = private_key::storage_type::template type_at<0>;
return private_key::storage_type(from_wif<default_type>(base58str));
} catch (...) {
// wif import failed
}
} else {
constexpr auto prefix = config::private_key_base_prefix;
const auto pivot = base58str.find('_');
FC_ASSERT(pivot != std::string::npos, "No delimiter in string, cannot determine type: ${str}", ("str", base58str));
constexpr auto prefix = config::private_key_base_prefix;
FC_ASSERT(prefix_matches(prefix, base58str), "Private Key has invalid prefix: ${str}", ("str", base58str));
auto sub_str = base58str.substr(const_strlen(prefix));
return base58_str_parser<private_key::storage_type, config::private_key_prefix>::apply(sub_str);
const auto prefix_str = base58str.substr(0, pivot);
FC_ASSERT(prefix == prefix_str, "Private Key has invalid prefix: ${str}", ("str", base58str)("prefix_str", prefix_str));
auto data_str = base58str.substr(pivot + 1);
FC_ASSERT(!data_str.empty(), "Private Key has no data: ${str}", ("str", base58str));
return base58_str_parser<private_key::storage_type, config::private_key_prefix>::apply(data_str);
}
}
private_key::private_key(const std::string& base58str)
......@@ -118,7 +123,7 @@ namespace fc { namespace crypto {
}
auto data_str = _storage.visit(base58str_visitor<storage_type, config::private_key_prefix>());
return std::string(config::private_key_base_prefix) + data_str;
return std::string(config::private_key_base_prefix) + "_" + data_str;
}
std::ostream& operator<<(std::ostream& s, const private_key& k) {
......
......@@ -26,25 +26,30 @@ namespace fc { namespace crypto {
static public_key::storage_type parse_base58(const std::string& base58str)
{
constexpr auto prefix = config::public_key_base_prefix;
FC_ASSERT(prefix_matches(prefix, base58str), "Public Key has invalid prefix: ${str}", ("str", base58str));
auto sub_str = base58str.substr(const_strlen(prefix));
try {
constexpr auto legacy_prefix = config::public_key_legacy_prefix;
if(prefix_matches(legacy_prefix, base58str) && base58str.find('_') == std::string::npos ) {
auto sub_str = base58str.substr(const_strlen(legacy_prefix));
using default_type = typename public_key::storage_type::template type_at<0>;
using data_type = default_type::data_type;
using wrapper = checksummed_data<data_type>;
auto bin = fc::from_base58(sub_str);
if (bin.size() == sizeof(data_type) + sizeof(uint32_t)) {
auto wrapped = fc::raw::unpack<wrapper>(bin);
FC_ASSERT(wrapper::calculate_checksum(wrapped.data) == wrapped.check);
return public_key::storage_type(default_type(wrapped.data));
}
} catch (...) {
// default import failed
FC_ASSERT(bin.size() == sizeof(data_type) + sizeof(uint32_t), "");
auto wrapped = fc::raw::unpack<wrapper>(bin);
FC_ASSERT(wrapper::calculate_checksum(wrapped.data) == wrapped.check);
return public_key::storage_type(default_type(wrapped.data));
} else {
constexpr auto prefix = config::public_key_base_prefix;
const auto pivot = base58str.find('_');
FC_ASSERT(pivot != std::string::npos, "No delimiter in string, cannot determine data type: ${str}", ("str", base58str));
const auto prefix_str = base58str.substr(0, pivot);
FC_ASSERT(prefix == prefix_str, "Public Key has invalid prefix: ${str}", ("str", base58str)("prefix_str", prefix_str));
auto data_str = base58str.substr(pivot + 1);
FC_ASSERT(!data_str.empty(), "Public Key has no data: ${str}", ("str", base58str));
return base58_str_parser<public_key::storage_type, config::public_key_prefix>::apply(data_str);
}
return base58_str_parser<public_key::storage_type, config::public_key_prefix>::apply(sub_str);
}
public_key::public_key(const std::string& base58str)
......@@ -54,7 +59,13 @@ namespace fc { namespace crypto {
public_key::operator std::string() const
{
auto data_str = _storage.visit(base58str_visitor<storage_type, config::public_key_prefix, 0>());
return std::string(config::public_key_base_prefix) + data_str;
auto which = _storage.which();
if (which == 0) {
return std::string(config::public_key_legacy_prefix) + data_str;
} else {
return std::string(config::public_key_base_prefix) + "_" + data_str;
}
}
std::ostream& operator<<(std::ostream& s, const public_key& k) {
......
......@@ -15,24 +15,16 @@ namespace fc { namespace crypto {
static signature::storage_type parse_base58(const std::string& base58str)
{
constexpr auto prefix = config::signature_base_prefix;
FC_ASSERT(prefix_matches(prefix, base58str), "Signature has invalid prefix: ${str}", ("str", base58str));
auto sub_str = base58str.substr(const_strlen(prefix));
try {
using default_type = signature::storage_type::template type_at<0>;
using data_type = default_type::data_type;
using wrapper = checksummed_data<data_type>;
auto bin = fc::from_base58(sub_str);
if (bin.size() == sizeof(data_type) + sizeof(uint32_t)) {
auto wrapped = fc::raw::unpack<wrapper>(bin);
FC_ASSERT(wrapper::calculate_checksum(wrapped.data) == wrapped.check);
return signature::storage_type(default_type(wrapped.data));
}
} catch (...) {
// default import failed
}
const auto pivot = base58str.find('_');
FC_ASSERT(pivot != std::string::npos, "No delimiter in string, cannot determine type: ${str}", ("str", base58str));
const auto prefix_str = base58str.substr(0, pivot);
FC_ASSERT(prefix == prefix_str, "Signature Key has invalid prefix: ${str}", ("str", base58str)("prefix_str", prefix_str));
return base58_str_parser<signature::storage_type, config::signature_prefix>::apply(sub_str);
auto data_str = base58str.substr(pivot + 1);
FC_ASSERT(!data_str.empty(), "Signature has no data: ${str}", ("str", base58str));
return base58_str_parser<signature::storage_type, config::signature_prefix>::apply(data_str);
}
signature::signature(const std::string& base58str)
......@@ -41,8 +33,8 @@ namespace fc { namespace crypto {
signature::operator std::string() const
{
auto data_str = _storage.visit(base58str_visitor<storage_type, config::signature_prefix, 0>());
return std::string(config::signature_base_prefix) + data_str;
auto data_str = _storage.visit(base58str_visitor<storage_type, config::signature_prefix>());
return std::string(config::signature_base_prefix) + "_" + data_str;
}
std::ostream& operator<<(std::ostream& s, const signature& k) {
......
......@@ -21,8 +21,8 @@ BOOST_AUTO_TEST_CASE(test_k1) try {
} FC_LOG_AND_RETHROW();
BOOST_AUTO_TEST_CASE(test_r1) try {
auto private_key_string = std::string("EOSR1iyQmnyPEGvFd8uffnk152WC2WryBjgTrg22fXQryuGL9mU6qW");
auto expected_public_key = std::string("EOSR16EPHFSKVYHBjQgxVGQPrwCxTg7BbZ69H9i4gztN9deKTEXYne4");
auto private_key_string = std::string("PVT_R1_iyQmnyPEGvFd8uffnk152WC2WryBjgTrg22fXQryuGL9mU6qW");
auto expected_public_key = std::string("PUB_R1_6EPHFSKVYHBjQgxVGQPrwCxTg7BbZ69H9i4gztN9deKTEXYne4");
auto test_private_key = private_key(private_key_string);
auto test_public_key = test_private_key.get_public_key();
......
......@@ -207,7 +207,7 @@ const char* error_advice_3120010 = R"=====(Ensure that your packed transaction
}
e.g.
{
"signatures" : [ "EOSJze4m1ZHQ4UjuHpBcX6uHPN4Xyggv52raQMTBZJghzDLepaPcSGCNYTxaP2NiaF4yRF5RaYwqsQYAwBwFtfuTJr34Z5GJX" ],
"signatures" : [ "SIG_K1_Jze4m1ZHQ4UjuHpBcX6uHPN4Xyggv52raQMTBZJghzDLepaPcSGCNYTxaP2NiaF4yRF5RaYwqsQYAwBwFtfuTJr34Z5GJX" ],
"compression" : "none",
"hex_transaction" : "6c36a25a00002602626c5e7f0000000000010000001e4d75af460000000000a53176010000000000ea305500000000a8ed3232180000001e4d75af4680969800000000000443555200000000"
})=====";
......
......@@ -50,7 +50,7 @@ that requires usage of a fingerprint when signing a digest (such a signing a tra
```
$ applesedemo.app/Contents/MacOS/applesedemo --create-se-touch-only
Successfully created
public_key(EOSR17iKCZrb1JqSjUncCbDGQenzSqyuNmPU8iUA15efNW5KD1iHd9x)
public_key(PUB_R1_7iKCZrb1JqSjUncCbDGQenzSqyuNmPU8iUA15efNW5KD1iHd9x)
```
The public key for the private key is printed; note it somewhere. It is possible to ask the Secure Enclave to
create multiple private keys and assign labels to them but this application only allows a single key at once.
......@@ -64,14 +64,14 @@ Now, ask the Secure Enclave to sign the digest with the private key only it know
generated until a valid fingerprint is used.
```
$ applesedemo.app/Contents/MacOS/applesedemo --sign 0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8
signature(EOSR1Jx4sBidhFV6PSvS8hWbG5oh77HKud8xpkoHLvWaZVaBeWttRpyEjaGbPRVEKu3JePTyVjANmP4GKFtG2DAuB4MTVqsdC9W)
signature(SIG_R1_Jx4sBidhFV6PSvS8hWbG5oh77HKud8xpkoHLvWaZVaBeWttRpyEjaGbPRVEKu3JePTyVjANmP4GKFtG2DAuB4MTVqsdC9W)
```
## Key Recovery
Given the signature and digest, we must be able to correlate that with the public key that signed the digest.
```
$ applesedemo.app/Contents/MacOS/applesedemo --recover 0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8 \
EOSR1Jx4sBidhFV6PSvS8hWbG5oh77HKud8xpkoHLvWaZVaBeWttRpyEjaGbPRVEKu3JePTyVjANmP4GKFtG2DAuB4MTVqsdC9W
public_key(EOSR17iKCZrb1JqSjUncCbDGQenzSqyuNmPU8iUA15efNW5KD1iHd9x)
SIG_R1_Jx4sBidhFV6PSvS8hWbG5oh77HKud8xpkoHLvWaZVaBeWttRpyEjaGbPRVEKu3JePTyVjANmP4GKFtG2DAuB4MTVqsdC9W
public_key(PUB_R1_7iKCZrb1JqSjUncCbDGQenzSqyuNmPU8iUA15efNW5KD1iHd9x)
```
Indeed, the public key recovered from this digest and signature matches the public key from the key stored in the Secure
Enclave.
\ No newline at end of file
......@@ -76,7 +76,7 @@ void print_pub_for_key(SecKeyRef key) {
pub_wrapper.check = fc::crypto::checksummed_data<fc::crypto::r1::public_key_data>::calculate_checksum(pub_wrapper.data, "R1");
std::vector<char> checksummed = fc::raw::pack(pub_wrapper);
cout << "public_key(EOSR1" << fc::to_base58(checksummed.data(), checksummed.size()) << ")" << endl;
cout << "public_key(PUB_R1_" << fc::to_base58(checksummed.data(), checksummed.size()) << ")" << endl;
}
void print_attributes() {
......@@ -221,7 +221,7 @@ void sign(const string& hex) {
signature_wrapper.check = fc::crypto::checksummed_data<fc::crypto::r1::compact_signature>::calculate_checksum(signature_wrapper.data, "R1");
checksummed = fc::raw::pack(signature_wrapper);
cout << "signature(EOSR1" << fc::to_base58(checksummed.data(), checksummed.size()) << ")" << endl;
cout << "signature(SIG_R1_" << fc::to_base58(checksummed.data(), checksummed.size()) << ")" << endl;
err:
CFRelease(key);
......
......@@ -1802,8 +1802,8 @@ BOOST_AUTO_TEST_CASE(general)
"string_arr" : ["ola ke ase","ola ke desi"],
"time" : "2021-12-20T15:30",
"time_arr" : ["2021-12-20T15:30","2021-12-20T15:31"],
"signature" : "EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U",
"signature_arr" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U","EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"signature" : "SIG_K1_Jzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwV1v4G5",
"signature_arr" : ["SIG_K1_Jzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwV1v4G5","SIG_K1_Jzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwV1v4G5"],
"checksum256" : "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
"checksum256_arr" : ["ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad","ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"],
"fieldname" : "name1",
......@@ -1895,7 +1895,7 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"2",
"expiration":"2021-12-20T15:30",
"region": "1",
"signatures" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"signatures" : ["SIG_K1_Jzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwV1v4G5"],
"context_free_data" : ["abcdef","0123456789","ABCDEF0123456789abcdef"],
"context_free_actions":[{"account":"contextfree1", "name":"cfactionname1", "authorization":[{"actor":"cfacc1","permission":"cfpermname1"}], "data":"778899"}],
"actions":[{"account":"accountname1", "name":"actionname1", "authorization":[{"actor":"acc1","permission":"permname1"}], "data":"445566"}],
......@@ -1908,7 +1908,7 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"2",
"expiration":"2021-12-20T15:30",
"region": "1",
"signatures" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"signatures" : ["SIG_K1_Jzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwV1v4G5"],
"context_free_data" : ["abcdef","0123456789","ABCDEF0123456789abcdef"],
"context_free_actions":[{"account":"contextfree1", "name":"cfactionname1", "authorization":[{"actor":"cfacc1","permission":"cfpermname1"}], "data":"778899"}],
"actions":[{"account":"acc1", "name":"actionname1", "authorization":[{"actor":"acc1","permission":"permname1"}], "data":"445566"}],
......@@ -1920,7 +1920,7 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"3",
"expiration":"2021-12-20T15:40",
"region": "1",
"signatures" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"signatures" : ["SIG_K1_Jzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwV1v4G5"],
"context_free_data" : ["abcdef","0123456789","ABCDEF0123456789abcdef"],
"context_free_actions":[{"account":"contextfree2", "name":"cfactionname2", "authorization":[{"actor":"cfacc2","permission":"cfpermname2"}], "data":"667788"}],
"actions":[{"account":"acc2", "name":"actionname2", "authorization":[{"actor":"acc2","permission":"permname2"}], "data":""}],
......
......@@ -579,7 +579,7 @@ BOOST_FIXTURE_TEST_CASE( producer_register_unregister, eosio_system_tester ) try
//call regproducer again to change parameters
fc::variant params2 = producer_parameters_example(2);
vector<char> key2 = fc::raw::pack( fc::crypto::public_key( std::string("EOSR16EPHFSKVYHBjQgxVGQPrwCxTg7BbZ69H9i4gztN9deKTEXYne4") ) );
vector<char> key2 = fc::raw::pack( fc::crypto::public_key( std::string("PUB_R1_6EPHFSKVYHBjQgxVGQPrwCxTg7BbZ69H9i4gztN9deKTEXYne4") ) );
BOOST_REQUIRE_EQUAL( success(), push_action(N(alice), N(regproducer), mvo()
("producer", "alice")
("producer_key", key2 )
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册