示例#1
0
void TestSymmetricCipher(TestData &v)
{
	std::string name = GetRequiredDatum(v, "Name");
	std::string test = GetRequiredDatum(v, "Test");

	std::string key = GetDecodedDatum(v, "Key");
	std::string ciphertext = GetDecodedDatum(v, "Ciphertext");
	std::string plaintext = GetDecodedDatum(v, "Plaintext");

	TestDataNameValuePairs pairs(v);

	if (test == "Encrypt")
	{
		std::auto_ptr<SymmetricCipher> encryptor(ObjectFactoryRegistry<SymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
		encryptor->SetKey((const byte *)key.data(), key.size(), pairs);
		std::string encrypted;
		StringSource ss(plaintext, true, new StreamTransformationFilter(*encryptor, new StringSink(encrypted), StreamTransformationFilter::NO_PADDING));
		if (encrypted != ciphertext)
			SignalTestFailure();
	}
	else if (test == "Decrypt")
	{
		std::auto_ptr<SymmetricCipher> decryptor(ObjectFactoryRegistry<SymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
		decryptor->SetKey((const byte *)key.data(), key.size(), pairs);
		std::string decrypted;
		StringSource ss(ciphertext, true, new StreamTransformationFilter(*decryptor, new StringSink(decrypted), StreamTransformationFilter::NO_PADDING));
		if (decrypted != plaintext)
			SignalTestFailure();
	}
	else
	{
		SignalTestError();
		assert(false);
	}
}
示例#2
0
void Cipher::decrypt(std::istream& source, std::ostream& sink, Encoding encoding)
{
	CryptoOutputStream decryptor(sink, createDecryptor());

	switch (encoding)
	{
	case ENC_NONE:
		StreamCopier::copyStream(source, decryptor);
		decryptor.close();
		break;

	case ENC_BASE64:
		{
			Poco::Base64Decoder decoder(source);
			StreamCopier::copyStream(decoder, decryptor);
			decryptor.close();
		}
		break;

	case ENC_BINHEX:
		{
			Poco::HexBinaryDecoder decoder(source);
			StreamCopier::copyStream(decoder, decryptor);
			decryptor.close();
		}
		break;

	default:
		throw Poco::InvalidArgumentException("Invalid argument", "encoding");
	}
}
示例#3
0
Test::Result
PK_Encryption_Decryption_Test::run_one_test(const std::string&, const VarMap& vars)
   {
   const std::vector<uint8_t> plaintext  = get_req_bin(vars, "Msg");
   const std::vector<uint8_t> ciphertext = get_req_bin(vars, "Ciphertext");

   const std::string padding = get_opt_str(vars, "Padding", default_padding(vars));

   std::unique_ptr<Botan::RandomNumberGenerator> kat_rng;
   if(vars.count("Nonce"))
      {
      kat_rng.reset(new Fixed_Output_RNG(get_req_bin(vars, "Nonce")));
      }

   Test::Result result(algo_name() + "/" + padding + " decryption");

   std::unique_ptr<Botan::Private_Key> privkey = load_private_key(vars);

   // instead slice the private key to work around elgamal test inputs
   //std::unique_ptr<Botan::Public_Key> pubkey(Botan::X509::load_key(Botan::X509::BER_encode(*privkey)));

   Botan::PK_Encryptor_EME encryptor(*privkey, padding);
   result.test_eq("encryption", encryptor.encrypt(plaintext, kat_rng ? *kat_rng : Test::rng()), ciphertext);

   Botan::PK_Decryptor_EME decryptor(*privkey, padding);
   result.test_eq("decryption", decryptor.decrypt(ciphertext), plaintext);

   check_invalid_ciphertexts(result, decryptor, plaintext, ciphertext);

   return result;
   }
std::string decrypt_string(const char *instr, const char *pass_phrase) {
    std::string out_str;
    CryptoPP::HexDecoder decryptor(new CryptoPP::DefaultDecryptorWithMAC(pass_phrase, new CryptoPP::StringSink(out_str)));
    decryptor.Put((byte *) instr, strlen(instr));
    decryptor.MessageEnd();
    return out_str;
}
QByteArray Encryptor::decryptAsymmetricly(ConnectedUser *user, QByteArray &data)
{
    const int DATA_SIZE = data.size();
    Botan::PK_Decryptor_EME decryptor(user->privateKey(), "EME1(SHA-256)");

    Botan::byte msgToDecrypt[DATA_SIZE];

    for (int i = 0; i < DATA_SIZE; i++)
    {
        Botan::byte character = (Botan::byte) data.at(i);
        msgToDecrypt[i] = character;
    }

    // Decrypt key with private key
    auto decryptedSerpentKey = decryptor.decrypt(msgToDecrypt, DATA_SIZE);

    // The key is transfered in hex
    QByteArray decryptedData;

    for (uint i = 0; i < decryptedSerpentKey.size(); ++i) {
        Botan::byte dataByte = decryptedSerpentKey[i];
        decryptedData.append(static_cast<char>(dataByte));
    }

    return decryptedData;
}
示例#6
0
文件: test.cpp 项目: acat/emule
string DecryptString(const char *instr, const char *passPhrase)
{
	string outstr;

	HexDecoder decryptor(new DefaultDecryptorWithMAC(passPhrase, new StringSink(outstr)));
	decryptor.Put((byte *)instr, strlen(instr));
	decryptor.MessageEnd();

	return outstr;
}
示例#7
0
bool Session::e_read(void* buffer, std::size_t size)
{
   std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);

   if (read(this->fd, buf.get(), size) > 0)
   {
      CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption decryptor(this->aes.key, sizeof(aes_key),
         this->aes.iv);

      decryptor.ProcessData((uint8_t*)buffer, buf.get(), size);
      return true;
   }
   else
   {
      return false;
   }
}
示例#8
0
static PyObject *tripledescbc_decrypt(tripledescbc *self, PyObject *args) {
	//	std::cout << "hello dec 0" << std::endl; std::cout.flush();
	PyObject *result = NULL;
	byte *plaintext = NULL;
	try {
		byte *iv;
		unsigned int ivlength;
		byte *text;
		unsigned int textlength;
		if(!PyArg_ParseTuple(args, "s#s#", &iv, &ivlength, &text, &textlength)) {
			throw Exception(Exception::INVALID_ARGUMENT, "wrong type of parameters passed in from Python");
		}
		if(ivlength != 8) {
			throw Exception(Exception::INVALID_ARGUMENT, "IV length must be 8");
		}
		CBC_CTS_Mode<DES_XEX3>::Decryption decryption(self->key, 24, iv);
		plaintext = new byte[textlength];
		if (plaintext == NULL) {
			throw MemoryException();
		}
		StreamTransformationFilter decryptor(decryption, new ArraySink(plaintext, textlength));
		decryptor.PutMessageEnd(text, textlength);
		result = Py_BuildValue("s#", plaintext, textlength);
		if(result == NULL) {
			throw MemoryException();
		}
		xdeletear(plaintext);
		return result;
	}
	catch(CryptoPP::Exception &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(plaintext);
		PyErr_SetString(TripleDESCBCError, e.what());
		return NULL;
	}
	catch(MemoryException &e) {
		if(result != NULL) {
			PyMem_DEL(result);
		}
		xdeletear(plaintext);
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to do decryption");
		return NULL;
	}
}
示例#9
0
void EncryptorDefault::decrypt(const umf_rawbuffer& input, umf_string& output)
{
    if(input.size() == 0)
    {
        output = string();
    }
    else
    {
        try
        {
            //or specify length of passphrase: decryptor(passphrase.c_str(), passphrase.length(), ...);
            DefaultDecryptorWithMAC decryptor(passphrase.c_str(), new StringSink(output));
            decryptor.Put((byte*)input.data(), input.size());
            decryptor.MessageEnd();
        }
        catch (CryptoPP::Exception const& e)
        {
            UMF_EXCEPTION(IncorrectParamException, "CryptoPP::Exception caught:" + string(e.what()));
        }
    }
}
示例#10
0
void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
{
	int modulusSize = 2048;
	alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize);

	assert(modulusSize >= 16);
	if (modulusSize < 16)
		throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small");

	m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17));

	assert(m_e >= 3); assert(!m_e.IsEven());
	if (m_e < 3 || m_e.IsEven())
		throw InvalidArgument("InvertibleRSAFunction: invalid public exponent");

	RSAPrimeSelector selector(m_e);
	AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
		(Name::PointerToPrimeSelector(), selector.GetSelectorPointer());
	m_p.GenerateRandom(rng, primeParam);
	m_q.GenerateRandom(rng, primeParam);

	m_d = m_e.InverseMod(LCM(m_p-1, m_q-1));
	assert(m_d.IsPositive());

	m_dp = m_d % (m_p-1);
	m_dq = m_d % (m_q-1);
	m_n = m_p * m_q;
	m_u = m_q.InverseMod(m_p);

	if (FIPS_140_2_ComplianceEnabled())
	{
		RSASS<PKCS1v15, SHA>::Signer signer(*this);
		RSASS<PKCS1v15, SHA>::Verifier verifier(signer);
		SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);

		RSAES<OAEP<SHA> >::Decryptor decryptor(*this);
		RSAES<OAEP<SHA> >::Encryptor encryptor(decryptor);
		EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor);
	}
}
示例#11
0
void TestAsymmetricCipher(TestData &v)
{
	std::string name = GetRequiredDatum(v, "Name");
	std::string test = GetRequiredDatum(v, "Test");

	member_ptr<PK_Encryptor> encryptor(ObjectFactoryRegistry<PK_Encryptor>::Registry().CreateObject(name.c_str()));
	member_ptr<PK_Decryptor> decryptor(ObjectFactoryRegistry<PK_Decryptor>::Registry().CreateObject(name.c_str()));

	std::string keyFormat = GetRequiredDatum(v, "KeyFormat");

	if (keyFormat == "DER")
	{
		decryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
		encryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
	}
	else if (keyFormat == "Component")
	{
		TestDataNameValuePairs pairs(v);
		decryptor->AccessMaterial().AssignFrom(pairs);
		encryptor->AccessMaterial().AssignFrom(pairs);
	}

	if (test == "DecryptMatch")
	{
		std::string decrypted, expected = GetDecodedDatum(v, "Plaintext");
		StringSource ss(GetDecodedDatum(v, "Ciphertext"), true, new PK_DecryptorFilter(GlobalRNG(), *decryptor, new StringSink(decrypted)));
		if (decrypted != expected)
			SignalTestFailure();
	}
	else if (test == "KeyPairValidAndConsistent")
	{
		TestKeyPairValidAndConsistent(encryptor->AccessMaterial(), decryptor->GetMaterial());
	}
	else
	{
		SignalTestError();
		assert(false);
	}
}
示例#12
0
void cryptos::_sha_decrypt(const bybuff& key, const bybuff& data, bybuff& out)const
{
    std::string  decryptedtext;
    uint8_t iv[ CryptoPP::AES::BLOCKSIZE ] = {0};
    //
    // Decrypt
    //
/**
    CryptoPP::AES::Decryption aesDecryption(key.buffer(), key.length());
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );

    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
    stfDecryptor.Put( data.buffer(), (size_t)data.length() );
    stfDecryptor.MessageEnd();
    out = decryptedtext;
*/
    try{
        CryptoPP::ECB_Mode< CryptoPP::AES >::Decryption aes_128_ecb(key.buffer(), key.length(), iv);
        //aes_128_ecb.SetKey( );
        CryptoPP::StreamTransformationFilter decryptor(aes_128_ecb, 0, CryptoPP::BlockPaddingSchemeDef::NO_PADDING);

        for(size_t j = 0; j < data.length(); j++)
        {
            decryptor.Put((byte)data[j]);
        }
        decryptor.MessageEnd();

        size_t ready = decryptor.MaxRetrievable();
        byte  outa[32] = {0};
        decryptor.Get((byte*) outa, ready);
        out.append(outa, ready);
    }
    catch( CryptoPP::Exception& e )
    {
        ERROR( e.what());
    }
}
示例#13
0
int appCrypto::symmetricKey(string& symKey, const string& encSymKey, const string& priKey)
{
    try
    {
        symKey.clear();
        
        // data decryption
        CryptoPP::StringSource priKeySrc(priKey, true, new CryptoPP::HexDecoder);
        CryptoPP::RSAES_PKCS1v15_Decryptor decryptor(priKeySrc);
        
        CryptoPP::AutoSeededRandomPool rng;
        CryptoPP::StringSource(encSymKey, true,
            new CryptoPP::HexDecoder(
                new CryptoPP::PK_DecryptorFilter(rng, decryptor,
                    new CryptoPP::StringSink(symKey))));
    }
    catch (CryptoPP::Exception& e)
    {
        cout << "decrypt symmetric key exception occur, what: " << e.what() << endl;
        return errDefault;
    }
    
    return errNone;
}
示例#14
0
int main(int argc, char *argv[]) 
{
	//@alan {n,e,d}
	int Keys[3][3]={{143, 7, 103}, {187, 27, 83}, {209, 17, 53}};
	int Key_counter = 0;
	
	//INITIALIZATION
   struct sockaddr_in localaddr,remoteaddr;

   SOCKET s, ns;

   char send_buffer[BUFFESIZE],receive_buffer[BUFFESIZE];
   memset(&send_buffer,0,BUFFESIZE);
   memset(&receive_buffer,0,BUFFESIZE);

   int n,bytes,addrlen;
   memset(&localaddr,0,sizeof(localaddr));//clean up the structure
   memset(&remoteaddr,0,sizeof(remoteaddr));//clean up the structure

	//WSSTARTUP
   if (WSAStartup(WSVERS, &wsadata) != 0) 
	{
      WSACleanup();
      printf("WSAStartup failed\n");
   }

	//SOCKET
   s = socket(PF_INET, SOCK_STREAM, 0);
   if (s < 0) 
	{
      printf("socket failed\n");
   }

   localaddr.sin_family = AF_INET;
   if (argc == 2) localaddr.sin_port = htons((u_short)atoi(argv[1]));
   else localaddr.sin_port = htons(1234);//default listening port
   localaddr.sin_addr.s_addr = INADDR_ANY;//server IP address should be local

	//BIND
   if (bind(s,(struct sockaddr *)(&localaddr),sizeof(localaddr)) != 0) 
	{
      printf("Bind failed!\n");
      exit(0);
   }
	
	//LISTEN
   listen(s,5);

   while (1) 
	{
      addrlen = sizeof(remoteaddr);

		//NEW SOCKET newsocket = accept
      ns = accept(s,(struct sockaddr *)(&remoteaddr),&addrlen);

      if (ns < 0) break;
      printf("accepted a connection from client IP %s port %d \n",inet_ntoa(remoteaddr.sin_addr),ntohs(localaddr.sin_port));
		
		/**
		  * @brief  send public key.
		  */
		if(Key_counter>2)
		{
			Key_counter=0;
		}		
		sprintf(send_buffer, "Public_Key %d %d\r\n",Keys[Key_counter][0],Keys[Key_counter][1]);
		
		bytes = send(ns, send_buffer, strlen(send_buffer), 0);
		printf("@alan: %s", send_buffer);
		
      while (1) 
		{
         n = 0;
         while (1) 
			{
				//RECEIVE
            bytes = recv(ns, &receive_buffer[n], 1, 0);

				//PROCESS REQUEST
            if ((bytes <=0 )) break;
            if (receive_buffer[n] == '\n') 
				{ /*end on a LF*/
               receive_buffer[n] = '\0';
               break;
            }
            if (receive_buffer[n] != '\r') n++; /*ignore CRs*/
         }
         if (bytes <= 0) break;
				
			printf("The client is sending: %s\n",receive_buffer);
			memset(&send_buffer, 0, BUFFESIZE);
			sprintf(send_buffer, "<<< SERVER SAYS:The client typed '%s' - There are %d bytes of information\r\n", receive_buffer, n);
			
			
			
			
			/**
			  * @brief  decrypt and save it in the receive_buffer
			  */
			decryptor(receive_buffer, Keys[Key_counter][0], Keys[Key_counter][2]);
			printf("@alan the decrpted message is:'%s'\n",receive_buffer);
			printf("...................................\n");
			
			
			
			
			//SEND
         bytes = send(ns, send_buffer, strlen(send_buffer), 0);
         if (bytes < 0) break;
      }
			//CLOSE SOCKET
      closesocket(ns);//close connecting socket
      printf("disconnected from %s\n",inet_ntoa(remoteaddr.sin_addr));
		
		
		/**
		  * @brief  next key
		  */
		Key_counter++;		
   }

   closesocket(s);//close listening socket
   return 0;
}
示例#15
0
void TestSymmetricCipher(TestData &v)
{
	std::string name = GetRequiredDatum(v, "Name");
	std::string test = GetRequiredDatum(v, "Test");

	std::string key = GetDecodedDatum(v, "Key");
	std::string plaintext = GetDecodedDatum(v, "Plaintext");

	TestDataNameValuePairs pairs(v);

	if (test == "Encrypt" || test == "EncryptXorDigest")
	{
		std::auto_ptr<SymmetricCipher> encryptor(ObjectFactoryRegistry<SymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
		std::auto_ptr<SymmetricCipher> decryptor(ObjectFactoryRegistry<SymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
		ConstByteArrayParameter iv;
		if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize())
			SignalTestFailure();
		encryptor->SetKey((const byte *)key.data(), key.size(), pairs);
		decryptor->SetKey((const byte *)key.data(), key.size(), pairs);
		int seek = pairs.GetIntValueWithDefault("Seek", 0);
		if (seek)
		{
			encryptor->Seek(seek);
			decryptor->Seek(seek);
		}
		std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
		StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(encrypted), StreamTransformationFilter::NO_PADDING));
		ss.Pump(plaintext.size()/2 + 1);
		ss.PumpAll();
		/*{
			std::string z;
			encryptor->Seek(seek);
			StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(z), StreamTransformationFilter::NO_PADDING));
			while (ss.Pump(64)) {}
			ss.PumpAll();
			for (int i=0; i<z.length(); i++)
				assert(encrypted[i] == z[i]);
		}*/
		if (test == "Encrypt")
			ciphertext = GetDecodedDatum(v, "Ciphertext");
		else
		{
			ciphertextXorDigest = GetDecodedDatum(v, "CiphertextXorDigest");
			xorDigest.append(encrypted, 0, 64);
			for (size_t i=64; i<encrypted.size(); i++)
				xorDigest[i%64] ^= encrypted[i];
		}
		if (test == "Encrypt" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest)
		{
			std::cout << "incorrectly encrypted: ";
			StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
			xx.Pump(256); xx.Flush(false);
			std::cout << "\n";
			SignalTestFailure();
		}
		std::string decrypted;
		StringSource dd(encrypted, false, new StreamTransformationFilter(*decryptor, new StringSink(decrypted), StreamTransformationFilter::NO_PADDING));
		dd.Pump(plaintext.size()/2 + 1);
		dd.PumpAll();
		if (decrypted != plaintext)
		{
			std::cout << "incorrectly decrypted: ";
			StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
			xx.Pump(256); xx.Flush(false);
			std::cout << "\n";
			SignalTestFailure();
		}
	}
	else if (test == "Decrypt")
	{
	}
	else
	{
		SignalTestError();
		assert(false);
	}
}
示例#16
0
/*! \brief Input: flag for multiple runs  Output: Message.
 *
 * This test creates a public and private key. The functions were tested for correctness in testSmall.c
 * Here we look at the integration of these functions to create the keys to have the properties
 * required of the GGH algortihm.
 */
