-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcrypto.cpp
93 lines (71 loc) · 3.05 KB
/
crypto.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
61
62
63
64
65
66
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
#include "crypto.h"
#include "cryptopp/aes.h"
#include "cryptopp/modes.h"
#include "cryptopp/sha.h"
#include "cryptopp/filters.h"
#include "cryptopp/pwdbased.h"
#include "cryptopp/osrng.h"
/**
* Decrypt a value using AES-256 CBC, where the first block is the message IV, and verify the PKCS#5 message padding
* is correct.
*
* @throws BadPaddingException if padding is bad or input is the wrong size
*/
std::string Code42AES256RandomIV::decrypt(const std::string & cipherText, const std::string &key) const {
// We expect the encrypted value to start with an IV and be padded to a full block size (padding)
if (cipherText.length() < CryptoPP::AES::BLOCKSIZE * 2 || cipherText.length() % CryptoPP::AES::BLOCKSIZE != 0) {
throw BadPaddingException();
}
// The first block of the input is the random IV:
const CryptoPP::byte *iv = (const CryptoPP::byte *) cipherText.data();
// And the remainder is ciphertext:
const CryptoPP::byte *encrypted = (const CryptoPP::byte *) cipherText.data() + CryptoPP::AES::BLOCKSIZE;
int encryptedSize = cipherText.length() - CryptoPP::AES::BLOCKSIZE;
uint8_t *buffer = new uint8_t[encryptedSize];
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryptor((const CryptoPP::byte *)key.data(), 256 / 8, iv);
decryptor.ProcessData(buffer, encrypted, encryptedSize);
// Verify padding is correct after decryption:
uint8_t padByte = buffer[encryptedSize - 1];
if (padByte <= 0 || padByte > CryptoPP::AES::BLOCKSIZE) {
throw BadPaddingException();
}
for (int i = 1; i < padByte; i++) {
if (buffer[encryptedSize - 1 - i] != padByte) {
throw BadPaddingException();
}
}
int unpaddedLength = encryptedSize - padByte;
std::string result((const char *) buffer, unpaddedLength);
delete[] buffer;
return result;
}
std::string Code42AES256RandomIV::encrypt(const std::string & plainText, const std::string & key) const {
CryptoPP::AutoSeededRandomPool prng;
CryptoPP::byte iv[CryptoPP::AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption e((const CryptoPP::byte *)key.data(), 256 / 8, iv);
// First block of output is the IV:
std::string result((const char *) iv, sizeof(iv));
// Followed by the ciphertext:
CryptoPP::StringSource ss(
plainText,
true,
new CryptoPP::StreamTransformationFilter(
e,
new CryptoPP::StringSink(result),
CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
)
);
return result;
}
std::string generateSmallBusinessKeyV2(const std::string &passphrase, const std::string &salt) {
CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA512> generator;
CryptoPP::byte derived[32];
generator.DeriveKey(
derived, sizeof(derived), 0,
(const CryptoPP::byte*) passphrase.data(), passphrase.length(),
(const CryptoPP::byte*) salt.data(), salt.length(),
10000
);
return std::string((const char *)derived, sizeof(derived));
}