Обфускация std::array с помощью constexpr

Я ищу небольшую функцию, которая может преобразовывать std::array, добавляя возрастающие значения. Функция должна быть функцией времени компиляции.

Мне удалось написать небольшую функцию constexpr, которая делает это для массива длины 3, но мне не удалось обобщить ее на std::arrays произвольной длины. Мне также не удалось обобщить его, чтобы он содержал что-то отличное от chars.

Кто-нибудь знает, как это сделать?

#include <array>
#include <iostream>
#include <valarray>

constexpr std::array<char,3> obfuscate(const std::array<char,3>& x)  {
     return std::array<char, 3>{x.at(0)+1, x.at(1) + 2, x.at(2) + 3 };
}

/* Won't compile

template<typename T,typename S, template<typename, typename> L=std::array<T, U>>
constexpr L<T,U> obfuscate(const L<T, U>& x) {
    return {x.at(0) + 1, x.at(0) + 2, x.at(0) + 3 };
}
*/

std::ostream& operator<<(std::ostream& str, const std::array<char, 3>& x) {
    for (auto i = 0; i < 3; i++) {
        str << x.at(i);
    }
    return str;
}

int main(int argc, char** args) {
    std::array<char, 3> x{ 'a','b','c' };
    std::cout << x << std::endl;
    std::cout << obfuscate(x) << std::endl;
//  std::cout << obfuscate<3>(x) << std::endl;
}

person Aleph0    schedule 16.03.2018    source источник
comment
Вы действительно хотите запутать массив или заставить свою программу работать? У меня есть куча кода для первого, хотя он обычно убивает компилятор MSVC для больших пакетов.   -  person Mikhail    schedule 16.03.2018
comment
@Mikhail: Я действительно хочу запутать свою строку, чтобы никто не мог прочитать строку в скомпилированном файле. Мои струны обычно очень короткие. Мне просто интересно, как это можно сделать.   -  person Aleph0    schedule 16.03.2018
comment
@Holt: я должен придерживаться С++ 11. Но каким было бы ваше решение? Это выражение времени компиляции?   -  person Aleph0    schedule 16.03.2018
comment
Какова цель? Обфускация — это не шифрование, злоумышленнику не составит труда расшифровать вашу строку, так зачем вообще беспокоиться?   -  person Jesper Juhl    schedule 16.03.2018
comment
Меня беспокоит любопытство, что можно сделать во время компиляции. Понятно, что сломать обфускатор можно, приложив достаточно усилий.   -  person Aleph0    schedule 16.03.2018


Ответы (2)


Вы можете использовать std::index_sequence:

template<class T, std::size_t N, std::size_t... Is>
constexpr std::array<T, N> helper (const std::array<T, N> &x, std::index_sequence<Is...>) {
     return std::array<T, N>{static_cast<T>(x.at(Is)+Is+1)...};
}

template<class T, std::size_t N>
constexpr std::array<T, N> obfuscate(const std::array<T, N> &x) {
     return helper(x, std::make_index_sequence<N>{});
}
person llllllllll    schedule 16.03.2018
comment
Отличная работа. Кажется, это правильный подход. К сожалению, это не запутывает строку? Есть идеи, почему? Я адаптировал свой оператор‹‹ для печати запутанной строки, но он остался прежним. - person Aleph0; 16.03.2018
comment
@ Aleph0 Вы ​​используете x.at(0) в своем собственном коде для каждого элемента. Я просто скопировал это. Это опечатка? - person llllllllll; 16.03.2018
comment
Извините, это был типаж. Я хотел добавить увеличивающиеся числа в свой массив. Только что исправил свою ошибку. - person Aleph0; 16.03.2018
comment
Работает как шарм. Мне действительно нужно время, чтобы переварить ваше решение. Кажется, что я могу многому у него научиться. - person Aleph0; 16.03.2018
comment
Мне интересно, можно ли использовать его таким образом, чтобы запутать (String). Но тогда мне нужен метод для преобразования const char* в std::array<char,N>? - person Aleph0; 16.03.2018
comment
Строковый литерал @Aleph0 представляет собой lvalue с типом const char[N], не const char *, поэтому он похож. - person llllllllll; 16.03.2018
comment
Только что нашел это: stackoverflow.com/a/40180971/5762796 Похоже, похоже. - person Aleph0; 16.03.2018
comment
Вам не хватает +1 для фактического воспроизведения кода ОП: static_cast<T>(x.at(Is)+Is+1)... - person Holt; 16.03.2018

Есть несколько методов, которые используют пакеты кортежей, они хороши, за исключением того, что у MSVC есть проблема с производительностью при компиляции больших строк.

Я обнаружил, что этот компромисс хорошо работает в MSVC.

template<typename I>
struct encrypted_string;

template<size_t... I>
struct encrypted_string<std::index_sequence<I...>>
{
    std::array<char, sizeof...(I)+1> buf;

    constexpr static char encrypt(char c) { return c ^ 0x41; }
    constexpr static char decrypt(char c) { return encrypt(c); }
    constexpr explicit __forceinline encrypted_string(const char* str)
        : buf{ encrypt(str[I])... } { }
    inline const char* decrypt()
    {
        for (size_t i = 0; i < sizeof...(I); ++i)
        {
            buf[i] = decrypt(buf[i]);
        }
        buf[sizeof...(I)] = 0;
        return buf.data();
    }
};
#define enc(str) encrypted_string<std::make_index_sequence<sizeof(str)>>(str)

И где-то позже

auto stringo = enc(R"(  
    kernel void prg_PassThru_src(const global unsigned short * restrict A, int srcstepA, int srcoffsetA,
    global float * restrict Beta, int srcstepBeta, int srcoffsetBeta,
    int rows, int cols) {
        int x = get_global_id(0);
        int y0 = get_global_id(1);
        if (x < cols) {
            int srcA_index = mad24(y0, srcstepA / 2, x + srcoffsetA / 2);
            int srcBeta_index = mad24(y0, srcstepBeta / 4, x + srcoffsetBeta / 4);
            Beta[srcBeta_index] = A[srcA_index];
        }
    }
//somewhere later
cv::ocl::ProgramSource programSource(stringo.decrypt());

Вы можете увидеть выступление этого парня о более сложных методах: To-software-Obfuscation.pdf" rel="nofollow noreferrer">https://www.blackhat.com/docs/eu-14/materials/eu-14-Anddrivet-C-plus-plus11-Metaprogramming-Applied-To -software-Obfuscation.pdf

person Mikhail    schedule 16.03.2018