int testGGH(int mruns){
	printf("* Executing %i GGH run(s)\n",mruns);

	gsl_matrix *uniMatrix = gsl_matrix_alloc(SIZE,SIZE);
	gsl_matrix *privKey = gsl_matrix_alloc(SIZE,SIZE);
	gsl_matrix *pubKey = gsl_matrix_alloc(SIZE,SIZE);
	gsl_matrix *message = gsl_matrix_alloc(SIZE,SIZE);
	gsl_matrix *Cmessage = gsl_matrix_alloc(SIZE,SIZE);
	gsl_matrix *Dmessage = gsl_matrix_alloc(SIZE,SIZE);
	
	int i, match, mismatch =0;
	if (mruns == 1){
		// Choose a good basis (Private key) [V]
		printf("Choose a good basis (Private key) [V]\n");
		privKey = create_private_key();
		
		// Create the unimodular matrix [U]
		printf("Create the unimodular matrix [U]\n");
		uniMatrix = genU();
		
		// Compute a bad basis (Public Key)
		printf("Compute a bad basis (Public Key)\n");
		pubKey = create_public_key(privKey,uniMatrix);
		
		// Generate the message
		printf("Generate the message\n");
		message = genM();
		
		// Encrypt
		printf("Compute cypher text.\n");
		Cmessage = encryptor(message,pubKey);
		
		// Decrypt
		printf("Decrypt\n");
		Dmessage = decryptor(Cmessage,privKey,uniMatrix);
		
		// Compare Messages
		printf("Compare Messages\n");
		
		if(compare(message,Dmessage)==0){
			printf("The messages match.\n");
		}
		else{
			printf("Message and decryped message do not match.\n");
		}
		
	}
	else{
		uniMatrix = genU();
		printf("Reusing the generated unimodular matrix [U] on 100 GGH runs.\n");
		for(i =0;i < (mruns+1); i++){
			// Choose a good basis (Private key) [V]
			privKey = create_private_key();
			
			// Compute a bad basis (Public Key)
			pubKey = create_public_key(privKey,uniMatrix);
			
			// Generate the message
			message = genM();
			
			// Encrypt
			Cmessage = encryptor(message,pubKey);
			
			// Decrypt
			Dmessage = decryptor(Cmessage,privKey,uniMatrix);
			
			// Compare Messages		
			if(compare(message,Dmessage)==0){
				match++;
			}
			else{
				mismatch++;
			}
		}
	}
	printf("  Number of matches: %i",match);
	return 1;
}
示例#17
0
/*
* Read a Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents,
                                         const Handshake_State& state,
                                         const Private_Key* server_rsa_kex_key,
                                         Credentials_Manager& creds,
                                         const Policy& policy,
                                         RandomNumberGenerator& rng)
   {
   const std::string kex_algo = state.ciphersuite().kex_algo();

   if(kex_algo == "RSA")
      {
      BOTAN_ASSERT(state.server_certs() && !state.server_certs()->cert_chain().empty(),
                   "RSA key exchange negotiated so server sent a certificate");

      if(!server_rsa_kex_key)
         throw Internal_Error("Expected RSA kex but no server kex key set");

      if(!dynamic_cast<const RSA_PrivateKey*>(server_rsa_kex_key))
         throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());

      PK_Decryptor_EME decryptor(*server_rsa_kex_key, "PKCS1v15");

      Protocol_Version client_version = state.client_hello()->version();

      /*
      * This is used as the pre-master if RSA decryption fails.
      * Otherwise we can be used as an oracle. See Bleichenbacher
      * "Chosen Ciphertext Attacks against Protocols Based on RSA
      * Encryption Standard PKCS #1", Crypto 98
      *
      * Create it here instead if in the catch clause as otherwise we
      * expose a timing channel WRT the generation of the fake value.
      * Some timing channel likely remains due to exception handling
      * and the like.
      */
      secure_vector<byte> fake_pre_master = rng.random_vec(48);
      fake_pre_master[0] = client_version.major_version();
      fake_pre_master[1] = client_version.minor_version();

      try
         {
         TLS_Data_Reader reader("ClientKeyExchange", contents);
         m_pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535));

         if(m_pre_master.size() != 48 ||
            client_version.major_version() != m_pre_master[0] ||
            client_version.minor_version() != m_pre_master[1])
            {
            throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
            }
         }
      catch(...)
         {
         m_pre_master = fake_pre_master;
         }
      }
   else
      {
      TLS_Data_Reader reader("ClientKeyExchange", contents);

      SymmetricKey psk;

      if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
         {
         const std::string psk_identity = reader.get_string(2, 0, 65535);

         psk = creds.psk("tls-server",
                         state.client_hello()->sni_hostname(),
                         psk_identity);

         if(psk.length() == 0)
            {
            if(policy.hide_unknown_users())
               psk = SymmetricKey(rng, 16);
            else
               throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
                                   "No PSK for identifier " + psk_identity);
            }
         }

      if(kex_algo == "PSK")
         {
         std::vector<byte> zeros(psk.length());
         append_tls_length_value(m_pre_master, zeros, 2);
         append_tls_length_value(m_pre_master, psk.bits_of(), 2);
         }
