9 #include <openssl/evp.h>
10 #include <openssl/rand.h>
32 Key *Key::CreateRandomly(
const unsigned size) {
35 result->
data_ =
reinterpret_cast<unsigned char *
>(smalloc(size));
37 int retval = RAND_bytes(result->
data_, result->
size_);
47 Key *Key::CreateFromFile(
const string &path) {
48 int fd = open(path.c_str(), O_RDONLY);
59 if ((info.st_size == 0) || (info.st_size > kMaxSize)) {
65 result->
size_ = info.st_size;
66 result->
data_ =
reinterpret_cast<unsigned char *
>(smalloc(result->
size_));
67 int nbytes = read(fd, result->
data_, result->
size_);
69 if ((nbytes < 0) || (static_cast<unsigned>(nbytes) != result->
size_)) {
77 Key *Key::CreateFromString(
const string &key) {
78 unsigned size = key.size();
79 if ((size == 0) || (size > kMaxSize))
83 result->data_ =
reinterpret_cast<unsigned char *
>(smalloc(size));
84 memcpy(result->data_, key.data(),
size);
91 memset(data_, 0, size_);
97 bool Key::SaveToFile(
const std::string &path) {
98 int fd = open(path.c_str(), O_WRONLY);
103 int nbytes = write(fd, data_, size_);
105 return (nbytes >= 0) && (
static_cast<unsigned>(nbytes) == size_);
109 string Key::ToBase64()
const {
110 return Base64(
string(reinterpret_cast<const char *>(data_), size_));
117 MemoryKeyDatabase::MemoryKeyDatabase() {
118 lock_ =
reinterpret_cast<pthread_mutex_t *
>(smalloc(
sizeof(pthread_mutex_t)));
119 int retval = pthread_mutex_init(lock_, NULL);
124 MemoryKeyDatabase::~MemoryKeyDatabase() {
125 pthread_mutex_destroy(lock_);
130 bool MemoryKeyDatabase::StoreNew(
const Key *key,
string *
id) {
136 map<string, const Key *>::const_iterator i = database_.find(*
id);
137 if (i != database_.end())
140 database_[*id] = key;
145 const Key *MemoryKeyDatabase::Find(
const string &
id) {
147 map<string, const Key *>::const_iterator i = database_.find(
id);
148 if (i != database_.end())
170 bool Cipher::Encrypt(
const string &plaintext,
172 string *ciphertext) {
174 if (key.
size() != key_size())
177 unsigned char envelope = 0 & 0x0F;
179 ciphertext->push_back(envelope);
181 *ciphertext += DoEncrypt(plaintext, key);
186 bool Cipher::Decrypt(
const string &ciphertext,
190 if (ciphertext.size() < 1)
192 unsigned char envelope = ciphertext[0];
193 unsigned char version = envelope & 0x0F;
196 unsigned char algorithm = (envelope & 0xF0) >> 4;
197 if (algorithm >
kNone)
201 if (key.
size() != cipher->key_size())
203 *plaintext += cipher->DoDecrypt(ciphertext.substr(1), key);
211 string CipherAes256Cbc::DoDecrypt(
const string &ciphertext,
const Key &key) {
214 if (ciphertext.size() < kIvSize)
217 const unsigned char *iv =
reinterpret_cast<const unsigned char *
>(
221 unsigned char *plaintext =
reinterpret_cast<unsigned char *
>(
222 smalloc(kBlockSize + ciphertext.size() - kIvSize));
225 #ifdef OPENSSL_API_INTERFACE_V11
226 EVP_CIPHER_CTX *ctx_ptr = EVP_CIPHER_CTX_new();
229 EVP_CIPHER_CTX_init(&ctx);
230 EVP_CIPHER_CTX *ctx_ptr = &
ctx;
232 retval = EVP_DecryptInit_ex(ctx_ptr, EVP_aes_256_cbc(), NULL, key.
data(), iv);
234 retval = EVP_DecryptUpdate(
235 ctx_ptr, plaintext, &plaintext_len,
236 reinterpret_cast<const unsigned char *>(ciphertext.data() + kIvSize),
237 ciphertext.length() - kIvSize);
240 #ifdef OPENSSL_API_INTERFACE_V11
241 EVP_CIPHER_CTX_free(ctx_ptr);
243 retval = EVP_CIPHER_CTX_cleanup(&ctx);
248 retval = EVP_DecryptFinal_ex(ctx_ptr, plaintext + plaintext_len, &tail_len);
249 #ifdef OPENSSL_API_INTERFACE_V11
250 EVP_CIPHER_CTX_free(ctx_ptr);
252 int retval_2 = EVP_CIPHER_CTX_cleanup(&ctx);
260 plaintext_len += tail_len;
261 if (plaintext_len == 0) {
265 string result(reinterpret_cast<char *>(plaintext), plaintext_len);
271 string CipherAes256Cbc::DoEncrypt(
const string &plaintext,
const Key &key) {
277 unsigned char *iv = md5.
digest;
281 unsigned char *ciphertext =
reinterpret_cast<unsigned char *
>(
282 smalloc(kIvSize + 2 * kBlockSize + plaintext.size()));
283 memcpy(ciphertext, iv, kIvSize);
286 #ifdef OPENSSL_API_INTERFACE_V11
287 EVP_CIPHER_CTX *ctx_ptr = EVP_CIPHER_CTX_new();
290 EVP_CIPHER_CTX_init(&ctx);
291 EVP_CIPHER_CTX *ctx_ptr = &
ctx;
293 retval = EVP_EncryptInit_ex(ctx_ptr, EVP_aes_256_cbc(), NULL, key.
data(), iv);
296 if (!plaintext.empty()) {
297 retval = EVP_EncryptUpdate(
298 ctx_ptr, ciphertext + kIvSize, &cipher_len,
299 reinterpret_cast<const unsigned char *>(plaintext.data()),
303 retval = EVP_EncryptFinal_ex(ctx_ptr, ciphertext + kIvSize + cipher_len,
306 #ifdef OPENSSL_API_INTERFACE_V11
307 EVP_CIPHER_CTX_free(ctx_ptr);
309 retval = EVP_CIPHER_CTX_cleanup(&ctx);
313 cipher_len += tail_len;
315 string result(reinterpret_cast<char *>(ciphertext), kIvSize + cipher_len);
335 return hmac.CastToMd5();
342 string CipherNone::DoDecrypt(
const string &ciphertext,
const Key &key) {
347 string CipherNone::DoEncrypt(
const string &plaintext,
const Key &key) {
struct cvmcache_context * ctx
static Publisher * Create(const SettingsPublisher &settings)
std::string ToString(const bool with_suffix=false) const
void Hmac(const string &key, const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
assert((mem||(size==0))&&"Out Of Memory")
unsigned char digest[digest_size_]
static Uuid * Create(const std::string &store_path)
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
string Base64(const string &data)
const unsigned char * data() const
const unsigned char * data() const