remove settings, add tryDecrypt function

This commit is contained in:
Duc Canh Le 2022-09-25 13:50:22 +08:00
parent a2c6d2267f
commit e882b4f694
6 changed files with 30 additions and 38 deletions

View File

@ -634,8 +634,6 @@ static constexpr UInt64 operator""_GiB(unsigned long long value)
\
M(Map, additional_table_filters, "", "Additional filter expression which would be applied after reading from specified table. Syntax: {'table1': 'expression', 'database.table2': 'expression'}", 0) \
M(String, additional_result_filter, "", "Additional filter expression which would be applied to query result", 0) \
\
M(Bool, aes_decryption_use_null_when_fail, false, "Decrypt a string with incorrect key will return NULL instead of throwing error", 0) \
/** Experimental functions */ \
M(Bool, allow_experimental_funnel_functions, false, "Enable experimental functions for funnel analysis.", 0) \
M(Bool, allow_experimental_nlp_functions, false, "Enable experimental functions for natural language processing.", 0) \

View File

@ -17,11 +17,6 @@ namespace ErrorCodes
}
}
bool AESHelpers::getParamsFromContext(DB::ContextPtr context)
{
return context->getSettingsRef().aes_decryption_use_null_when_fail;
}
namespace OpenSSLDetails
{
void onError(std::string error_message)

View File

@ -31,11 +31,6 @@ namespace ErrorCodes
}
}
namespace AESHelpers
{
bool NO_INLINE getParamsFromContext(DB::ContextPtr context);
}
namespace OpenSSLDetails
{
[[noreturn]] void onError(std::string error_message);
@ -416,14 +411,13 @@ template <typename Impl>
class FunctionDecrypt : public IFunction
{
public:
explicit FunctionDecrypt(bool use_null_when_decrypt_fail_) : use_null_when_decrypt_fail(use_null_when_decrypt_fail_) { }
static constexpr OpenSSLDetails::CompatibilityMode compatibility_mode = Impl::compatibility_mode;
static constexpr auto name = Impl::name;
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionDecrypt>(AESHelpers::getParamsFromContext(context)); }
static constexpr bool use_null_when_decrypt_fail = Impl::use_null_when_decrypt_fail;
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionDecrypt>(); }
private:
using CipherMode = OpenSSLDetails::CipherMode;
bool use_null_when_decrypt_fail = false;
String getName() const override { return name; }
bool isVariadic() const override { return true; }
@ -454,7 +448,7 @@ private:
optional_args
);
if (use_null_when_decrypt_fail)
if constexpr (use_null_when_decrypt_fail)
return std::make_shared<DataTypeNullable>(std::make_shared<DataTypeString>());
return std::make_shared<DataTypeString>();
@ -480,7 +474,7 @@ private:
ColumnPtr result_column;
if (arguments.size() <= 3)
{
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, nullptr, nullptr, use_null_when_decrypt_fail);
result_column = doDecrypt<use_null_when_decrypt_fail>(evp_cipher, input_rows_count, input_column, key_column, nullptr, nullptr);
}
else
{
@ -490,7 +484,7 @@ private:
if (arguments.size() <= 4)
{
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, nullptr, use_null_when_decrypt_fail);
result_column = doDecrypt<use_null_when_decrypt_fail>(evp_cipher, input_rows_count, input_column, key_column, iv_column, nullptr);
}
else
{
@ -498,50 +492,48 @@ private:
throw Exception("AAD can be only set for GCM-mode", ErrorCodes::BAD_ARGUMENTS);
const auto aad_column = arguments[4].column;
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column, use_null_when_decrypt_fail);
result_column = doDecrypt<use_null_when_decrypt_fail>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
}
}
return result_column;
}
template<bool use_null_when_decrypt_fail>
static ColumnPtr doDecrypt(
const EVP_CIPHER * evp_cipher,
size_t input_rows_count,
const ColumnPtr & input_column,
const ColumnPtr & key_column,
const ColumnPtr & iv_column,
const ColumnPtr & aad_column,
bool use_null_when_decrypt_fail = false)
const ColumnPtr & aad_column)
{
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::MySQL)
{
return doDecryptImpl<CipherMode::MySQLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column, use_null_when_decrypt_fail);
return doDecryptImpl<CipherMode::MySQLCompatibility, use_null_when_decrypt_fail>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
}
else
{
const auto cipher_mode = EVP_CIPHER_mode(evp_cipher);
if (cipher_mode == EVP_CIPH_GCM_MODE)
{
return doDecryptImpl<CipherMode::RFC5116_AEAD_AES_GCM>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column, use_null_when_decrypt_fail);
return doDecryptImpl<CipherMode::RFC5116_AEAD_AES_GCM, use_null_when_decrypt_fail>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
}
else
{
return doDecryptImpl<CipherMode::OpenSSLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column, use_null_when_decrypt_fail);
return doDecryptImpl<CipherMode::OpenSSLCompatibility, use_null_when_decrypt_fail>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
}
}
return nullptr;
}
template <CipherMode mode>
template <CipherMode mode, bool use_null_when_decrypt_fail>
static ColumnPtr doDecryptImpl(const EVP_CIPHER * evp_cipher,
size_t input_rows_count,
const ColumnPtr & input_column,
const ColumnPtr & key_column,
[[maybe_unused]] const ColumnPtr & iv_column,
[[maybe_unused]] const ColumnPtr & aad_column,
bool use_null_when_decrypt_fail = false)
[[maybe_unused]] const ColumnPtr & aad_column)
{
using namespace OpenSSLDetails;
@ -679,7 +671,7 @@ private:
reinterpret_cast<unsigned char*>(decrypted), &output_len,
reinterpret_cast<const unsigned char*>(input_value.data), static_cast<int>(input_value.size)) != 1)
{
if (!use_null_when_decrypt_fail)
if constexpr (!use_null_when_decrypt_fail)
onError("Failed to decrypt");
decrypt_fail = true;
}
@ -699,7 +691,7 @@ private:
if (!decrypt_fail && EVP_DecryptFinal_ex(evp_ctx,
reinterpret_cast<unsigned char*>(decrypted), &output_len) != 1)
{
if (!use_null_when_decrypt_fail)
if constexpr (!use_null_when_decrypt_fail)
onError("Failed to decrypt");
decrypt_fail = true;
}
@ -712,7 +704,7 @@ private:
++decrypted;
decrypted_result_column_offsets.push_back(decrypted - decrypted_result_column_data.data());
if (use_null_when_decrypt_fail)
if constexpr (use_null_when_decrypt_fail)
{
if (decrypt_fail)
null_map->insertValue(1);
@ -729,7 +721,7 @@ private:
}
decrypted_result_column->validate();
if (use_null_when_decrypt_fail)
if constexpr (use_null_when_decrypt_fail)
return ColumnNullable::create(std::move(decrypted_result_column), std::move(null_map));
else
return decrypted_result_column;