#if defined(BOTAN_HAS_SRP6)
      else if(kex_algo == "SRP_SHA")
         {
         SRP6_Server_Session& srp = state.server_kex()->server_srp_params();

         m_pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of();
         }
#endif
      else if(kex_algo == "DH" || kex_algo == "DHE_PSK" ||
              kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
         {
         const Private_Key& private_key = state.server_kex()->server_kex_key();

         const PK_Key_Agreement_Key* ka_key =
            dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);

         if(!ka_key)
            throw Internal_Error("Expected key agreement key type but got " +
                                 private_key.algo_name());

         try
            {
            PK_Key_Agreement ka(*ka_key, "Raw");

            std::vector<byte> client_pubkey;

            if(ka_key->algo_name() == "DH")
               client_pubkey = reader.get_range<byte>(2, 0, 65535);
            else
               client_pubkey = reader.get_range<byte>(1, 0, 255);

            secure_vector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of();

            if(ka_key->algo_name() == "DH")
               shared_secret = CT::strip_leading_zeros(shared_secret);

            if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
               {
               append_tls_length_value(m_pre_master, shared_secret, 2);
               append_tls_length_value(m_pre_master, psk.bits_of(), 2);
               }
            else
               m_pre_master = shared_secret;
            }
         catch(std::exception &)
            {
            /*
            * Something failed in the DH computation. To avoid possible
            * timing attacks, randomize the pre-master output and carry
            * on, allowing the protocol to fail later in the finished
            * checks.
            */
            m_pre_master = rng.random_vec(ka_key->public_value().size());
            }
         }
      else
         throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
      }
   }