2015-08-29 11 views
13

का उपयोग कर एन्क्रिप्शन मैं एक संकलन समय स्ट्रिंग एन्क्रिप्शन है, ऐसा है कि मैं अपने कोड में लिख सकता हूँ:संकलन समय स्ट्रिंग constexpr

const auto encryptedInvalidLicense = ENCRYPT("Invalid license"); 
std::cout << encryptedInvalidLicense.decrypt() << std::endl; // outputs "Invalid license" 

और स्ट्रिंग "अवैध लाइसेंस" अभ्यस्त बाइनरी में दिखाई देते हैं। प्री-बिल्ड का जवाब हो सकता है, लेकिन मैं इस समस्या के लिए एक शुद्ध सी ++ constexpr समाधान ढूंढ रहा हूं, और यह VS2015 द्वारा समर्थित होगा।

कोई सुझाव?


  1. मैं पहले से ही Compile-time string encryption है, जो समस्या का समाधान constexpr प्रदान नहीं करता है देखा है।

  2. मैंने http://www.unknowncheats.me/forum/c-and-c/113715-compile-time-string-encryption.html में भी देखा है। हालांकि यह एक कॉन्सएक्सप्रस समाधान है, वीएस2015 अभी भी बाइनरी में स्ट्रिंग सादा पाठ जोड़ता है।

+0

संभावित डुप्लिकेट [संकलन समय पर एक स्ट्रिंग अक्षर को एन्क्रिप्टिंग/obfuscating] (https://stackoverflow.com/questions/6934217/encrypting-obfuscating-a-string-literal-at-compile-time) – karliwson

उत्तर

13

यहाँ कैसे मैं यह कर देगा: Conveniently Declaring Compile-Time Strings in C++

कोड::

class str_const { 
    // constexpr string 
private: 
    const char * const p_; 
    const std::size_t sz_; 

public: 
    template <std::size_t N> 
    constexpr str_const(const char(&a)[N]) 
      : p_(a) 
      , sz_(N - 1) 
    {} 

    constexpr char operator[](std::size_t n) const { return n < sz_ ? p_[n] : throw std::out_of_range(""); } 
    constexpr std::size_t size() const { return sz_; } 

    constexpr const char * get() const { return p_; } 
}; 

यह आपको करने की सुविधा देता

1.) यहाँ वर्णित constexpr स्ट्रिंग हेरफेर के लिए str_const टेम्पलेट का उपयोग करें str_const message = "Invalid license" जैसी चीजें और constexpr कार्यों में message का उपयोग करें।

2.) मैक्रो __TIME__ और __LINE__ का उपयोग कर बीज उत्पन्न करने के लिए, एक साधारण संकलन समय कूट-यादृच्छिक जनरेटर करें। इसे यहां विस्तार से वर्णित किया गया है: Generate random numbers in C++ at compile time

वे कुछ टेम्पलेट-आधारित कोड देते हैं।

3.) एक constexpr ctor जो str_const उदाहरण की तरह ही आकार के खिलाफ या तो const char [] और टेम्पलेट्स ही लेता है, या जो सिर्फ एक str_const लेता है, और दो str_const जो वह अपने सदस्य चर रहे हैं उत्पन्न करता है के साथ, एक struct करें।

  • एक लंबाई n कूट-यादृच्छिक अहस्ताक्षरित वर्ण, कूट-यादृच्छिक जनरेटर, जहां n इनपुट की लंबाई है उपयोग करते हुए उत्पन्न युक्त str_const। ("शोर स्ट्रिंग")
  • एक लंबाई n शोर पात्रों के साथ इनपुट पात्रों में से (अहस्ताक्षरित वर्ण के रूप में) प्रवेश के लिहाज से योग युक्त str_const। ("सिफर पाठ")

तो यह एक सदस्य समारोह decrypt जो constexpr होने की जरूरत नहीं है, और एक std::string, जो केवल सिफर पाठ की इसी चरित्र से शोर स्ट्रिंग के हर किरदार को घटा लौट सकते हैं और परिणामी स्ट्रिंग देता है।

