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
|