#ifndef _OBF_STRING_H_ #define _OBF_STRING_H_ #include #include #include #include #include #include #include #include #include #include // forward declarations namespace details { template< typename Sequence > class sequence_array; template< typename UnobfuscatedString > class base_obf_string; } /** * @struct obf_string * Handles up to 20 multichars, i.e. 80 characters. * @brief Obfuscates sensitive strings */ template < int E0, int E1 = -1, int E2 = -1 , int E3 = -1 , int E4 = -1 , int E5 = -1 , int E6 = -1 , int E7 = -1 , int E8 = -1 , int E9 = -1 , int E10 = -1 , int E11 = -1 , int E12 = -1 , int E13 = -1 , int E14 = -1 , int E15 = -1 , int E16 = -1 , int E17 = -1 , int E18 = -1 , int E19 = -1 > struct obf_string : public details::base_obf_string > {}; // implementation details clients don't need to know about namespace details { // base implementation of the obfuscated string. its template argumentis a Forward Sequence which contains // the original string. template< typename UnobfuscatedString > class base_obf_string { public: // unobfuscates the string and returns it. std::string unobfuscate() const { std::stringstream ss; // we operate on an ObfuscatedArray which is a runtime-iteratable version of ObfuscatedString // iterates int-by-int for(size_t i = 0; i < m_obfuscated.size(); i++) { // undoes the obfuscation: a simple XOR int elem = m_obfuscated[i] ^ 0x42424242; if(elem == -1) { // optional terminator; indicates the string has ended break; } // now iterates byte-by-byte int shift_amount = 24; while( shift_amount >= 0 ) { char c = elem >> shift_amount; if(c != 0) { // edge cases such as as obf_string<'a'> will result in 0x00000061. ss << c; } shift_amount -= 8; } } return ss.str(); } private: // here's the obfuscation magic: using mpl::transform_view, we apply a XOR (mpl::bitxor_) to each element of UnobfuscatedString. // The resulting type is called ObfuscatedString. This is all done in compile-time. typedef typename boost::mpl::transform_view< UnobfuscatedString, boost::mpl::bitxor_ > >::type ObfuscatedString; // the sequence_array class transforms an MPL container into a boost::array which can be manipulated in runtime. // ObfuscatedArray is a boost::array which contains the elements of ObfuscatedString. typedef details::sequence_array ObfuscatedArray; ObfuscatedArray m_obfuscated; }; // inherits from boost::array and stores all the elements contained in Sequence. template< typename Sequence > class sequence_array : public boost::array< typename boost::mpl::front< Sequence >::type::value_type, // the type of the first element of Sequence boost::mpl::size::type::value // the number of elements in Sequence > { typedef typename boost::array< typename boost::mpl::front< Sequence >::type::value_type, boost::mpl::size::type::value >::iterator iterator; // used to copy the contents from the sequence into the sequence_array; see the ctor struct copier_ { copier_(iterator it) : it_(it) {} template void operator()(U u) { *(it_++) = u; } iterator it_; }; public: sequence_array() { // for_each goes through each element of Sequence and calls operator() on the object passed // as its argument. In this cases, operator() from copier_ inserts the current element of Sequence // into the position pointed to by the iterator, which is subsequently incremented. boost::mpl::for_each(copier_(this->begin())); } }; } // namespace details #endif