अपने संकलक अभी भी मूल स्ट्रिंग बाइनरी में शाब्दिक भंडारण है, तो इसका मतलब है कि या तो यह इनपुट स्ट्रिंग शाब्दिक (निर्माता तर्क), जो मुझे नहीं लगता कि वह अपने एक अस्थायी, या उसके बाद से करना चाहिए है भंडारण है मूल रूप से decrypt फ़ंक्शन को रेखांकित करते हुए, और आप इसे फ़ंक्शन पॉइंटर्स के साथ obfuscating करके या इसे volatile या इसी तरह चिह्नित करके इसे रोकने में सक्षम होना चाहिए।

संपादित करें: मुझे यकीन नहीं है कि मानक के लिए अस्थायी constexpr वस्तुओं बाइनरी में प्रकट नहीं होना चाहिए। वास्तव में मैं अब इसके बारे में उत्सुक हूँ। मेरी उम्मीद यह है कि कम से कम एक रिलीज बिल्ड में, एक अच्छा कंपाइलर उन्हें तब हटा देना चाहिए जब उनकी आवश्यकता नहीं होती है।

संपादित करें: तो, आप पहले से ही मेरा जवाब स्वीकार कर चुके हैं। लेकिन वैसे भी पूर्णता के लिए, यहां कुछ स्रोत कोड है जो उपरोक्त विचारों को लागू करते हैं, केवल सी ++ 11 मानक का उपयोग करते हुए। यह जीसीसी -4.9 और क्लैंग-3.6 पर काम करता है, भले ही ऑप्टिमाइज़ेशन अक्षम हो जाएं, जैसा कि मैं बता सकता हूं।

#include <array> 
#include <iostream> 
#include <string> 

typedef uint32_t u32; 
typedef uint64_t u64; 
typedef unsigned char uchar; 

template<u32 S, u32 A = 16807UL, u32 C = 0UL, u32 M = (1UL<<31)-1> 
struct LinearGenerator { 
    static const u32 state = ((u64)S * A + C) % M; 
    static const u32 value = state; 
    typedef LinearGenerator<state> next; 
    struct Split { // Leapfrog 
     typedef LinearGenerator< state, A*A, 0, M> Gen1; 
     typedef LinearGenerator<next::state, A*A, 0, M> Gen2; 
    }; 
}; 

// Metafunction to get a particular index from generator 
template<u32 S, std::size_t index> 
struct Generate { 
    static const uchar value = Generate<LinearGenerator<S>::state, index - 1>::value; 
}; 

template<u32 S> 
struct Generate<S, 0> { 
    static const uchar value = static_cast<uchar> (LinearGenerator<S>::value); 
}; 

// List of indices 
template<std::size_t...> 
struct StList {}; 

// Concatenate 
template<typename TL, typename TR> 
struct Concat; 

template<std::size_t... SL, std::size_t... SR> 
struct Concat<StList<SL...>, StList<SR...>> { 
    typedef StList<SL..., SR...> type; 
}; 

template<typename TL, typename TR> 
using Concat_t = typename Concat<TL, TR>::type; 

// Count from zero to n-1 
template<size_t s> 
struct Count { 
    typedef Concat_t<typename Count<s-1>::type, StList<s-1>> type; 
}; 

template<> 
struct Count<0> { 
    typedef StList<> type; 
}; 

template<size_t s> 
using Count_t = typename Count<s>::type; 

// Get a scrambled character of a string 
template<u32 seed, std::size_t index, std::size_t N> 
constexpr uchar get_scrambled_char(const char(&a)[N]) { 
    return static_cast<uchar>(a[index]) + Generate<seed, index>::value; 
} 

// Get a ciphertext from a plaintext string 
template<u32 seed, typename T> 
struct cipher_helper; 

