Kagome
Polkadot Runtime Engine in C++17
secp256k1_provider_impl.cpp
Go to the documentation of this file.
1 
7 
8 #include <secp256k1_recovery.h>
9 
10 namespace kagome::crypto {
11 
13  : context_(secp256k1_context_create(SECP256K1_CONTEXT_SIGN
14  | SECP256K1_CONTEXT_VERIFY),
15  secp256k1_context_destroy) {}
16 
17  outcome::result<secp256k1::UncompressedPublicKey>
19  const secp256k1::RSVSignature &signature,
20  const secp256k1::MessageHash &message_hash) const {
21  OUTCOME_TRY(pubkey, recoverPublickey(signature, message_hash));
23  size_t outputlen = pubkey_out.size();
24 
25  if (1
26  != secp256k1_ec_pubkey_serialize(context_.get(),
27  pubkey_out.data(),
28  &outputlen,
29  &pubkey,
30  SECP256K1_EC_UNCOMPRESSED)) {
32  }
33 
34  return pubkey_out;
35  };
36 
37  outcome::result<secp256k1::CompressedPublicKey>
39  const secp256k1::RSVSignature &signature,
40  const secp256k1::MessageHash &message_hash) const {
41  OUTCOME_TRY(pubkey, recoverPublickey(signature, message_hash));
43  size_t outputlen = secp256k1::CompressedPublicKey::size();
44 
45  if (1
46  != secp256k1_ec_pubkey_serialize(context_.get(),
47  pubkey_out.data(),
48  &outputlen,
49  &pubkey,
50  SECP256K1_EC_COMPRESSED)) {
52  }
53 
54  return pubkey_out;
55  }
56 
57  outcome::result<int> validateRecoveryId(int v) {
58  int recovery_id = -1;
59  // v can be 0/1 27/28, recovery id must be 0 or 1
60  switch (v) {
61  case 0:
62  recovery_id = 0;
63  break;
64  case 1:
65  recovery_id = 1;
66  break;
67  case 27:
68  recovery_id = 0;
69  break;
70  case 28:
71  recovery_id = 1;
72  break;
73  default:
75  }
76  return recovery_id;
77  }
78 
79  outcome::result<secp256k1_pubkey> Secp256k1ProviderImpl::recoverPublickey(
80  const secp256k1::RSVSignature &signature,
81  const secp256k1::MessageHash &message_hash) const {
82  OUTCOME_TRY(rec_id, validateRecoveryId(static_cast<int>(signature[64])));
83 
84  secp256k1_ecdsa_recoverable_signature sig_rec;
85  secp256k1_pubkey pubkey;
86 
87  if (1
88  != secp256k1_ecdsa_recoverable_signature_parse_compact(
89  context_.get(), &sig_rec, signature.data(), rec_id)) {
91  }
92 
93  if (1
94  != secp256k1_ecdsa_recover(
95  context_.get(), &pubkey, &sig_rec, message_hash.data())) {
97  }
98 
99  return pubkey;
100  }
101 } // namespace kagome::crypto
102 
105  switch (e) {
106  case E::INVALID_ARGUMENT:
107  return "invalid argument occured";
108  case E::INVALID_V_VALUE:
109  return "invalid V value of an RSV signature";
111  return "invalid R or S value of an RSV signature";
113  return "invalid RSV signature";
114  case E::RECOVERY_FAILED:
115  return "public key recovery operation failed";
116  }
117  return "unknown Secp256k1ProviderError error occured";
118 }
outcome::result< secp256k1_pubkey > recoverPublickey(const secp256k1::RSVSignature &signature, const secp256k1::MessageHash &message_hash) const
outcome::result< int > validateRecoveryId(int v)
OUTCOME_CPP_DEFINE_CATEGORY(kagome::crypto, Secp256k1ProviderError, e)
outcome::result< secp256k1::UncompressedPublicKey > recoverPublickeyUncompressed(const secp256k1::RSVSignature &signature, const secp256k1::MessageHash &message_hash) const override
recover public key in uncompressed form
std::unique_ptr< secp256k1_context, void(*)(secp256k1_context *)> context_
outcome::result< secp256k1::CompressedPublicKey > recoverPublickeyCompressed(const secp256k1::RSVSignature &signature, const secp256k1::MessageHash &message_hash) const override
recover public key in compressed form
static constexpr size_t size()
Definition: blob.hpp:146