This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9066 from EOSIO/separate_signing_plugin
separate out signature provider from producer plugin
- Loading branch information
Showing
7 changed files
with
175 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
file(GLOB HEADERS "include/eosio/signature_provider_plugin/*.hpp") | ||
add_library( signature_provider_plugin | ||
signature_provider_plugin.cpp | ||
${HEADERS} ) | ||
|
||
target_link_libraries( signature_provider_plugin appbase fc http_client_plugin ) | ||
target_include_directories( signature_provider_plugin PUBLIC include ) | ||
if(APPLE) | ||
target_link_libraries( signature_provider_plugin se-helpers ) | ||
endif() |
33 changes: 33 additions & 0 deletions
33
...ure_provider_plugin/include/eosio/signature_provider_plugin/signature_provider_plugin.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#pragma once | ||
#include <appbase/application.hpp> | ||
#include <eosio/http_client_plugin/http_client_plugin.hpp> | ||
#include <eosio/chain/types.hpp> | ||
|
||
namespace eosio { | ||
|
||
using namespace appbase; | ||
|
||
class signature_provider_plugin : public appbase::plugin<signature_provider_plugin> { | ||
public: | ||
signature_provider_plugin(); | ||
virtual ~signature_provider_plugin(); | ||
|
||
APPBASE_PLUGIN_REQUIRES((http_client_plugin)) | ||
virtual void set_program_options(options_description&, options_description& cfg) override; | ||
|
||
void plugin_initialize(const variables_map& options) {} | ||
void plugin_startup() {} | ||
void plugin_shutdown() {} | ||
|
||
const char* const signature_provider_help_text() const; | ||
|
||
using signature_provider_type = std::function<chain::signature_type(chain::digest_type)>; | ||
|
||
std::pair<chain::public_key_type,signature_provider_type> signature_provider_for_specification(const std::string& spec) const; | ||
signature_provider_type signature_provider_for_private_key(const chain::private_key_type priv) const; | ||
|
||
private: | ||
std::unique_ptr<class signature_provider_plugin_impl> my; | ||
}; | ||
|
||
} |
123 changes: 123 additions & 0 deletions
123
plugins/signature_provider_plugin/signature_provider_plugin.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#include <eosio/signature_provider_plugin/signature_provider_plugin.hpp> | ||
#include <eosio/chain/exceptions.hpp> | ||
|
||
#include <fc/time.hpp> | ||
#include <fc/network/url.hpp> | ||
|
||
#include <boost/algorithm/string.hpp> | ||
|
||
#ifdef __APPLE__ | ||
#include <eosio/se-helpers/se-helpers.hpp> | ||
#endif | ||
|
||
namespace eosio { | ||
static appbase::abstract_plugin& _signature_provider_plugin = app().register_plugin<signature_provider_plugin>(); | ||
|
||
class signature_provider_plugin_impl { | ||
public: | ||
fc::microseconds _keosd_provider_timeout_us; | ||
|
||
signature_provider_plugin::signature_provider_type | ||
make_key_signature_provider(const chain::private_key_type& key) const { | ||
return [key]( const chain::digest_type& digest ) { | ||
return key.sign(digest); | ||
}; | ||
} | ||
|
||
#ifdef __APPLE__ | ||
signature_provider_plugin::signature_provider_type | ||
make_se_signature_provider(const chain::public_key_type pubkey) const { | ||
EOS_ASSERT(secure_enclave::hardware_supports_secure_enclave(), chain::secure_enclave_exception, "Secure Enclave not supported on this hardware"); | ||
EOS_ASSERT(secure_enclave::application_signed(), chain::secure_enclave_exception, "Application is not signed, Secure Enclave use not supported"); | ||
|
||
std::set<secure_enclave::secure_enclave_key> allkeys = secure_enclave::get_all_keys(); | ||
for(const auto& se_key : secure_enclave::get_all_keys()) | ||
if(se_key.public_key() == pubkey) | ||
return [se_key](const chain::digest_type& digest) { | ||
return se_key.sign(digest); | ||
}; | ||
|
||
EOS_THROW(chain::secure_enclave_exception, "${k} not found in Secure Enclave", ("k", pubkey)); | ||
} | ||
#endif | ||
|
||
signature_provider_plugin::signature_provider_type | ||
make_keosd_signature_provider(const string& url_str, const chain::public_key_type pubkey) const { | ||
fc::url keosd_url; | ||
if(boost::algorithm::starts_with(url_str, "unix://")) | ||
//send the entire string after unix:// to http_plugin. It'll auto-detect which part | ||
// is the unix socket path, and which part is the url to hit on the server | ||
keosd_url = fc::url("unix", url_str.substr(7), fc::ostring(), fc::ostring(), fc::ostring(), fc::ostring(), fc::ovariant_object(), fc::optional<uint16_t>()); | ||
else | ||
keosd_url = fc::url(url_str); | ||
|
||
return [to=_keosd_provider_timeout_us, keosd_url, pubkey](const chain::digest_type& digest) { | ||
fc::variant params; | ||
fc::to_variant(std::make_pair(digest, pubkey), params); | ||
auto deadline = to.count() >= 0 ? fc::time_point::now() + to : fc::time_point::maximum(); | ||
return app().get_plugin<http_client_plugin>().get_client().post_sync(keosd_url, params, deadline).as<chain::signature_type>(); | ||
}; | ||
} | ||
}; | ||
|
||
signature_provider_plugin::signature_provider_plugin():my(new signature_provider_plugin_impl()){} | ||
signature_provider_plugin::~signature_provider_plugin(){} | ||
|
||
void signature_provider_plugin::set_program_options(options_description&, options_description& cfg) { | ||
cfg.add_options() | ||
("keosd-provider-timeout", boost::program_options::value<int32_t>()->default_value(5)->notifier([this](auto to){ | ||
my->_keosd_provider_timeout_us = fc::milliseconds(to); | ||
}), | ||
"Limits the maximum time (in milliseconds) that is allowed for sending requests to a keosd provider for signing") | ||
; | ||
} | ||
|
||
const char* const signature_provider_plugin::signature_provider_help_text() const { | ||
return "Key=Value pairs in the form <public-key>=<provider-spec>\n" | ||
"Where:\n" | ||
" <public-key> \tis a string form of a vaild EOSIO public key\n\n" | ||
" <provider-spec> \tis a string in the form <provider-type>:<data>\n\n" | ||
" <provider-type> \tis KEY, KEOSD, or SE\n\n" | ||
" KEY:<data> \tis a string form of a valid EOSIO private key which maps to the provided public key\n\n" | ||
" KEOSD:<data> \tis the URL where keosd is available and the approptiate wallet(s) are unlocked\n\n" | ||
#ifdef __APPLE__ | ||
" SE: \tindicates the key resides in Secure Enclave" | ||
#endif | ||
; | ||
|
||
} | ||
|
||
std::pair<chain::public_key_type,signature_provider_plugin::signature_provider_type> | ||
signature_provider_plugin::signature_provider_for_specification(const std::string& spec) const { | ||
auto delim = spec.find("="); | ||
EOS_ASSERT(delim != std::string::npos, chain::plugin_config_exception, "Missing \"=\" in the key spec pair"); | ||
auto pub_key_str = spec.substr(0, delim); | ||
auto spec_str = spec.substr(delim + 1); | ||
|
||
auto spec_delim = spec_str.find(":"); | ||
EOS_ASSERT(spec_delim != std::string::npos, chain::plugin_config_exception, "Missing \":\" in the key spec pair"); | ||
auto spec_type_str = spec_str.substr(0, spec_delim); | ||
auto spec_data = spec_str.substr(spec_delim + 1); | ||
|
||
auto pubkey = chain::public_key_type(pub_key_str); | ||
|
||
if(spec_type_str == "KEY") { | ||
chain::private_key_type priv(spec_data); | ||
EOS_ASSERT(pubkey == priv.get_public_key(), chain::plugin_config_exception, "Private key does not match given public key for ${pub}", ("pub", pubkey)); | ||
return std::make_pair(pubkey, my->make_key_signature_provider(priv)); | ||
} | ||
else if(spec_type_str == "KEOSD") | ||
return std::make_pair(pubkey, my->make_keosd_signature_provider(spec_data, pubkey)); | ||
#ifdef __APPLE__ | ||
else if(spec_type_str == "SE") | ||
return std::make_pair(pubkey, my->make_se_signature_provider(pubkey)); | ||
#endif | ||
EOS_THROW(chain::plugin_config_exception, "Unsupported key provider type \"${t}\"", ("t", spec_type_str)); | ||
} | ||
|
||
signature_provider_plugin::signature_provider_type | ||
signature_provider_plugin::signature_provider_for_private_key(const chain::private_key_type priv) const { | ||
return my->make_key_signature_provider(priv); | ||
} | ||
|
||
} |