首页 > 解决方案 > 在编译时创建哈希值和/或加密字符串?

问题描述

有没有办法在编译时为字符串或加密字符串创建哈希值?我想将生成加密文本或哈希值的原始字符串作为字符串文字直接放在我的代码中,但我不希望它们以未转换的形式编译到可执行文件中。

像这样的东西?

constexpr uint32 hash(const char * string){
    ... // turns a string into a value to represent it
}
constexpr std::string encrypt(const char * string){
    ... // turns a string into a cyphertext (unsure what return type would work best here)
}

void f(){

    std::string input << std::cin();

    switch(hashedKey){
        case hash("help"): // legal?
            if(0 == encryptRT(input).compare(encrypt("secret string")){
                // the secret string should never appear in the executable
            }
            break;
    }
}

直接放入 constexpr 函数的字符串永远不会放入字符串表中,这一点非常重要。这可能吗?

标签: c++visual-studio-2015compilationconstexpr

解决方案


编译时xor混淆示例:

#include <iostream>
#include <iomanip>
#include <cstddef>
#include <cstdint>
#include <array>

template<::std::size_t x_data_bytes_count, ::std::size_t x_key_bytes_count> constexpr auto
obfuscate
(
    ::std::array<::std::uint8_t, x_data_bytes_count> const & input
,   ::std::array<::std::uint8_t, x_key_bytes_count> const &  key
) noexcept
{
    static_assert(::std::size_t{0} < x_data_bytes_count);
    // Assuming null-terminated string is used as a key.
    static_assert(::std::size_t{1} < x_key_bytes_count);
    ::std::array<::std::uint8_t, x_data_bytes_count> output{};
    ::std::size_t data_byte_index{};
    ::std::size_t key_byte_index{};
    do
    {
        output[data_byte_index] = input[data_byte_index] xor key[key_byte_index];
        data_byte_index = data_byte_index + ::std::size_t{1};
        key_byte_index = key_byte_index + ::std::size_t{1};
        key_byte_index = key_byte_index % (key.size() - ::std::size_t{1});
    }
    while(input.size() != data_byte_index);
    return output;
}

// Following two overloads may accept string literals
// so calling obfuscation function would be more convenient.
template<::std::size_t x_data_bytes_count, ::std::size_t x_key_bytes_count> constexpr auto
obfuscate
(
    char const ( & input )[x_data_bytes_count]
,   char const ( & key )[x_key_bytes_count]
) noexcept
{
    ::std::size_t byte_index{};
    ::std::array<::std::uint8_t, x_data_bytes_count> input_arr{};
    for(byte_index = 0; x_data_bytes_count != byte_index; ++byte_index)
    {
        input_arr[byte_index] = static_cast<::std::uint8_t>(input[byte_index]);
    }
    ::std::array<::std::uint8_t, x_key_bytes_count> key_arr{};
    for(byte_index = 0; x_key_bytes_count != byte_index; ++byte_index)
    {
        key_arr[byte_index] = static_cast<::std::uint8_t>(key[byte_index]);
    }
    return obfuscate(input_arr, key_arr);
}

template<::std::size_t x_data_bytes_count, ::std::size_t x_key_bytes_count> constexpr auto
obfuscate
(
    ::std::array<::std::uint8_t, x_data_bytes_count> const & input_arr
,   char const ( &                                           key )[x_key_bytes_count]
) noexcept
{
    ::std::size_t byte_index{};
    ::std::array<::std::uint8_t, x_key_bytes_count> key_arr{};
    for(byte_index = 0; x_key_bytes_count != byte_index; ++byte_index)
    {
        key_arr[byte_index] = static_cast<::std::uint8_t>(key[byte_index]);
    }
    return obfuscate(input_arr, key_arr);
}

int main()
{
    constexpr auto const & key{"Stack overflow"};
    constexpr auto const obfuscated_str{obfuscate("Hello World!", key)};
    for(auto const & ch: obfuscated_str)
    {
        ::std::cout << ::std::hex << ::std::setw(2) << ::std::setfill('0')
            << static_cast<::std::uint32_t>(ch) << " ";
    }
    ::std::cout << ::std::endl;
    auto const deobfuscated_str{obfuscate(obfuscated_str, key)};
    for(auto const & ch: deobfuscated_str)
    {
        ::std::cout << ::std::hex << ::std::setw(2) << ::std::setfill('0')
            << static_cast<::std::uint32_t>(ch) << " ";
    }
    ::std::cout << ::std::endl;
    ::std::cout << reinterpret_cast<char const *>(deobfuscated_str.data()) << ::std::endl;
    return 0;
}

在线编译器


推荐阅读