LCOV - code coverage report
Current view: top level - libs/crypto - keys_manager_impl.cpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 61 63 96.8 %
Date: 2019-03-07 14:46:43 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #include "crypto/keys_manager_impl.hpp"
       7             : 
       8             : #include <fstream>
       9             : 
      10             : #include "common/byteutils.hpp"
      11             : #include "cryptography/crypto_provider/crypto_defaults.hpp"
      12             : #include "logger/logger.hpp"
      13             : 
      14             : using namespace shared_model::crypto;
      15             : 
      16             : using iroha::operator|;
      17             : 
      18             : namespace iroha {
      19             :   /**
      20             :    * Function for the key encryption via XOR
      21             :    * @tparam is a key type
      22             :    * @param privkey is a private key
      23             :    * @param pass_phrase is a key for encryption
      24             :    * @return encrypted string
      25             :    */
      26             :   template <typename T>
      27             :   static std::string encrypt(const T &key, const std::string &pass_phrase) {
      28          18 :     std::string ciphertext(key.size(), '\0');
      29          18 :     const size_t min_pass_size = 1;
      30             :     // pass_size will always be > 0
      31          18 :     const auto pass_size = std::max(min_pass_size, pass_phrase.size());
      32             :     // When pass_phrase is empty it, pass_phrase[0] is "\0", so no out_of_range
      33             :     // exception is possible
      34         562 :     for (size_t i = 0; i < key.size(); i++) {
      35         544 :       ciphertext[i] = key[i] ^ pass_phrase[i % pass_size];
      36         544 :     }
      37          18 :     return ciphertext;
      38          18 :   }
      39             : 
      40             :   /**
      41             :    * Function for XOR decryption
      42             :    */
      43             :   static constexpr auto decrypt = encrypt<Blob::Bytes>;
      44             : 
      45             :   KeysManagerImpl::KeysManagerImpl(
      46             :       const std::string &account_id,
      47             :       const boost::filesystem::path &path_to_keypair,
      48             :       logger::LoggerPtr log)
      49          19 :       : path_to_keypair_(path_to_keypair),
      50          19 :         account_id_(account_id),
      51          19 :         log_(std::move(log)) {}
      52             : 
      53             :   /**
      54             :    * Here we use an empty string as a default value of path to file,
      55             :    * since there are usages of KeysManagerImpl with path passed as a part of
      56             :    * account_id.
      57             :    */
      58             :   KeysManagerImpl::KeysManagerImpl(const std::string account_id,
      59             :                                    logger::LoggerPtr log)
      60          13 :       : KeysManagerImpl(account_id, "", std::move(log)) {}
      61             : 
      62             :   bool KeysManagerImpl::validate(const Keypair &keypair) const {
      63             :     try {
      64          13 :       auto test = Blob("12345");
      65          13 :       auto sig = DefaultCryptoAlgorithmType::sign(test, keypair);
      66          11 :       if (not DefaultCryptoAlgorithmType::verify(
      67          11 :               sig, test, keypair.publicKey())) {
      68           3 :         log_->error("key validation failed");
      69           3 :         return false;
      70             :       }
      71          19 :     } catch (const BadFormatException &exception) {
      72           2 :       log_->error("Cannot validate keyapir: {}", exception.what());
      73           2 :       return false;
      74           2 :     }
      75           8 :     return true;
      76          13 :   }
      77             : 
      78             :   boost::optional<std::string> KeysManagerImpl::loadFile(
      79             :       const boost::filesystem::path &path) const {
      80          32 :     auto file_path = path.string();
      81          32 :     std::ifstream file(file_path);
      82          32 :     if (not file) {
      83           4 :       log_->error("Cannot read '" + file_path + "'");
      84           4 :       return {};
      85             :     }
      86             : 
      87          28 :     std::string contents;
      88          28 :     file >> contents;
      89          28 :     return contents;
      90          32 :   }
      91             : 
      92             :   boost::optional<Keypair> KeysManagerImpl::loadKeys() {
      93          13 :     return loadKeys("");
      94           0 :   }
      95             : 
      96             :   boost::optional<Keypair> KeysManagerImpl::loadKeys(
      97             :       const std::string &pass_phrase) {
      98             :     auto public_key =
      99          16 :         loadFile(path_to_keypair_ / (account_id_ + kPublicKeyExtension));
     100             :     auto private_key =
     101          16 :         loadFile(path_to_keypair_ / (account_id_ + kPrivateKeyExtension));
     102             : 
     103          16 :     if (not public_key or not private_key) {
     104           3 :       return boost::none;
     105             :     }
     106             : 
     107          13 :     Keypair keypair = Keypair(
     108          13 :         PublicKey(Blob::fromHexString(public_key.get())),
     109          13 :         PrivateKey(decrypt(Blob::fromHexString(private_key.get()).blob(),
     110          13 :                            pass_phrase)));
     111             : 
     112          13 :     return validate(keypair) ? boost::make_optional(keypair) : boost::none;
     113          16 :   }
     114             : 
     115             :   bool KeysManagerImpl::createKeys() {
     116           1 :     return createKeys("");
     117           0 :   }
     118             : 
     119             :   bool KeysManagerImpl::createKeys(const std::string &pass_phrase) {
     120           5 :     Keypair keypair = DefaultCryptoAlgorithmType::generateKeypair();
     121             : 
     122           5 :     auto pub = keypair.publicKey().hex();
     123           5 :     auto priv = bytestringToHexstring(
     124           5 :         encrypt(keypair.privateKey().blob(), pass_phrase));
     125           5 :     return store(pub, priv);
     126           5 :   }
     127             : 
     128             :   bool KeysManagerImpl::store(const std::string &pub, const std::string &priv) {
     129           5 :     std::ofstream pub_file(
     130           5 :         (path_to_keypair_ / (account_id_ + kPublicKeyExtension)).string());
     131           5 :     std::ofstream priv_file(
     132           5 :         (path_to_keypair_ / (account_id_ + kPrivateKeyExtension)).string());
     133           5 :     if (not pub_file or not priv_file) {
     134           1 :       return false;
     135             :     }
     136             : 
     137           4 :     pub_file << pub;
     138           4 :     priv_file << priv;
     139           4 :     return pub_file.good() && priv_file.good();
     140           5 :   }
     141             : 
     142             :   const std::string KeysManagerImpl::kPublicKeyExtension = ".pub";
     143             :   const std::string KeysManagerImpl::kPrivateKeyExtension = ".priv";
     144             : }  // namespace iroha

Generated by: LCOV version 1.13