CppSecurity  1.1.1.0
C++ Security Library
cipher.cpp
Go to the documentation of this file.
1 
9 #include "security/cipher.h"
10 
11 #include "errors/exceptions.h"
12 #include "string/format.h"
13 #include "utility/countof.h"
14 
15 namespace CppSecurity {
16 
17 Cipher::Cipher(CipherAlgorithm algorithm, size_t iterations)
18  : _algorithm(algorithm),
19  _iterations(iterations),
20  _encrypt(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free),
21  _decrypt(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free)
22 {
23  switch (algorithm)
24  {
26  _name = "AES-128";
27  _cipher = EVP_aes_128_cbc();
28  break;
30  _name = "AES-192";
31  _cipher = EVP_aes_192_cbc();
32  break;
34  _name = "AES-256";
35  _cipher = EVP_aes_256_cbc();
36  break;
38  _name = "ARIA-128";
39  _cipher = EVP_aria_128_cbc();
40  break;
42  _name = "ARIA-192";
43  _cipher = EVP_aria_192_cbc();
44  break;
46  _name = "ARIA-256";
47  _cipher = EVP_aria_256_cbc();
48  break;
50  _name = "Camellia-128";
51  _cipher = EVP_camellia_128_cbc();
52  break;
54  _name = "Camellia-192";
55  _cipher = EVP_camellia_192_cbc();
56  break;
58  _name = "Camellia-256";
59  _cipher = EVP_camellia_256_cbc();
60  break;
61  }
62 
63  // Validate cipher algorithm
64  assert((_cipher != nullptr) && "Unknown cipher algorithm!");
65  if (_cipher == nullptr)
66  throwex CppCommon::SecurityException("Unknown cipher algorithm!");
67 
68  // Validate cipher encrypt context
69  assert((_encrypt != nullptr) && "Invalid cipher encrypt context!");
70  if (_encrypt == nullptr)
71  throwex CppCommon::SecurityException("Invalid cipher encrypt context!");
72 
73  // Validate cipher decrypt context
74  assert((_decrypt != nullptr) && "Invalid cipher decrypt context!");
75  if (_decrypt == nullptr)
76  throwex CppCommon::SecurityException("Invalid cipher decrypt context!");
77 }
78 
79 std::string Cipher::GenerateSalt()
80 {
81  std::string result(8, 0);
82  CppCommon::Memory::CryptoFill(result.data(), result.size());
83  return result;
84 }
85 
86 void Cipher::Initialize(std::string_view secret)
87 {
88  int result = EVP_BytesToKey(_cipher, EVP_sha1(), nullptr, (const uint8_t*)secret.data(), (int)secret.size(), (int)_iterations, _key, _iv);
89  if (result == 0)
90  throwex CppCommon::SecurityException(CppCommon::format("Cannot initialize key and IV for {} cipher!", _name));
91  InitializeContext();
92 }
93 
94 void Cipher::Initialize(std::string_view secret, std::string_view salt)
95 {
96  uint8_t salta[8];
97  std::memcpy(salta, salt.data(), std::min(salt.size(), CppCommon::countof(salta)));
98  int result = EVP_BytesToKey(_cipher, EVP_sha1(), salta, (const uint8_t*)secret.data(), (int)secret.size(), (int)_iterations, _key, _iv);
99  if (result == 0)
100  throwex CppCommon::SecurityException(CppCommon::format("Cannot initialize key and IV for {} cipher!", _name));
101  InitializeContext();
102 }
103 
104 void Cipher::InitializeContext()
105 {
106  // Initialize encrypt context
107  EVP_CIPHER_CTX_init(_encrypt.get());
108  if (EVP_EncryptInit_ex(_encrypt.get(), _cipher, nullptr, _key, _iv) == 0)
109  throwex CppCommon::SecurityException(CppCommon::format("Cannot initialize encrypt context for {} cipher!", _name));
110 
111  // Initialize decrypt context
112  EVP_CIPHER_CTX_init(_decrypt.get());
113  if (EVP_DecryptInit_ex(_decrypt.get(), _cipher, nullptr, _key, _iv) == 0)
114  throwex CppCommon::SecurityException(CppCommon::format("Cannot initialize decrypt context for {} cipher!", _name));
115 }
116 
117 std::string Cipher::Encrypt(std::string_view str)
118 {
119  std::string result(str.size() + EVP_MAX_BLOCK_LENGTH, 0);
120 
121  // Initialize encrypt context
122  if (EVP_EncryptInit_ex(_encrypt.get(), nullptr, nullptr, nullptr, nullptr) == 0)
123  throwex CppCommon::SecurityException(CppCommon::format("Cannot initialize encrypt context for {} cipher!", _name));
124 
125  // Update encrypt context with plane data
126  int cur_length = 0;
127  if (EVP_EncryptUpdate(_encrypt.get(), (uint8_t*)result.data(), &cur_length, (const uint8_t*)str.data(), (int)str.size()) == 0)
128  throwex CppCommon::SecurityException(CppCommon::format("Cannot encrypt data with {} cipher!", _name));
129 
130  // Finalize the encrypted context
131  int fin_length = 0;
132  if (EVP_EncryptFinal_ex(_encrypt.get(), (uint8_t*)result.data() + cur_length, &fin_length) == 0)
133  throwex CppCommon::SecurityException(CppCommon::format("Cannot finalize encrypted data with {} cipher!", _name));
134 
135  // Return the encrypted data
136  result.resize(cur_length + fin_length);
137  return result;
138 }
139 
140 std::string Cipher::Decrypt(std::string_view str)
141 {
142  std::string result(str.size(), 0);
143 
144  // Initialize decrypt context
145  if (EVP_DecryptInit_ex(_decrypt.get(), nullptr, nullptr, nullptr, nullptr) == 0)
146  throwex CppCommon::SecurityException(CppCommon::format("Cannot initialize decrypt context for {} cipher!", _name));
147 
148  // Update decrypt context with encrypted data
149  int cur_length = 0;
150  if (EVP_DecryptUpdate(_decrypt.get(), (uint8_t*)result.data(), &cur_length, (const uint8_t*)str.data(), (int)str.size()) == 0)
151  throwex CppCommon::SecurityException(CppCommon::format("Cannot decrypt data with {} cipher!", _name));
152 
153  // Finalize the decrypted data
154  int fin_length = 0;
155  if (EVP_DecryptFinal_ex(_decrypt.get(), (uint8_t*)result.data() + cur_length, &fin_length) == 0)
156  throwex CppCommon::SecurityException(CppCommon::format("Cannot finalize decrypted data with {} cipher!", _name));
157 
158  // Return the decrypted data
159  result.resize(cur_length + fin_length);
160  return result;
161 }
162 
163 } // namespace CppSecurity
Cipher definition.
void Initialize(std::string_view secret)
Initialize the cipher with the given secret key.
Definition: cipher.cpp:86
CipherAlgorithm algorithm() const noexcept
Get the cipher algorithm.
Definition: cipher.h:75
static std::string GenerateSalt()
Generate the unique secret salt.
Definition: cipher.cpp:79
std::string Decrypt(std::string_view str)
Decrypt the given string.
Definition: cipher.cpp:140
std::string Encrypt(std::string_view str)
Encrypt the given string.
Definition: cipher.cpp:117
Cipher(CipherAlgorithm algorithm=CipherAlgorithm::AES256, size_t iterations=1000)
Initialize cipher with required algorithm.
Definition: cipher.cpp:17
CipherAlgorithm
Cipher algorithm.
Definition: cipher.h:22