template<u32 seed, std::size_t... SL> 
struct cipher_helper<seed, StList<SL...>> { 
    static constexpr std::array<uchar, sizeof...(SL)> get_array(const char (&a)[sizeof...(SL)]) { 
     return {{ get_scrambled_char<seed, SL>(a)... }}; 
    } 
}; 

template<u32 seed, std::size_t N> 
constexpr std::array<uchar, N> get_cipher_text (const char (&a)[N]) { 
    return cipher_helper<seed, Count_t<N>>::get_array(a); 
} 

// Get a noise sequence from a seed and string length 
template<u32 seed, typename T> 
struct noise_helper; 

template<u32 seed, std::size_t... SL> 
struct noise_helper<seed, StList<SL...>> { 
    static constexpr std::array<uchar, sizeof...(SL)> get_array() { 
     return {{ Generate<seed, SL>::value ... }}; 
    } 
}; 

template<u32 seed, std::size_t N> 
constexpr std::array<uchar, N> get_key() { 
    return noise_helper<seed, Count_t<N>>::get_array(); 
} 


/* 
// Get an unscrambled character of a string 
template<u32 seed, std::size_t index, std::size_t N> 
char get_unscrambled_char(const std::array<uchar, N> & a) { 
    return static_cast<char> (a[index] - Generate<seed, index>::value); 
} 
*/ 

// Metafunction to get the size of an array 
template<typename T> 
struct array_info; 

template <typename T, size_t N> 
struct array_info<T[N]> 
{ 
    typedef T type; 
    enum { size = N }; 
}; 

template <typename T, size_t N> 
struct array_info<const T(&)[N]> : array_info<T[N]> {}; 

// Scramble a string 
template<u32 seed, std::size_t N> 
class obfuscated_string { 
private: 
    std::array<uchar, N> cipher_text_; 
    std::array<uchar, N> key_; 
public: 
    explicit constexpr obfuscated_string(const char(&a)[N]) 
     : cipher_text_(get_cipher_text<seed, N>(a)) 
     , key_(get_key<seed,N>()) 
    {} 

    operator std::string() const { 
     char plain_text[N]; 
     for (volatile std::size_t i = 0; i < N; ++i) { 
      volatile char temp = static_cast<char>(cipher_text_[i] - key_[i]); 
      plain_text[i] = temp; 
     } 
     return std::string{plain_text, plain_text + N}; 
    } 
}; 

template<u32 seed, std::size_t N> 
std::ostream & operator<< (std::ostream & s, const obfuscated_string<seed, N> & str) { 
    s << static_cast<std::string>(str); 
    return s; 
} 

#define RNG_SEED ((__TIME__[7] - '0') * 1 + (__TIME__[6] - '0') * 10 + \ 
       (__TIME__[4] - '0') * 60 + (__TIME__[3] - '0') * 600 + \ 
       (__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000) + \ 
       (__LINE__ * 100000) 


#define LIT(STR) \ 
    obfuscated_string<RNG_SEED, array_info<decltype(STR)>::size>{STR} 

auto S2 = LIT(("Hewwo, I'm hunting wabbits")); 

int main() { 
    constexpr auto S1 = LIT(("What's up doc")); 
    std::cout << S1 << std::endl; 
    std::cout << S2 << std::endl; 
} 
+1

लगता है पूरे स्तर अनुकूलन और "अधिकतम गति (/ ओ 2)" या "न्यूनतम आकार (/ ओ 1)" के साथ काम करें। –

+1

विजुअल स्टूडियो 2015 अपडेट पर काम करता है 1 :) –

+1

'# शामिल ', शायद बूस्ट को भी हटा दें – Mikhail

-1

मैं इस तरह कोड होगा:

#if GENERATE_CODE 
.... code to generate the C++ code describing the encrypted literal 
.... generating exactly the code in the #else part 
#else 
static char encryptedLicense [32] = "..."; or whatever 
#endif 

चालाक बनने की कोशिश कर नहीं। #if कोड को एक अलग फ़ाइल में कॉपी करें, संकलित करें और चलाएं, परिणाम को पेस्ट करें।

संबंधित मुद्दे