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