You need to sign in or sign up before continuing.
Newer
Older
#include "mtxclient/crypto/utils.hpp"
#include <iostream>
namespace mtx {
namespace crypto {
BinaryBuf
PBKDF2_HMAC_SHA_512(const std::string pass, const BinaryBuf salt, uint32_t iterations) {
uint8_t out[SHA512_DIGEST_LENGTH];
PKCS5_PBKDF2_HMAC(&pass[0], pass.size(), salt.data(), salt.size(), iterations, EVP_sha512(), SHA512_DIGEST_LENGTH, out);
BinaryBuf output(out, out + SHA512_DIGEST_LENGTH);
return output;
}
BinaryBuf
AES_CTR_256_Encrypt(const std::string plaintext, const BinaryBuf aes256Key, BinaryBuf iv) {
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
unsigned char *cipher = new unsigned char[plaintext.size()];
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
uint8_t *iv_data = iv.data();
// need to set bit 63 to 0
*(iv_data) &= ~(1UL << 63);
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) {
//handleErrors();
}
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, aes256Key.data(), iv_data)) {
//handleErrors();
}
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, cipher, &len, reinterpret_cast<const unsigned char*>(&plaintext.c_str()[0]), plaintext.size())) {
//handleErrors();
}
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, cipher + len, &len)) {
//handleErrors();
}
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
BinaryBuf encrypted(reinterpret_cast<uint8_t *>(cipher), cipher + ciphertext_len);
delete [] cipher;
return encrypted;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
BinaryBuf
AES_CTR_256_Decrypt(const std::string ciphertext, const BinaryBuf aes256Key, BinaryBuf iv)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
unsigned char *plaintext = new unsigned char[ciphertext.size()];
/* Create and initialise the context */
if (!(ctx = EVP_CIPHER_CTX_new())) {
// handleErrors();
}
/* Initialise the decryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, aes256Key.data(), iv.data())) {
// handleErrors();
}
/* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary
*/
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, reinterpret_cast<const unsigned char*>(&ciphertext.data()[0]), ciphertext.size())) {
// handleErrors();
}
plaintext_len = len;
/* Finalise the decryption. Further plaintext bytes may be written at
* this stage.
*/
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
// handleErrors();
}
plaintext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
BinaryBuf decrypted(reinterpret_cast<uint8_t *>(plaintext), plaintext + plaintext_len);
delete[] plaintext;
return decrypted;
}
template<typename T>
void remove_substrs(std::basic_string<T>& s,
const std::basic_string<T>& p) {
auto n = p.length();
for (auto i = s.find(p);
i != std::basic_string<T>::npos;
i = s.find(p))
s.erase(i, n);
}
std::string
unpack_key_file(const std::string &data) {
std::string unpacked(data);
remove_substrs(unpacked, HEADER_LINE);
remove_substrs(unpacked, TRAILER_LINE);
remove_substrs(unpacked, std::string("\n"));
return unpacked;
}
BinaryBuf
HMAC_SHA256 (const BinaryBuf hmacKey, const BinaryBuf data) {
unsigned int len = SHA256_DIGEST_LENGTH;
unsigned char digest[SHA256_DIGEST_LENGTH];
HMAC(EVP_sha256(), hmacKey.data(), hmacKey.size(), data.data(), data.size(), digest, &len);
BinaryBuf output(digest, digest + SHA256_DIGEST_LENGTH);
return output;
}
void
print_binary_buf(const BinaryBuf buf) {
for (uint8_t val : buf) {
std::cout << std::to_string(val) << ",";
}
std::cout << std::endl;
}
void uint8_to_uint32(uint8_t b[4], uint32_t &u32) {
u32 = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
}
void uint32_to_uint8 (uint8_t b[4], uint32_t u32) {
b[3] = (uint8_t)u32;
b[2] = (uint8_t)(u32>>=8);
b[1] = (uint8_t)(u32>>=8);
b[0] = (uint8_t)(u32>>=8);
}
} // namespace crypto
} // namespace mtx