Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #10456 from EOSIO/rodeos-recover-key
Browse files Browse the repository at this point in the history
Add recover_key & assert_recover_key to rodeos
  • Loading branch information
heifner authored Jun 25, 2021
2 parents 50db9cd + 0c3fa1f commit d81585f
Showing 1 changed file with 68 additions and 2 deletions.
70 changes: 68 additions & 2 deletions libraries/rodeos/include/b1/rodeos/callbacks/crypto.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#pragma once

#include <b1/rodeos/callbacks/vm_types.hpp>
#include <eosio/chain/config.hpp>
#include <fc/crypto/public_key.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/signature.hpp>
#include <fc/io/datastream.hpp>

namespace b1::rodeos {

Expand All @@ -15,8 +19,70 @@ struct crypto_callbacks {
throw std::runtime_error("wasm called " + std::string(name) + ", which is unimplemented");
}

void assert_recover_key(int, int, int, int, int) { return unimplemented<void>("assert_recover_key"); }
int recover_key(int, int, int, int, int) { return unimplemented<int>("recover_key"); }
void assert_recover_key( legacy_ptr<const fc::sha256> digest,
legacy_span<const char> sig,
legacy_span<const char> pub ) const {
fc::crypto::signature s;
fc::crypto::public_key p;
fc::datastream<const char*> ds( sig.data(), sig.size() );
fc::datastream<const char*> pubds ( pub.data(), pub.size() );

fc::raw::unpack( ds, s );
fc::raw::unpack( pubds, p );

// TODO: enforce supported key types
// EOS_ASSERT(static_cast<unsigned>(s.which()) < db.get<protocol_state_object>().num_supported_key_types,
// eosio::chain::unactivated_signature_type,
// "Unactivated signature type used during assert_recover_key");
// EOS_ASSERT(static_cast<unsigned>(p.which()) < db.get<protocol_state_object>().num_supported_key_types,
// eosio::chain::unactivated_key_type,
// "Unactivated key type used during assert_recover_key");

// TODO: enforce subjective signature length limit maximum-variable-signature-length in queries. Filters don't need this protection.
// EOS_ASSERT(s.variable_size() <= configured_subjective_signature_length_limit(),
// eosio::chain::sig_variable_size_limit_exception, "signature variable length component size greater than subjective maximum");

auto check = fc::crypto::public_key( s, *digest, false );
EOS_ASSERT( check == p, eosio::chain::crypto_api_exception, "Error expected key different than recovered key" );
}

int32_t recover_key( legacy_ptr<const fc::sha256> digest,
legacy_span<const char> sig,
legacy_span<char> pub ) const {
fc::crypto::signature s;
fc::datastream<const char*> ds( sig.data(), sig.size() );
fc::raw::unpack(ds, s);

// TODO: enforce supported key types
// EOS_ASSERT(static_cast<unsigned>(s.which()) < db.get<protocol_state_object>().num_supported_key_types,
// eosio::chain::unactivated_signature_type,
// "Unactivated signature type used during assert_recover_key");

// TODO: enforce subjective signature length limit maximum-variable-signature-length in queries. Filters don't need this protection.
// EOS_ASSERT(s.variable_size() <= configured_subjective_signature_length_limit(),
// eosio::chain::sig_variable_size_limit_exception, "signature variable length component size greater than subjective maximum");

auto recovered = fc::crypto::public_key(s, *digest, false);

// the key types newer than the first 2 may be varible in length
if (static_cast<unsigned>(s.which()) >= eosio::chain::config::genesis_num_supported_key_types ) {
EOS_ASSERT(pub.size() >= 33, eosio::chain::wasm_execution_error,
"destination buffer must at least be able to hold an ECC public key");
auto packed_pubkey = fc::raw::pack(recovered);
auto copy_size = std::min<size_t>(pub.size(), packed_pubkey.size());
std::memcpy(pub.data(), packed_pubkey.data(), copy_size);
return packed_pubkey.size();
} else {
// legacy behavior, key types 0 and 1 always pack to 33 bytes.
// this will do one less copy for those keys while maintaining the rules of
// [0..33) dest sizes: assert (asserts in fc::raw::pack)
// [33..inf) dest sizes: return packed size (always 33)
fc::datastream<char*> out_ds( pub.data(), pub.size() );
fc::raw::pack(out_ds, recovered);
return out_ds.tellp();
}
}

void assert_sha256(int, int, int) { return unimplemented<void>("assert_sha256"); }
void assert_sha1(int, int, int) { return unimplemented<void>("assert_sha1"); }
void assert_sha512(int, int, int) { return unimplemented<void>("assert_sha512"); }
Expand Down

0 comments on commit d81585f

Please sign in to comment.