mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
remove settings, add tryDecrypt function
This commit is contained in:
parent
a2c6d2267f
commit
e882b4f694
@ -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) \
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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>>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user