Kagome
Polkadot Runtime Engine in C++17
crypto_extension.cpp
Go to the documentation of this file.
1 
7 
8 #include <algorithm>
9 #include <exception>
10 
11 #include <boost/assert.hpp>
12 #include <gsl/span>
13 
16 #include "crypto/crypto_store.hpp"
20 #include "crypto/hasher.hpp"
23 #include "runtime/memory.hpp"
24 #include "runtime/ptr_size.hpp"
25 #include "scale/scale.hpp"
26 
27 namespace {
28  template <typename... Args>
29  void throw_with_error(const kagome::log::Logger &logger, Args &&...fmt_args) {
30  auto msg = fmt::format(fmt_args...);
31  logger->error(msg);
32  throw std::runtime_error(msg);
33  }
34 
35  void checkIfKeyIsSupported(kagome::crypto::KeyTypeId key_type,
36  kagome::log::Logger log) {
37  if (not kagome::crypto::isSupportedKeyType(key_type)) {
38  const auto *p = reinterpret_cast<const char *>(&key_type);
39  std::string key_type_str(p, p + sizeof(key_type));
40 
41  log->warn("key type <ascii: {}, hex: {:08x}> is not officially supported",
42  key_type_str,
43  key_type);
44  }
45  }
46 
47 } // namespace
48 
49 namespace kagome::host_api {
50  namespace sr25519_constants = crypto::constants::sr25519;
51  namespace ed25519_constants = crypto::constants::ed25519;
52  namespace ecdsa_constants = crypto::constants::ecdsa;
53  namespace secp256k1 = crypto::secp256k1;
54 
62 
64  std::shared_ptr<const runtime::MemoryProvider> memory_provider,
65  std::shared_ptr<const crypto::Sr25519Provider> sr25519_provider,
66  std::shared_ptr<const crypto::EcdsaProvider> ecdsa_provider,
67  std::shared_ptr<const crypto::Ed25519Provider> ed25519_provider,
68  std::shared_ptr<const crypto::Secp256k1Provider> secp256k1_provider,
69  std::shared_ptr<const crypto::Hasher> hasher,
70  std::shared_ptr<crypto::CryptoStore> crypto_store,
71  std::shared_ptr<const crypto::Bip39Provider> bip39_provider)
72  : memory_provider_(std::move(memory_provider)),
73  sr25519_provider_(std::move(sr25519_provider)),
74  ecdsa_provider_(std::move(ecdsa_provider)),
75  ed25519_provider_(std::move(ed25519_provider)),
76  secp256k1_provider_(std::move(secp256k1_provider)),
77  hasher_(std::move(hasher)),
78  crypto_store_(std::move(crypto_store)),
79  bip39_provider_(std::move(bip39_provider)),
80  logger_{log::createLogger("CryptoExtension", "crypto_extension")} {
81  BOOST_ASSERT(memory_provider_ != nullptr);
82  BOOST_ASSERT(sr25519_provider_ != nullptr);
83  BOOST_ASSERT(ecdsa_provider_ != nullptr);
84  BOOST_ASSERT(ed25519_provider_ != nullptr);
85  BOOST_ASSERT(secp256k1_provider_ != nullptr);
86  BOOST_ASSERT(hasher_ != nullptr);
87  BOOST_ASSERT(crypto_store_ != nullptr);
88  BOOST_ASSERT(bip39_provider_ != nullptr);
89  BOOST_ASSERT(logger_ != nullptr);
90  }
91 
92  // ---------------------- hashing ----------------------
93 
95  runtime::WasmSpan data) {
96  auto [addr, len] = runtime::PtrSize(data);
97  const auto &buf = getMemory().loadN(addr, len);
98  auto hash = hasher_->keccak_256(buf);
99 
100  SL_TRACE_FUNC_CALL(logger_, hash, buf);
101 
102  return getMemory().storeBuffer(hash);
103  }
104 
106  runtime::WasmSpan data) {
107  auto [addr, len] = runtime::PtrSize(data);
108  const auto &buf = getMemory().loadN(addr, len);
109  auto hash = hasher_->sha2_256(buf);
110  SL_TRACE_FUNC_CALL(logger_, hash, buf);
111 
112  return getMemory().storeBuffer(hash);
113  }
114 
116  runtime::WasmSpan data) {
117  auto [addr, len] = runtime::PtrSize(data);
118  const auto &buf = getMemory().loadN(addr, len);
119  auto hash = hasher_->blake2b_128(buf);
120  SL_TRACE_FUNC_CALL(logger_, hash, buf);
121 
122  return getMemory().storeBuffer(hash);
123  }
124 
126  runtime::WasmSpan data) {
127  auto [addr, len] = runtime::PtrSize(data);
128  const auto &buf = getMemory().loadN(addr, len);
129  auto hash = hasher_->blake2b_256(buf);
130  SL_TRACE_FUNC_CALL(logger_, hash, buf);
131 
132  return getMemory().storeBuffer(hash);
133  }
134 
136  runtime::WasmSpan data) {
137  auto [addr, len] = runtime::PtrSize(data);
138  const auto &buf = getMemory().loadN(addr, len);
139  auto hash = hasher_->twox_64(buf);
140  SL_TRACE_FUNC_CALL(logger_, hash, buf);
141 
142  return getMemory().storeBuffer(hash);
143  }
144 
146  runtime::WasmSpan data) {
147  auto [addr, len] = runtime::PtrSize(data);
148  const auto &buf = getMemory().loadN(addr, len);
149  auto hash = hasher_->twox_128(buf);
150  SL_TRACE_FUNC_CALL(logger_, hash, buf);
151 
152  return getMemory().storeBuffer(hash);
153  }
154 
156  runtime::WasmSpan data) {
157  auto [ptr, size] = runtime::PtrSize(data);
158  const auto &buf = getMemory().loadN(ptr, size);
159  auto hash = hasher_->twox_256(buf);
160  SL_TRACE_FUNC_CALL(logger_, hash, buf);
161 
162  return getMemory().storeBuffer(hash);
163  }
164 
166  // TODO (kamilsa) 05.07.21 https://github.com/soramitsu/kagome/issues/804
167  }
168 
171  // TODO (kamilsa) 05.07.21 https://github.com/soramitsu/kagome/issues/804
172  return kVerifyBatchSuccess;
173  }
174 
176  runtime::WasmSize key_type) {
177  using ResultType = std::vector<crypto::Ed25519PublicKey>;
178  static const auto error_result(scale::encode(ResultType{}).value());
179 
180  auto key_type_id =
181  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
182  checkIfKeyIsSupported(key_type_id, logger_);
183 
184  auto public_keys = crypto_store_->getEd25519PublicKeys(key_type_id);
185  if (not public_keys) {
186  throw_with_error(logger_,
187  "error loading public keys: {}",
188  public_keys.error().message());
189  }
190  common::Buffer buffer{scale::encode(public_keys.value()).value()};
191  SL_TRACE_FUNC_CALL(logger_, buffer.size(), key_type_id);
192 
193  return getMemory().storeBuffer(buffer);
194  }
195 
196  common::Blob<32> CryptoExtension::deriveSeed(std::string_view content) {
197  // first check if content is a hexified seed value
198  if (auto res = common::Blob<32>::fromHexWithPrefix(content); res) {
199  return res.value();
200  }
201 
202  SL_DEBUG(logger_, "failed to unhex seed, try parse mnemonic");
203 
204  // now check if it is a bip39 mnemonic phrase with optional password
205  auto mnemonic = crypto::bip39::Mnemonic::parse(content);
206  if (!mnemonic) {
207  throw_with_error(
208  logger_, "failed to parse mnemonic {}", mnemonic.error().message());
209  }
210 
211  auto &&entropy = bip39_provider_->calculateEntropy(mnemonic.value().words);
212  if (!entropy) {
213  throw_with_error(
214  logger_, "failed to calculate entropy {}", entropy.error().message());
215  }
216 
217  auto &&big_seed =
218  bip39_provider_->makeSeed(entropy.value(), mnemonic.value().password);
219  if (!big_seed) {
220  throw_with_error(
221  logger_, "failed to generate seed {}", big_seed.error().message());
222  }
223 
224  auto big_span = gsl::span<uint8_t>(big_seed.value());
225  constexpr size_t size = common::Blob<32>::size();
226  // get first 32 bytes from big seed as ed25519 or sr25519 seed
227  auto seed = common::Blob<32>::fromSpan(big_span.subspan(0, size));
228  if (!seed) {
229  // impossible case bip39 seed is always 64 bytes long
230  BOOST_UNREACHABLE_RETURN({});
231  }
232  return seed.value();
233  }
234 
236  runtime::WasmSize key_type, runtime::WasmSpan seed) {
237  auto key_type_id =
238  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
239  checkIfKeyIsSupported(key_type_id, logger_);
240 
241  auto [seed_ptr, seed_len] = runtime::PtrSize(seed);
242  auto seed_buffer = getMemory().loadN(seed_ptr, seed_len);
243  auto seed_res = scale::decode<std::optional<std::string>>(seed_buffer);
244  if (!seed_res) {
245  throw_with_error(logger_, "failed to decode seed");
246  }
247  auto &&seed_opt = seed_res.value();
248 
249  outcome::result<crypto::Ed25519Keypair> kp_res{{}};
250  if (seed_opt.has_value()) {
251  kp_res =
252  crypto_store_->generateEd25519Keypair(key_type_id, seed_opt.value());
253  } else {
254  kp_res = crypto_store_->generateEd25519KeypairOnDisk(key_type_id);
255  }
256  if (!kp_res) {
257  throw_with_error(logger_,
258  "failed to generate ed25519 key pair: {}",
259  kp_res.error().message());
260  }
261  auto &key_pair = kp_res.value();
262  SL_TRACE_FUNC_CALL(logger_, key_pair.public_key, key_type_id, seed_buffer);
263  runtime::PtrSize res_span{getMemory().storeBuffer(key_pair.public_key)};
264  return res_span.combine();
265  }
266 
268  runtime::WasmSize key_type,
270  runtime::WasmSpan msg) {
271  using ResultType = std::optional<crypto::Ed25519Signature>;
272 
273  auto key_type_id =
274  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
275  checkIfKeyIsSupported(key_type_id, logger_);
276 
277  auto public_buffer =
278  getMemory().loadN(key, crypto::Ed25519PublicKey::size());
279  auto [msg_data, msg_len] = runtime::PtrSize(msg);
280  auto msg_buffer = getMemory().loadN(msg_data, msg_len);
281  auto pk = crypto::Ed25519PublicKey::fromSpan(public_buffer);
282  if (!pk) {
283  BOOST_UNREACHABLE_RETURN({});
284  }
285  auto key_pair = crypto_store_->findEd25519Keypair(key_type_id, pk.value());
286  if (!key_pair) {
287  logger_->error("failed to find required key");
288  auto error_result = scale::encode(ResultType(std::nullopt)).value();
289  return getMemory().storeBuffer(error_result);
290  }
291 
292  auto sign = ed25519_provider_->sign(key_pair.value(), msg_buffer);
293  if (!sign) {
294  throw_with_error(logger_,
295  "failed to sign message, error = {}",
296  sign.error().message());
297  }
299  logger_, sign.value(), key_pair.value().public_key, msg_buffer);
300  auto buffer = scale::encode(ResultType(sign.value())).value();
301  return getMemory().storeBuffer(buffer);
302  }
303 
306  runtime::WasmSpan msg_span,
307  runtime::WasmPointer pubkey_data) {
308  auto [msg_data, msg_len] = runtime::PtrSize(msg_span);
309  auto msg = getMemory().loadN(msg_data, msg_len);
310  auto sig_bytes =
312 
313  auto signature_res = crypto::Ed25519Signature::fromSpan(sig_bytes);
314  if (!signature_res) {
315  BOOST_UNREACHABLE_RETURN(kVerifyFail);
316  }
317  auto &&signature = signature_res.value();
318 
319  auto pubkey_bytes = getMemory()
321  .toVector();
322  auto pubkey_res = crypto::Ed25519PublicKey::fromSpan(pubkey_bytes);
323  if (!pubkey_res) {
324  BOOST_UNREACHABLE_RETURN(kVerifyFail);
325  }
326  auto pubkey = pubkey_res.value();
327 
328  auto verify_res = ed25519_provider_->verify(signature, msg, pubkey);
329 
330  auto res = verify_res && verify_res.value() ? kVerifySuccess : kVerifyFail;
331 
332  SL_TRACE_FUNC_CALL(logger_, res, signature, msg, pubkey);
333  return res;
334  }
335 
337  runtime::WasmSize key_type) {
338  using ResultType = std::vector<crypto::Sr25519PublicKey>;
339  static const auto error_result(scale::encode(ResultType{}).value());
340 
341  auto key_type_id =
342  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
343  checkIfKeyIsSupported(key_type_id, logger_);
344 
345  auto public_keys = crypto_store_->getSr25519PublicKeys(key_type_id);
346  if (not public_keys) {
347  throw_with_error(logger_,
348  "error loading public keys: {}",
349  public_keys.error().message());
350  }
351 
352  auto buffer = scale::encode(public_keys.value()).value();
353  SL_TRACE_FUNC_CALL(logger_, public_keys.value().size(), key_type_id);
354 
355  return getMemory().storeBuffer(buffer);
356  }
357 
359  runtime::WasmSize key_type, runtime::WasmSpan seed) {
360  auto key_type_id =
361  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
362  checkIfKeyIsSupported(key_type_id, logger_);
363 
364  auto [seed_ptr, seed_len] = runtime::PtrSize(seed);
365  auto seed_buffer = getMemory().loadN(seed_ptr, seed_len);
366  auto seed_res = scale::decode<std::optional<std::string>>(seed_buffer);
367  if (!seed_res) {
368  throw_with_error(logger_, "failed to decode seed");
369  }
370 
371  outcome::result<crypto::Sr25519Keypair> kp_res{{}};
372  auto bip39_seed = seed_res.value();
373  if (bip39_seed.has_value()) {
374  kp_res = crypto_store_->generateSr25519Keypair(key_type_id,
375  bip39_seed.value());
376  } else {
377  kp_res = crypto_store_->generateSr25519KeypairOnDisk(key_type_id);
378  }
379  if (!kp_res) {
380  throw_with_error(logger_,
381  "failed to generate sr25519 key pair: {}",
382  kp_res.error().message());
383  }
384  auto &key_pair = kp_res.value();
385 
386  SL_TRACE_FUNC_CALL(logger_, key_pair.public_key, key_type_id, seed_buffer);
387 
388  common::Buffer buffer(key_pair.public_key);
389  runtime::WasmSpan ps = getMemory().storeBuffer(buffer);
390 
391  return runtime::PtrSize(ps).ptr;
392  }
393 
395  runtime::WasmSize key_type,
397  runtime::WasmSpan msg) {
398  using ResultType = std::optional<crypto::Sr25519Signature>;
399  static const auto error_result =
400  scale::encode(ResultType(std::nullopt)).value();
401 
402  auto key_type_id =
403  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
404  checkIfKeyIsSupported(key_type_id, logger_);
405 
406  auto public_buffer =
407  getMemory().loadN(key, crypto::Sr25519PublicKey::size());
408  auto [msg_data, msg_len] = runtime::PtrSize(msg);
409  auto msg_buffer = getMemory().loadN(msg_data, msg_len);
410  auto pk = crypto::Sr25519PublicKey::fromSpan(public_buffer);
411  if (!pk) {
412  // error is not possible, since we loaded correct number of bytes
413  BOOST_UNREACHABLE_RETURN({});
414  }
415  auto key_pair = crypto_store_->findSr25519Keypair(key_type_id, pk.value());
416  if (!key_pair) {
417  logger_->error("failed to find required key: {}",
418  key_pair.error().message());
419  return getMemory().storeBuffer(error_result);
420  }
421 
422  auto sign = sr25519_provider_->sign(key_pair.value(), msg_buffer);
423  if (!sign) {
424  throw_with_error(logger_,
425  "failed to sign message, error = {}",
426  sign.error().message());
427  }
429  logger_, sign.value(), key_pair.value().public_key, msg_buffer);
430  auto buffer = scale::encode(ResultType(sign.value())).value();
431  return getMemory().storeBuffer(buffer);
432  }
433 
436  runtime::WasmSpan msg_span,
437  runtime::WasmPointer pubkey_data) {
438  // TODO(Harrm): this should support deprecated signatures from schnorrkel
439  // 0.1.1 in contrary to version_2
440  auto [msg_data, msg_len] = runtime::PtrSize(msg_span);
441  auto msg = getMemory().loadN(msg_data, msg_len);
442  auto signature_buffer =
444 
445  auto pubkey_buffer =
447  auto key_res = crypto::Sr25519PublicKey::fromSpan(pubkey_buffer);
448  if (!key_res) {
449  BOOST_UNREACHABLE_RETURN(kVerifyFail)
450  }
451  auto &&key = key_res.value();
452 
453  crypto::Sr25519Signature signature{};
454  std::copy_n(signature_buffer.begin(),
456  signature.begin());
457 
458  auto verify_res = sr25519_provider_->verify_deprecated(signature, msg, key);
459 
460  auto res = verify_res && verify_res.value() ? kVerifySuccess : kVerifyFail;
461 
462  SL_TRACE_FUNC_CALL(logger_, res, signature, msg, pubkey_buffer);
463  return res;
464  }
465 
468  runtime::WasmSpan msg_span,
469  runtime::WasmPointer pubkey_data) {
471  "delegated to ext_crypto_sr25519_verify_version_1");
472  return ext_crypto_sr25519_verify_version_1(sig, msg_span, pubkey_data);
473  }
474 
475  namespace {
476  template <typename T>
477  using failure_type =
478  decltype(outcome::result<std::decay_t<T>>(T{}).as_failure());
479 
485  template <class T>
486  Secp256k1VerifyError convertFailureToError(const failure_type<T> &failure) {
487  const outcome::result<void> res = failure;
488  if (res == outcome::failure(Secp256k1ProviderError::INVALID_V_VALUE)) {
490  }
491  if (res
492  == outcome::failure(Secp256k1ProviderError::INVALID_R_OR_S_VALUE)) {
494  }
495 
497  }
498  } // namespace
499 
503  using ResultType =
504  boost::variant<secp256k1::PublicKey, Secp256k1VerifyError>;
505 
506  constexpr auto signature_size = RSVSignature::size();
507  constexpr auto message_size = MessageHash::size();
508 
509  auto sig_buffer = getMemory().loadN(sig, signature_size);
510  auto msg_buffer = getMemory().loadN(msg, message_size);
511 
512  auto signature = RSVSignature::fromSpan(sig_buffer).value();
513  auto message = MessageHash::fromSpan(msg_buffer).value();
514 
515  auto public_key =
516  secp256k1_provider_->recoverPublickeyUncompressed(signature, message);
517  if (!public_key) {
518  logger_->error("failed to recover uncompressed secp256k1 public key: {}",
519  public_key.error().message());
520 
521  auto error_code =
522  convertFailureToError<UncompressedPublicKey>(public_key.as_failure());
523  auto error_result =
524  scale::encode(static_cast<ResultType>(error_code)).value();
525 
526  return getMemory().storeBuffer(error_result);
527  }
528 
529  // according to substrate implementation
530  // returned key shouldn't include the 0x04 prefix
531  // specification says, that it should have 64 bytes, not 65 as with prefix
532  // On success it contains the 64-byte recovered public key or an error type
533  auto truncated_span = gsl::span<uint8_t>(public_key.value()).subspan(1, 64);
534  auto truncated_public_key =
535  secp256k1::PublicKey::fromSpan(truncated_span).value();
536  SL_TRACE_FUNC_CALL(logger_, truncated_public_key, sig_buffer, msg_buffer);
537  auto buffer = scale::encode(ResultType(truncated_public_key)).value();
538  return getMemory().storeBuffer(buffer);
539  }
540 
544  using ResultType =
545  boost::variant<CompressedPublicKey, Secp256k1VerifyError>;
546 
547  constexpr auto signature_size = RSVSignature::size();
548  constexpr auto message_size = MessageHash::size();
549 
550  auto sig_buffer = getMemory().loadN(sig, signature_size);
551  auto msg_buffer = getMemory().loadN(msg, message_size);
552 
553  auto signature = RSVSignature::fromSpan(sig_buffer).value();
554  auto message = MessageHash::fromSpan(msg_buffer).value();
555 
556  auto public_key =
557  secp256k1_provider_->recoverPublickeyCompressed(signature, message);
558  if (!public_key) {
559  logger_->error("failed to recover uncompressed secp256k1 public key: {}",
560  public_key.error().message());
561 
562  auto error_code =
563  convertFailureToError<CompressedPublicKey>(public_key.as_failure());
564  auto error_result =
565  scale::encode(static_cast<ResultType>(error_code)).value();
566  return getMemory().storeBuffer(error_result);
567  }
568  SL_TRACE_FUNC_CALL(logger_, public_key.value(), sig_buffer, msg_buffer);
569  auto buffer = scale::encode(ResultType(public_key.value())).value();
570  return getMemory().storeBuffer(buffer);
571  }
572 
574  runtime::WasmSize key_type) {
575  using ResultType = std::vector<crypto::EcdsaPublicKey>;
576  static const auto error_result(scale::encode(ResultType{}).value());
577 
578  auto key_type_id =
579  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
580  checkIfKeyIsSupported(key_type_id, logger_);
581 
582  auto public_keys = crypto_store_->getEcdsaPublicKeys(key_type_id);
583  if (not public_keys) {
584  throw_with_error(logger_,
585  "error loading public keys: {}",
586  public_keys.error().message());
587  }
588 
589  auto buffer = scale::encode(public_keys.value()).value();
590  SL_TRACE_FUNC_CALL(logger_, public_keys.value().size(), key_type_id);
591 
592  return getMemory().storeBuffer(buffer);
593  }
594 
596  runtime::WasmSize key_type,
598  runtime::WasmSpan msg) {
599  using ResultType = std::optional<crypto::EcdsaSignature>;
600 
601  auto key_type_id =
602  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
603  checkIfKeyIsSupported(key_type_id, logger_);
604 
605  auto public_buffer = getMemory().loadN(key, sizeof(crypto::EcdsaPublicKey));
606  auto [msg_data, msg_len] = runtime::PtrSize(msg);
607  auto msg_buffer = getMemory().loadN(msg_data, msg_len);
608 
609  crypto::EcdsaPublicKey pk;
610  std::copy(public_buffer.begin(), public_buffer.end(), pk.begin());
611  auto key_pair = crypto_store_->findEcdsaKeypair(key_type_id, pk);
612  if (!key_pair) {
613  logger_->error("failed to find required key");
614  auto error_result = scale::encode(ResultType(std::nullopt)).value();
615  return getMemory().storeBuffer(error_result);
616  }
617 
618  auto sign = ecdsa_provider_->sign(msg_buffer, key_pair.value().secret_key);
619  if (!sign) {
620  throw_with_error(logger_,
621  "failed to sign message, error = {}",
622  sign.error().message());
623  }
625  logger_, sign.value(), key_pair.value().public_key, msg_buffer);
626  auto buffer = scale::encode(ResultType(sign.value())).value();
627  return getMemory().storeBuffer(buffer);
628  }
629 
631  runtime::WasmSize key_type,
633  runtime::WasmSpan msg) {
634  using ResultType = std::optional<crypto::EcdsaSignature>;
635 
636  auto key_type_id =
637  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
638  checkIfKeyIsSupported(key_type_id, logger_);
639 
640  auto public_buffer = getMemory().loadN(key, sizeof(crypto::EcdsaPublicKey));
641  auto [msg_data, msg_len] = runtime::PtrSize(msg);
642  auto msg_buffer = getMemory().loadN(msg_data, msg_len);
643 
644  crypto::EcdsaPublicKey pk;
645  std::copy(public_buffer.begin(), public_buffer.end(), pk.begin());
646  auto key_pair = crypto_store_->findEcdsaKeypair(key_type_id, pk);
647  if (!key_pair) {
648  logger_->error("failed to find required key");
649  auto error_result = scale::encode(ResultType(std::nullopt)).value();
650  return getMemory().storeBuffer(error_result);
651  }
652 
654  std::copy(msg_buffer.begin(), msg_buffer.end(), digest.begin());
655  auto sign =
656  ecdsa_provider_->signPrehashed(digest, key_pair.value().secret_key);
657  if (!sign) {
658  throw_with_error(logger_,
659  "failed to sign message, error = {}",
660  sign.error().message());
661  }
663  logger_, sign.value(), key_pair.value().public_key, msg_buffer);
664  auto buffer = scale::encode(ResultType(sign.value())).value();
665  return getMemory().storeBuffer(buffer);
666  }
667 
669  runtime::WasmSize key_type, runtime::WasmSpan seed) const {
670  auto key_type_id =
671  static_cast<crypto::KeyTypeId>(getMemory().load32u(key_type));
672  checkIfKeyIsSupported(key_type_id, logger_);
673 
674  auto [seed_ptr, seed_len] = runtime::PtrSize(seed);
675  auto seed_buffer = getMemory().loadN(seed_ptr, seed_len);
676  auto seed_res = scale::decode<std::optional<std::string>>(seed_buffer);
677  if (!seed_res) {
678  throw_with_error(logger_, "failed to decode seed");
679  }
680 
681  outcome::result<crypto::EcdsaKeypair> kp_res{{}};
682  auto bip39_seed = seed_res.value();
683  if (bip39_seed.has_value()) {
684  kp_res =
685  crypto_store_->generateEcdsaKeypair(key_type_id, bip39_seed.value());
686  } else {
687  kp_res = crypto_store_->generateEcdsaKeypairOnDisk(key_type_id);
688  }
689  if (!kp_res) {
690  throw_with_error(logger_,
691  "failed to generate ecdsa key pair: {}",
692  kp_res.error().message());
693  }
694  auto &key_pair = kp_res.value();
695 
696  SL_TRACE_FUNC_CALL(logger_, key_pair.public_key, key_type_id, seed_buffer);
697 
698  common::Buffer buffer(key_pair.public_key);
699  runtime::WasmSpan ps = getMemory().storeBuffer(buffer);
700 
701  return runtime::PtrSize(ps).ptr;
702  }
703 
706  runtime::WasmSpan msg_span,
707  runtime::WasmPointer pubkey_data) const {
708  auto [msg_data, msg_len] = runtime::PtrSize(msg_span);
709  auto msg = getMemory().loadN(msg_data, msg_len);
710  auto signature =
712 
713  auto pubkey_buffer =
715  auto key_res = crypto::EcdsaPublicKey::fromSpan(pubkey_buffer);
716  if (!key_res) {
717  BOOST_UNREACHABLE_RETURN(kVerifyFail)
718  }
719  auto &&pubkey = key_res.value();
720 
721  auto verify_res = ecdsa_provider_->verify(msg, signature, pubkey);
722 
723  auto res = verify_res && verify_res.value() ? kVerifySuccess : kVerifyFail;
724 
725  SL_TRACE_FUNC_CALL(logger_, res, signature, msg, pubkey);
726  return res;
727  }
728 
731  runtime::WasmSpan msg_span,
732  runtime::WasmPointer pubkey_data) const {
733  auto [msg_data, msg_len] = runtime::PtrSize(msg_span);
734  auto msg = getMemory().loadN(msg_data, msg_len);
735  auto signature =
737 
738  auto pubkey_buffer =
740  auto key_res = crypto::EcdsaPublicKey::fromSpan(pubkey_buffer);
741  if (!key_res) {
742  BOOST_UNREACHABLE_RETURN(kVerifyFail)
743  }
744  auto &&pubkey = key_res.value();
745 
747  std::copy(msg.begin(), msg.end(), digest.begin());
748 
749  auto verify_res =
750  ecdsa_provider_->verifyPrehashed(digest, signature, pubkey);
751 
752  auto res = verify_res && verify_res.value() ? kVerifySuccess : kVerifyFail;
753 
754  SL_TRACE_FUNC_CALL(logger_, res, signature, msg, pubkey);
755  return res;
756  }
757 } // namespace kagome::host_api
int32_t ext_crypto_ecdsa_verify_version_1(runtime::WasmPointer sig, runtime::WasmSpan msg, runtime::WasmPointer key) const
static constexpr uint32_t kVerifySuccess
common::Blob< 32 > deriveSeed(std::string_view content)
Class represents arbitrary (including empty) byte buffer.
Definition: buffer.hpp:29
int32_t ext_crypto_sr25519_verify_version_2(runtime::WasmPointer sig, runtime::WasmSpan msg, runtime::WasmPointer pubkey_data)
CryptoExtension(std::shared_ptr< const runtime::MemoryProvider > memory_provider, std::shared_ptr< const crypto::Sr25519Provider > sr25519_provider, std::shared_ptr< const crypto::EcdsaProvider > ecdsa_provider, std::shared_ptr< const crypto::Ed25519Provider > ed25519_provider, std::shared_ptr< const crypto::Secp256k1Provider > secp256k1_provider, std::shared_ptr< const crypto::Hasher > hasher, std::shared_ptr< crypto::CryptoStore > crypto_store, std::shared_ptr< const crypto::Bip39Provider > bip39_provider)
runtime::WasmPointer ext_crypto_ed25519_generate_version_1(runtime::WasmSize key_type, runtime::WasmSpan seed)
uint32_t WasmSize
Size type is uint32_t because we are working in 32 bit address space.
Definition: types.hpp:35
std::shared_ptr< const crypto::Ed25519Provider > ed25519_provider_
WasmPointer ptr
address of buffer
Definition: ptr_size.hpp:40
runtime::WasmPointer ext_crypto_sr25519_generate_version_1(runtime::WasmSize key_type, runtime::WasmSpan seed)
std::shared_ptr< const crypto::Secp256k1Provider > secp256k1_provider_
runtime::WasmSize ext_crypto_ed25519_verify_version_1(runtime::WasmPointer sig, runtime::WasmSpan msg, runtime::WasmPointer pubkey_data)
runtime::Memory & getMemory() const
#define SL_TRACE_FUNC_CALL(logger, ret,...)
Definition: logger.hpp:142
int32_t ext_crypto_ecdsa_verify_prehashed_version_1(runtime::WasmPointer sig, runtime::WasmSpan msg, runtime::WasmPointer key) const
runtime::WasmPointer ext_hashing_blake2_128_version_1(runtime::WasmSpan data)
STL namespace.
static constexpr uint32_t kVerifyFail
common::Blob< constants::kCompressedPublicKeySize > CompressedPublicKey
virtual common::Buffer loadN(WasmPointer addr, WasmSize n) const =0
virtual uint32_t load32u(WasmPointer addr) const =0
runtime::WasmSpan ext_crypto_ecdsa_public_keys_version_1(runtime::WasmSize key_type)
runtime::WasmSpan ext_crypto_secp256k1_ecdsa_recover_version_1(runtime::WasmPointer sig, runtime::WasmPointer msg)
uint32_t KeyTypeId
Key type identifier.
Definition: key_type.hpp:21
runtime::WasmPointer ext_hashing_keccak_256_version_1(runtime::WasmSpan data)
runtime::WasmPointer ext_hashing_twox_64_version_1(runtime::WasmSpan data)
common::Blob< constants::kUncompressedPublicKeySize > UncompressedPublicKey
runtime::WasmSpan ext_crypto_sr25519_sign_version_1(runtime::WasmSize key_type, runtime::WasmPointer key, runtime::WasmSpan msg)
std::shared_ptr< crypto::CryptoStore > crypto_store_
runtime::WasmPointer ext_crypto_ecdsa_generate_version_1(runtime::WasmSize key_type_id, runtime::WasmSpan seed) const
int32_t ext_crypto_sr25519_verify_version_1(runtime::WasmPointer sig, runtime::WasmSpan msg, runtime::WasmPointer pubkey_data)
static constexpr Secp256k1VerifyError kInvalidRS
static constexpr Secp256k1VerifyError kInvalidV
static outcome::result< Mnemonic > parse(std::string_view phrase)
parse mnemonic from phrase
Definition: mnemonic.cpp:34
common::Blob< constants::kCompactSignatureSize > RSVSignature
libp2p::crypto::ecdsa::PrehashedMessage EcdsaPrehashedMessage
Definition: ecdsa_types.hpp:45
runtime::WasmPointer ext_hashing_twox_128_version_1(runtime::WasmSpan data)
std::shared_ptr< soralog::Logger > Logger
Definition: logger.hpp:23
runtime::WasmSpan ext_crypto_ed25519_sign_version_1(runtime::WasmSize key_type, runtime::WasmPointer key, runtime::WasmSpan msg)
static outcome::result< Blob< size_ > > fromSpan(const gsl::span< const uint8_t > &span)
Definition: blob.hpp:208
runtime::WasmSize ext_crypto_finish_batch_verify_version_1()
uint64_t WasmSpan
combination of pointer and size, where less significant part represents wasm pointer, and most significant represents size
Definition: types.hpp:31
runtime::WasmSpan ext_crypto_sr25519_public_keys_version_1(runtime::WasmSize key_type)
static constexpr uint32_t kVerifyBatchSuccess
std::shared_ptr< const crypto::Sr25519Provider > sr25519_provider_
uint32_t WasmPointer
type of wasm memory is 32 bit integer
Definition: types.hpp:26
std::shared_ptr< const crypto::Bip39Provider > bip39_provider_
runtime::WasmPointer ext_hashing_twox_256_version_1(runtime::WasmSpan data)
runtime::WasmSpan ext_crypto_ecdsa_sign_version_1(runtime::WasmSize key_type, runtime::WasmPointer key, runtime::WasmSpan msg)
static constexpr size_t size()
Definition: blob.hpp:146
std::string encodeKeyTypeIdToStr(KeyTypeId key_type_id)
makes string representation of KeyTypeId
Definition: key_type.cpp:29
runtime::WasmSpan ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(runtime::WasmPointer sig, runtime::WasmPointer msg)
runtime::WasmSpan ext_crypto_ed25519_public_keys_version_1(runtime::WasmSize key_type)
virtual void storeBuffer(WasmPointer addr, gsl::span< const uint8_t > value)=0
runtime::WasmPointer ext_hashing_blake2_256_version_1(runtime::WasmSpan data)
Logger createLogger(const std::string &tag)
Definition: logger.cpp:112
bool isSupportedKeyType(KeyTypeId k)
checks whether key type value is supported
Definition: key_type.cpp:14
std::shared_ptr< const crypto::EcdsaProvider > ecdsa_provider_
static constexpr Secp256k1VerifyError kInvalidSignature
runtime::WasmPointer ext_hashing_sha2_256_version_1(runtime::WasmSpan data)
runtime::WasmSpan ext_crypto_ecdsa_sign_prehashed_version_1(runtime::WasmSize key_type, runtime::WasmPointer key, runtime::WasmSpan msg)
std::shared_ptr< const runtime::MemoryProvider > memory_provider_
std::vector< uint8_t > toVector()&
Definition: buffer.hpp:143
std::shared_ptr< const crypto::Hasher > hasher_