int main(int argc, char* argv[]) { /********************************* Non-Filter Method Encoder *********************************/ #if 0 byte decoded[] = { 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 }; string encoded; HexEncoder encoder; encoder.Put(decoded, sizeof(decoded)); encoder.MessageEnd(); word64 size = encoder.MaxRetrievable(); if(size) { encoded.resize(size); encoder.Get((byte*)encoded.data(), encoded.size()); } cout << encoded << endl; #endif /********************************* Filter Method Encoder *********************************/ #if 1 char decoded[] = {106,102,114,97,103, 101, 9, 9,9, 9, 9, 9,9,9,9,114,101,32,83,113,117,101,97, 109,105,115,104,32,79,115,84,104,101,32,77,97,103,105,99,32,87,111,114,100,115,32}; string encoded = ""; StringSource ss(decoded, true/* pumpAll */, new HexEncoder( new StringSink(encoded), true ) // HexEncoder ); // StringSource cout << encoded << endl; //encoded = encoded + decoded; //cout << encoded << endl; #endif /********************************* Non-Filter Method Decoder *********************************/ #if 0 string encoded = "FFEEDDCCBBAA99887766554433221100"; string decoded; HexDecoder decoder; decoder.Put( (byte*)encoded.data(), encoded.size() ); decoder.MessageEnd(); word64 size = decoder.MaxRetrievable(); if(size && size <= SIZE_MAX) { decoded.resize(size); decoder.Get((byte*)decoded.data(), decoded.size()); } cout << decoded << endl; #endif /********************************* Filter Method Decoder *********************************/ #if 1 //string encoded = "FFEEDDCCBBAA99887766554433221100"; string decoded2; string enc = "3130362C3130322C3131342C39372C3130332C203130312C20392C20392C392C20392C20392C20392C392C392C392C3131342C3130312C33322C38332C3131332C3131372C3130312C39372C203130392C3130352C3131352C3130342C33322C37392C3131352C38342C3130342C3130312C33322C37372C39372C3130332C3130352C39392C33322C38372C3131312C3131342C3130302C3131352C3332"; StringSource sss(enc, true/* pumpAll */, new HexDecoder( new StringSink(decoded2) ) // HexEncoder ); // StringSource cout << decoded2 << endl; #endif return 0; }
void PEM_CipherForAlgorithm(const EncapsulatedHeader& header, const char* password, size_t length, auto_ptr<StreamTransformation>& stream) { unsigned int ksize, vsize; string algorithm(header.m_algorithm); std::transform(algorithm.begin(), algorithm.end(), algorithm.begin(), (int(*)(int))std::toupper); if(algorithm == "AES-256-CBC") { ksize = 32; vsize = 16; stream = auto_ptr<StreamTransformation>(new CBC_Mode<AES>::Decryption); } else if(algorithm == "AES-192-CBC") { ksize = 24; vsize = 16; stream = auto_ptr<StreamTransformation>(new CBC_Mode<AES>::Decryption); } else if(algorithm == "AES-128-CBC") { ksize = 16; vsize = 16; stream = auto_ptr<StreamTransformation>(new CBC_Mode<AES>::Decryption); } else if(algorithm == "CAMELLIA-256-CBC") { ksize = 32; vsize = 16; stream = auto_ptr<StreamTransformation>(new CBC_Mode<Camellia>::Decryption); } else if(algorithm == "CAMELLIA-192-CBC") { ksize = 24; vsize = 16; stream = auto_ptr<StreamTransformation>(new CBC_Mode<Camellia>::Decryption); } else if(algorithm == "CAMELLIA-128-CBC") { ksize = 16; vsize = 16; stream = auto_ptr<StreamTransformation>(new CBC_Mode<Camellia>::Decryption); } else if(algorithm == "DES-EDE3-CBC") { ksize = 24; vsize = 8; stream = auto_ptr<StreamTransformation>(new CBC_Mode<DES_EDE3>::Decryption); } else if(algorithm == "IDEA-CBC") { ksize = 16; vsize = 8; stream = auto_ptr<StreamTransformation>(new CBC_Mode<IDEA>::Decryption); } else if(algorithm == "DES-CBC") { ksize = 8; vsize = 8; stream = auto_ptr<StreamTransformation>(new CBC_Mode<DES>::Decryption); } else { throw NotImplemented("PEM_CipherForAlgorithm: '" + header.m_algorithm + "' is not implemented"); } const unsigned char* _pword = reinterpret_cast<const unsigned char*>(password); const size_t _plen = length; // Decode the IV. It used as the Salt in EVP_BytesToKey, // and its used as the IV in the cipher. HexDecoder hex; hex.Put((const byte*)header.m_iv.data(), header.m_iv.size()); hex.MessageEnd(); // If the IV size is wrong, SetKeyWithIV will throw an exception. size_t size = hex.MaxRetrievable(); size = std::min(size, static_cast<size_t>(vsize)); SecByteBlock _key(ksize); SecByteBlock _iv(size); SecByteBlock _salt(size); hex.Get(_iv.data(), _iv.size()); // The IV pulls double duty. First, the first PKCS5_SALT_LEN bytes are used // as the Salt in EVP_BytesToKey. Second, its used as the IV in the cipher. _salt = _iv; assert(_salt.size() >= OPENSSL_PKCS5_SALT_LEN); // MD5 is engrained OpenSSL goodness. MD5, IV and Password are IN; KEY is OUT. // {NULL,0} parameters are the OUT IV. However, the original IV in the PEM // header is used; and not the derived IV. Weak::MD5 md5; int ret = OPENSSL_EVP_BytesToKey(md5, _iv.data(), _pword, _plen, 1, _key.data(), _key.size(), NULL, 0); if(ret != static_cast<int>(ksize)) throw Exception(Exception::OTHER_ERROR, "PEM_CipherForAlgorithm: EVP_BytesToKey failed"); SymmetricCipher* cipher = dynamic_cast<SymmetricCipher*>(stream.get()); assert(cipher != NULL); cipher->SetKeyWithIV(_key.data(), _key.size(), _iv.data(), _iv.size()); }