RSA encrypt/decrypt and warning fixes.
GitOrigin-RevId: 6d556509d911678c1dd7d489132c07f942f3be0f
This commit is contained in:
parent
372196280c
commit
b6637ccfc5
@ -43,7 +43,7 @@ Result<ValueHash> calc_value_hash(DataView &data_view) {
|
||||
}
|
||||
|
||||
BufferSlice gen_random_prefix(int64 data_size) {
|
||||
BufferSlice buff(((32 + 15 + data_size) & -16) - data_size);
|
||||
BufferSlice buff(narrow_cast<size_t>(((32 + 15 + data_size) & -16) - data_size));
|
||||
Random::secure_bytes(buff.as_slice());
|
||||
buff.as_slice()[0] = narrow_cast<uint8>(buff.size());
|
||||
CHECK((buff.size() + data_size) % 16 == 0);
|
||||
@ -58,7 +58,7 @@ int64 FileDataView::size() {
|
||||
}
|
||||
|
||||
Result<BufferSlice> FileDataView::pread(int64 offset, int64 size) {
|
||||
auto slice = BufferSlice(size);
|
||||
auto slice = BufferSlice(narrow_cast<size_t>(size));
|
||||
TRY_RESULT(actual_size, fd_.pread(slice.as_slice(), offset));
|
||||
if (static_cast<int64>(actual_size) != size) {
|
||||
return Status::Error("Not enough data in file");
|
||||
@ -69,14 +69,14 @@ Result<BufferSlice> FileDataView::pread(int64 offset, int64 size) {
|
||||
BufferSliceDataView::BufferSliceDataView(BufferSlice buffer_slice) : buffer_slice_(std::move(buffer_slice)) {
|
||||
}
|
||||
int64 BufferSliceDataView::size() {
|
||||
return buffer_slice_.size();
|
||||
return narrow_cast<int64>(buffer_slice_.size());
|
||||
}
|
||||
Result<BufferSlice> BufferSliceDataView::pread(int64 offset, int64 size) {
|
||||
auto end_offset = size + offset;
|
||||
if (this->size() < end_offset) {
|
||||
return Status::Error("Not enough data in BufferSlice");
|
||||
}
|
||||
return BufferSlice(buffer_slice_.as_slice().substr(offset, size));
|
||||
return BufferSlice(buffer_slice_.as_slice().substr(narrow_cast<size_t>(offset), narrow_cast<size_t>(size)));
|
||||
}
|
||||
|
||||
ConcatDataView::ConcatDataView(DataView &left, DataView &right) : left_(left), right_(right) {
|
||||
|
@ -15,14 +15,14 @@
|
||||
|
||||
#if TD_HAVE_OPENSSL
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
|
||||
#if TD_HAVE_ZLIB
|
||||
@ -557,8 +557,17 @@ uint64 crc64(Slice data) {
|
||||
return crc64_partial(data, static_cast<uint64>(-1)) ^ static_cast<uint64>(-1);
|
||||
}
|
||||
|
||||
static int get_evp_pkey_type(EVP_PKEY *pkey) {
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
return EVP_PKEY_type(pkey->type);
|
||||
#else
|
||||
return EVP_PKEY_base_id(pkey);
|
||||
#endif
|
||||
}
|
||||
|
||||
Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) {
|
||||
BIO *mem_bio = BIO_new_mem_buf(public_key.data(), narrow_cast<int>(public_key.size()));
|
||||
BIO *mem_bio = BIO_new_mem_buf(const_cast<void *>(static_cast<const void *>(public_key.data())),
|
||||
narrow_cast<int>(public_key.size()));
|
||||
SCOPE_EXIT {
|
||||
BIO_vfree(mem_bio);
|
||||
};
|
||||
@ -567,30 +576,43 @@ Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) {
|
||||
if (!pkey) {
|
||||
return Status::Error("Cannot read public key");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_PKEY_free(pkey);
|
||||
};
|
||||
if (get_evp_pkey_type(pkey) != EVP_PKEY_RSA) {
|
||||
return Status::Error("Wrong key type, expected RSA");
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, nullptr);
|
||||
if (!ctx) {
|
||||
return Status::Error("Cannot create EVP_PKEY_CTX");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
};
|
||||
|
||||
if (EVP_PKEY_encrypt_init(ctx) <= 0) {
|
||||
return Status::Error("Cannot init EVP_PKEY_CTX");
|
||||
}
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
|
||||
return Status::Error("Cannot set RSA_PKCS1_OAEP padding in EVP_PKEY_CTX");
|
||||
}
|
||||
|
||||
size_t outlen;
|
||||
if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, data.ubegin(), data.size()) <= 0) {
|
||||
return Status::Error("Cannot calculate encrypted length");
|
||||
}
|
||||
BufferSlice res(outlen);
|
||||
if (EVP_PKEY_encrypt(ctx, res.as_slice().ubegin(), &outlen, data.ubegin(), data.size()) <= 0) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
// ERR_print_errors_fp(stderr);
|
||||
return Status::Error("Cannot encrypt");
|
||||
}
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data) {
|
||||
BIO *mem_bio = BIO_new_mem_buf(private_key.data(), narrow_cast<int>(private_key.size()));
|
||||
BIO *mem_bio = BIO_new_mem_buf(const_cast<void *>(static_cast<const void *>(private_key.data())),
|
||||
narrow_cast<int>(private_key.size()));
|
||||
SCOPE_EXIT {
|
||||
BIO_vfree(mem_bio);
|
||||
};
|
||||
@ -599,16 +621,28 @@ Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data) {
|
||||
if (!pkey) {
|
||||
return Status::Error("Cannot read private key");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_PKEY_free(pkey);
|
||||
};
|
||||
if (get_evp_pkey_type(pkey) != EVP_PKEY_RSA) {
|
||||
return Status::Error("Wrong key type, expected RSA");
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, nullptr);
|
||||
if (!ctx) {
|
||||
return Status::Error("Cannot create EVP_PKEY_CTX");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
};
|
||||
|
||||
if (EVP_PKEY_decrypt_init(ctx) <= 0) {
|
||||
return Status::Error("Cannot init EVP_PKEY_CTX");
|
||||
}
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
|
||||
return Status::Error("Cannot set RSA_PKCS1_OAEP padding in EVP_PKEY_CTX");
|
||||
}
|
||||
|
||||
size_t outlen;
|
||||
if (EVP_PKEY_decrypt(ctx, nullptr, &outlen, data.ubegin(), data.size()) <= 0) {
|
||||
return Status::Error("Cannot calculate decrypted length");
|
||||
|
@ -6,9 +6,9 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
@ -85,7 +85,7 @@ void hmac_sha256(Slice key, Slice message, MutableSlice dest);
|
||||
|
||||
// Interface may be improved
|
||||
Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data);
|
||||
Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice public_key, Slice data);
|
||||
Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data);
|
||||
|
||||
void init_openssl_threads();
|
||||
#endif
|
||||
|
@ -29,20 +29,22 @@ TEST(SecureStorage, simple) {
|
||||
BufferSlice value("Small tale about cucumbers");
|
||||
auto value_secret = Secret::create_new();
|
||||
|
||||
auto value_view = BufferSliceDataView(value.copy());
|
||||
BufferSlice prefix = gen_random_prefix(value_view.size());
|
||||
auto prefix_view = BufferSliceDataView(std::move(prefix));
|
||||
auto full_value_view = ConcatDataView(prefix_view, value_view);
|
||||
auto hash = calc_value_hash(full_value_view).move_as_ok();
|
||||
{
|
||||
auto value_view = BufferSliceDataView(value.copy());
|
||||
BufferSlice prefix = gen_random_prefix(value_view.size());
|
||||
auto prefix_view = BufferSliceDataView(std::move(prefix));
|
||||
auto full_value_view = ConcatDataView(prefix_view, value_view);
|
||||
auto hash = calc_value_hash(full_value_view).move_as_ok();
|
||||
|
||||
Encryptor encryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()), full_value_view);
|
||||
auto encrypted_value = encryptor.pread(0, encryptor.size()).move_as_ok();
|
||||
Encryptor encryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()), full_value_view);
|
||||
auto encrypted_value = encryptor.pread(0, encryptor.size()).move_as_ok();
|
||||
|
||||
Decryptor decryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()));
|
||||
auto res = decryptor.append(encrypted_value.copy()).move_as_ok();
|
||||
auto decrypted_hash = decryptor.finish().ok();
|
||||
ASSERT_TRUE(decrypted_hash.as_slice() == hash.as_slice());
|
||||
ASSERT_TRUE(res.as_slice() == value.as_slice());
|
||||
Decryptor decryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()));
|
||||
auto res = decryptor.append(encrypted_value.copy()).move_as_ok();
|
||||
auto decrypted_hash = decryptor.finish().ok();
|
||||
ASSERT_TRUE(decrypted_hash.as_slice() == hash.as_slice());
|
||||
ASSERT_TRUE(res.as_slice() == value.as_slice());
|
||||
}
|
||||
|
||||
{
|
||||
auto encrypted_value = encrypt_value(value_secret, value.as_slice()).move_as_ok();
|
||||
|
Reference in New Issue
Block a user