View File

@ -12,6 +12,7 @@ struct DecryptMySQLModeImpl
{
static constexpr auto name = "aes_decrypt_mysql";
static constexpr auto compatibility_mode = OpenSSLDetails::CompatibilityMode::MySQL;
static constexpr bool use_null_when_decrypt_fail = false;
};
}

View File

@ -12,6 +12,14 @@ struct DecryptImpl
{
static constexpr auto name = "decrypt";
static constexpr auto compatibility_mode = OpenSSLDetails::CompatibilityMode::OpenSSL;
static constexpr bool use_null_when_decrypt_fail = false;
};
struct TryDecryptImpl
{
static constexpr auto name = "tryDecrypt";
static constexpr auto compatibility_mode = OpenSSLDetails::CompatibilityMode::OpenSSL;
static constexpr bool use_null_when_decrypt_fail = true;
};
}
@ -22,6 +30,7 @@ namespace DB
REGISTER_FUNCTION(Decrypt)
{
factory.registerFunction<FunctionDecrypt<DecryptImpl>>();
factory.registerFunction<FunctionDecrypt<TryDecryptImpl>>();
}
}

View File

@ -129,7 +129,7 @@ SELECT
hex(decrypt('aes-256-gcm', concat(ciphertext, tag), key, iv, aad)) as plaintext_actual,
plaintext_actual = hex(plaintext);
-- decrypt with null when fail
-- tryDecrypt
CREATE TABLE decrypt_null (
dt DateTime,
user_id UInt32,
@ -140,10 +140,7 @@ CREATE TABLE decrypt_null (
INSERT INTO decrypt_null VALUES ('2022-08-02 00:00:00', 1, encrypt('aes-256-gcm', 'value1', 'keykeykeykeykeykeykeykeykeykey01', 'iv1'), 'iv1'), ('2022-09-02 00:00:00', 2, encrypt('aes-256-gcm', 'value2', 'keykeykeykeykeykeykeykeykeykey02', 'iv2'), 'iv2'), ('2022-09-02 00:00:01', 3, encrypt('aes-256-gcm', 'value3', 'keykeykeykeykeykeykeykeykeykey03', 'iv3'), 'iv3');
SELECT dt, user_id FROM decrypt_null WHERE (user_id > 0) AND (decrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv) = 'value2'); --{serverError 454}
SELECT dt, user_id FROM decrypt_null WHERE (user_id > 0) AND (decrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv) = 'value2') SETTINGS aes_decryption_use_null_when_fail = 1;
SELECT dt, user_id, (decrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv)) as value FROM decrypt_null ORDER BY user_id SETTINGS aes_decryption_use_null_when_fail = 1;
SELECT dt, user_id FROM decrypt_null WHERE (user_id > 0) AND (tryDecrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv) = 'value2');
SELECT dt, user_id, (tryDecrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv)) as value FROM decrypt_null ORDER BY user_id;
DROP TABLE encryption_test;