Advertisement

Is RSA Privatekey and Publickeys what I need...

Started by July 22, 2015 01:26 PM
14 comments, last by ankhd 9 years, 3 months ago

What if the user wants to log in from another compute

That is a very good point.. oop's Just locked everyone out. Or it's a very exclusive server.

Its like one of the tutorials I was following using the Hard Drive ID for client validation.

create account

Keepin it simple now. Encrypt(Public Key + Password) To Server ->Unlock with private Key-> Hash(password + Salt) ->Data Base;

login

Client->Encrypt(Public Key + Password)->SendToServer Server->Unlock->Hash->CompareDigest() = Done;

And I'll not forget to compare in constant time.

Time Attacks, Reminds me of the 3 key combination locks.

create account
Keepin it simple now. Encrypt(Public Key + Password) To Server ->Unlock with private Key-> Hash(password + Salt) ->Data Base;

login
Client->Encrypt(Public Key + Password)->SendToServer Server->Unlock->Hash->CompareDigest() = Done;


Yup. (Except the CompareDigest() function likely does the hash for you)
enum Bool { True, False, FileNotFound };
Advertisement

ahh The penny dropped. No wonder why it was hard to find things on the RSA key size and things.

Using RSA wrong concept dont help. It only clicked Last knight when looking for a check sum function after a hour some thing just went click, it was what the hell am I even looking for check sum function when in fact my password hash function using AES SHA512 just needed a new name from GeneratePasswordHash to GenerateHash the same thing derr. All about the concept I build around it.

Tested it can load large data sets LargeDataHash = GenerateHash(dataofanysize, SALT);

then RSA encrypt(LargeDataHash, PublicKey); done. Mess with any part of the file any bit and the hash on the server will reject it.

validhash = GenerateHash(downloadeddata +SALT);

decrypt PayloadCheckSumHash a fail here and someone played with the encrypted hash of the payload.

compare PayloadCheckSumHash with validhash fail here and someone played with the payload down stream

.

(Except the CompareDigest() function likely does the hash for you)

The CompareDigest is a helper function only. bool CompareDigest(std::string &digest1, std::string &digest2).

You need to put the clear text password into the encryption on the client side, and extract the clear text password on the server side, and calculate the bcrypt() or scrypt() of the password on the server.

Separately, an important concept in cryptographic communication is encrypt-then-MAC -- not MAC-then-encrypt.
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.5488&rep=rep1&type=pdf
enum Bool { True, False, FileNotFound };

Hey Thanks all.

I think I have it.

Here is a convoluted prototype of the steps I think I need to take written in code is probably the best way for me to describe. I hope this is correct.

.



int main(int argc, char* argv[])
{

	std::cout << "For Secure Encryption one should Encrypt the data first \nand then Authenticate The Data With a HMAC\n\n" << std::endl;
//STEP 1
//----------------------------------------------------------------------------------------
//simulates the server creating the salt and IV for the client
//and the creation of the private and public keys done on server side 
//----------------------------------------------------------------------------------------
	
//the server has a private and a public key for clients for encryption created on server startup
//the only data this key pair will encrypt is the hash of the data we send not the data
KEYPAIRHEX keypair; 
unsigned int keysize =3072;//amount of text this key can encrypt 342. out string key size for SHA512 is 128 on big endian and 64U small
	
if(RsaGenerateKeyPair<CryptoPP::AES>(keypair, keysize) == false)
{
std::cout << "Failed: To Create Key Pair" << std::endl; 
return 1;
}

//we need to first create a SALT and IV each client gets there own
//we use this SALT and IV to encrypt the data to be sent over the wire or saved to file
cCryptography ClientsCryptograph;//server would send this to the client on connection


//create the SALT and IV for anysize data encryption
ClientsCryptograph.GenerateSaltandIV();


//the server would send the client the public key
//the client recieves the public key then send to sever has key
//server sends encrypted SALT and IV to client
//client would use public key to decrypt salt and IV and store it for session token time



//STEP 2
//----------------------------------------------------------------------------------------//simulates a client sending data to the server first encrypt then apply the HMAC of the data
//ready to send to the server
//----------------------------------------------------------------------------------------
	
//here the client has some data ready to send to server
//we compress data first compression will not be included in this example
//then encrypt and authenticate the encrypted data
std::string DataToSend = "\
We show an example of an en-cryption function that provides (Shannon's) perfect secrecy but when\
combined with any MAC function under the authenticate-then-encrypt\
method yields a totally insecure protocol (for example, ¯finding passwords\
or credit card numbers transmitted under the protection of such protocol\
becomes an easy task for an active attacker). The same applies to the\
encrypt-and-authenticate method used in SSH.\
On the positive side we show that the authenticate-then-encrypt method\
is secure if the encryption method in use is either CBC mode (with an\
underlying secure block cipher) or a stream cipher (that xor the data\
with a random or pseudorandom pad). Thus, while we show the generic\
security of SSL to be broken, the current practical implementations of\
the protocol that use the above modes of encryption are safe.\
DOES THIS SAY BOTH WAYS WORK ANYWAY?????????????????????????";

	
//for encryption we need a digest created from the clients password and the server assigned SALT
	
std::string ClientPassword = "123456789";
int iterations = 16384;
if(ClientsCryptograph.GenerateHash(ClientPassword, iterations) == false)
{
	std::cout << "Failed to Has Password" << std::endl;

	std::system("Pause");
	return 1;
}

	
//the digest is now valid in class ClientsCryptograph
//ok we want to encrypt the test data with DIGEST and IV sent from the server
std::string EncryptedData;
bool Hexencoding = false;
if(ClientsCryptograph.EncryptData(DataToSend, EncryptedData, Hexencoding) == false)
{
	std::cout << "Failed to Encrypt Data" << std::endl;

	std::system("Pause");
	return 1;
}


//the data now is encrypted we now need to create a hash of the current encrypted data
//using our server assigned Salt AND IV but our digest will be created with the encrypted data and not a password

cCryptography SignedData;

//assign clients SALT and IV to this
SignedData.SALT		= ClientsCryptograph.SALT;
SignedData.IV		= ClientsCryptograph.IV;


//ok we are ready to do a fancy check sum of the data
//use SignedData to create a hash of the encrypted data
iterations = 16384;//we can set less if we want I think ???????
if(SignedData.GenerateHash(EncryptedData, iterations) == false)
{
	std::cout << "Failed to Encrypt Data" << std::endl;

	std::system("Pause");
	return 1;
}


//ok we now have a valid  DIGEST ready to be encrypted with RSA Key pair encryption
//using the public key because we are simulating the client here
	
std::string CipheredSignedDataHash;
std::string SignedDataStr;//we need to convert the signed data digest to a string

Hexencoding = false;
SignedData.GetDigest(SignedDataStr, Hexencoding);
//keypair.PublicKey[0] = '0x2';
if(RsaEncryptMessage<CryptoPP::AES>(keypair.PublicKey, SignedDataStr,  CipheredSignedDataHash) == false)
{
	std::cout << "Public Key  Encryption invalid." << std::endl;
}

//now EncryptedData is ready to be moved of to what ever output
//also needed is the CipheredSignedDataHash that validates the data
	





//STEP3
//----------------------------------------------------------------------------------------//simulates the server recieving data from a client
//----------------------------------------------------------------------------------------

	
//ok the server has recieved data from a client
//the EncryptedData and CipheredSignedDataHash is the data in this example
//EncryptedData is encrypted with the clients password + SALT and IV
//CipheredSignedDataHash is encrypted with clients public key

//CipheredSignedDataHash[5] = '0x2';
//first thing to do is decipher the signed data in CipheredSignedDataHash
//this will allow us to validate the incomming data with a few steps
	
std::string DecipheredDigest;
if(RsaDecryptMessage<CryptoPP::AES>(keypair.PrivateKey, CipheredSignedDataHash, DecipheredDigest) == false)
{
	std::cout << "Private Key Decryption invalid." << std::endl;
	std::system("Pause");
	return 1;
}


	
//DecipheredSignedData holds the hash of the sent data
//next we need to generate a hash of the encrypted sent data to see if its been tainted
	
cCryptography ServerClientDataHashEncoder;

//the server will know the SALT and IV of the client
ServerClientDataHashEncoder.SALT	= ClientsCryptograph.SALT;
ServerClientDataHashEncoder.IV		= ClientsCryptograph.IV;

	
//generate a server side hash with the sent data
iterations = 16384;//need to be the same as what the client used we could send this value or not 
if(ServerClientDataHashEncoder.GenerateHash(EncryptedData, iterations) == false)	
{
	std::cout << "Server Failed to Generate Hash of EncryptedData :" << EncryptedData << std::endl;

        std::system("Pause");
	return 1;
}


//convert ServerClientDataHashEncoder.Digest to a string
std::string Digest;
ServerClientDataHashEncoder.GetDigest(Digest, Hexencoding);


//check the sent datas digest and the servers created digest they need to match
if(cCryptography::IsEqualDigest(DecipheredDigest ,Digest)== false)
{
	std::cout << "Data Digest Does Not Match" << std::endl;

	std::system("Pause");
	return 1;
}

//ok no one messed with the data we can decrypt the data now	
std::string DecipheredMessage;

//the server will need the clients encrypted password hash from file
//for this example we have the clients in ClientsCryptograph set at the start of the program
	
//EncryptedData[0] = 'd';
if(ClientsCryptograph.DecryptData(EncryptedData, DecipheredMessage) == false)
{
	std::cout << "The EncryptedData is Corrupt " << EncryptedData << std::endl;

	std::system("Pause");
	return 1;
}


//the data is ready to use
std::cout << "Encrypted Data Size: " << EncryptedData.size() << " Data is: " << EncryptedData << std::endl;

std::cout << "\n\n\n-------------------------------------------------------------------------"  << std::endl;
	std::cout << "-------------------------------------------------------------------------"  << std::endl;
	std::cout << "-------------------------------------------------------------------------\n\n\n"  << std::endl;

	
std::cout << "Decrypted Data Size: " << DecipheredMessage.size() << " Data is: " << DecipheredMessage << std::endl;











//STEP 4
//----------------------------------------------------------------------------------------//simulates the server sending data to a client
//----------------------------------------------------------------------------------------

//here we use the private key to sign the datas hash to send to the client
//and use the clients hash to encrypt the data 
//use the message we had from the start of the program DataToSend

//first encrypt the data using the clients key Password + SALT and IV 
//we have it in ClientsCryptograph for this example
Hexencoding = false;
EncryptedData = "";;//reuse this
if(ClientsCryptograph.EncryptData(DataToSend, EncryptedData, Hexencoding) == false)
{
	std::cout << "Failed Encrypt Data  " << std::endl;

	std::system("Pause");
	return 1;
}


//create a a hash from the clients Password + SALT the server knows this data

//assign clients SALT and IV to this
SignedData.SALT		= ClientsCryptograph.SALT;
SignedData.IV		= ClientsCryptograph.IV;


//ok we are ready to do a fancy check sum of the data
//use SignedData to create a hash of the encrypted data
iterations = 16384;//we can set less if we want I think ???????
if(SignedData.GenerateHash(EncryptedData, iterations) == false)
{
	std::cout << "Failed to Encrypt Data" << std::endl;

	std::system("Pause");
	return 1;
}


//ok we now have a valid  DIGEST ready to be encrypted with RSA Key pair encryption
//using the private key because we are simulating the server here
CipheredSignedDataHash = "";
SignedDataStr = "";//we need to convert the signed data digest to a string

Hexencoding = false;
SignedData.GetDigest(SignedDataStr, Hexencoding);


//this bit differs because you can't encypt from a private key
//but the private key can sign the data and no one can change it or the public key will fail
// generate a signature for the message
if(RsaSignMessage<CryptoPP::PSSR, CryptoPP::SHA1, CryptoPP::AES>(keypair.PrivateKey, SignedDataStr, CipheredSignedDataHash) == false)
{
	std::cout << "Failed: To RsaSignMessage" << std::endl; 
	return 1;
}



//EncryptedData and CipheredSignedDataHash would be sent to client now




	
//STEP 5
//----------------------------------------------------------------------------------------//simulates the client getting data from the server
//----------------------------------------------------------------------------------------

//ok we need to decrypt CipheredSignedDataHash with our public key
//then decrypt with the clients SALT ClientsCryptograph

//verify the CipheredSignedDataHash with the hash we create now of the sent data
//assign clients SALT and IV to this
SignedData.SALT		= ClientsCryptograph.SALT;
SignedData.IV		= ClientsCryptograph.IV;

//EncryptedData[0] = '0';
//ok we are ready to do a fancy check sum of the data
//use SignedData to create a hash of the encrypted data

iterations = 16384;//needs to be the same value for all checks as it was created with
if(SignedData.GenerateHash(EncryptedData, iterations) == false)
{
	std::cout << "Failed to Encrypt Data" << std::endl;

	std::system("Pause");
	return 1;
}


//ok we now have a valid  DIGEST ready to be encrypted with RSA Key pair encryption
//using the public key because we are simulating the client here
SignedDataStr.clear();//we need to convert the signed data digest to a string

Hexencoding = false;
SignedData.GetDigest(SignedDataStr, Hexencoding);

//CipheredSignedDataHash[0] = '2';
//SignedDataStr[2] = 'o';
//keypair.PublicKey[5] = '0x2';

// verify signature against public key
if(RsaVerifyMessage<CryptoPP::PSSR, CryptoPP::SHA1>(keypair.PublicKey, SignedDataStr, CipheredSignedDataHash)) 
{
	std::cout << "Signatue valid." << std::endl;

	DecipheredMessage = "";
	//the signature is valid we can decrypt the data now
	if(ClientsCryptograph.DecryptData(EncryptedData, DecipheredMessage) == false)
	{
		std::cout << "Failed to Decrypt Data" << std::endl;

		std::system("Pause");
		return 1;
	}

std::cout << "\n\n\n-------------------------------------------------------------------------"  << std::endl;
		std::cout << "-------------------------------------------------------------------------"  << std::endl;
		std::cout << "-------------------------------------------------------------------------\n\n\n"  << std::endl;

		std::cout << "Client Decrypting\n"  << std::endl;


//the data is ready to use
std::cout << "Encrypted Data Size: " << EncryptedData.size() << " Data is: " << EncryptedData << std::endl;

		std::cout << "\n\n\n-------------------------------------------------------------------------"  << std::endl;
		std::cout << "-------------------------------------------------------------------------"  << std::endl;
		std::cout << "-------------------------------------------------------------------------\n\n\n"  << std::endl;

std::cout << "Decrypted Data Size: " << DecipheredMessage.size() << " Data is: " << DecipheredMessage << std::endl;



} 
else 
{
	std::cout << "Signatue invalid." << std::endl;
}

	

std::system("Pause");

return 0;
}

Hi again.

Implementing the above code did not go so well in the real app, what happened was it ended up still being the chicken and the egg story(which came first)Hashed or plain send from client its the same thing.

The real answer is and the only way is On first connect send a public key to client the client then uses this to encrypt only the password not the whole network message, with the public key, This will make a safe password for transport.

The thing to note here is if you allow a password of 256 bytes the public key to encrypt 256 bytes of text needs to be at 2400 key bits that generate a public key of 840 bytes and a Private key of 3486 bytes.

The public key can encrypt 256 byte max password size to a 300 byte buffer of encrypted password. And only now can the password be sent to the server safe.

Once the server gets the password it uses the private key decrypts the password, Generates a SALT and IV, Hashes the password saves then sends the SALT and IV to client.

now the connection is secure, the client can hash password with salt then encrypt any amount of data with the hashed password and the IV. Now I have SSL more or less.

I have it all working. and I Tim the Toolman It. Added compression, encryption, packet data check sum using IV and password hash, plus signing of the check sum with public key

this make the whole message tamper proof. But alas all this turned on slows the network by about 60% per message, So now I have 2 public keys, One for secure really secure Password and any thing under 256 bytes. And the other public key is a smaller one 128 bytes with less iterations on hashing they only needs to encrypt the packet digest this lowerd the effect to 50%. The lesser key has a iterations of 1000 this could still be over kill for packet data safety.

The system allow flags for each send that say's if you want to compress, encrypt, data digest and sign, This allows all server communication to take advantage of the full system, and in game maybe just sign the data and or not compression.

Maybe some one could help speed this up

.


//-----------------------------------------------------------------------------
// File: EnCodePacketData.h
//27/7/15
//-----------------------------------------------------------------------------
#ifndef ENCODEPACKETDATA_H
#define ENCODEPACKETDATA_H



#define MSGPACKET_SIZE	68 //the room for the MsgPacket protocol from the network packet size


#define ENCODEPACKETDATA_COMPRESSIONLEVEL	9//compression for encoder and decoder class


//defines for each function
#define ENCODEPACKETDATA_OK							0//all good
#define ENCODEPACKETDATA_TO_LARGE					1//the input is to large to fit try a compression
#define ENCODEPACKETDATA_EMPTY						2//no valis data to work with
#define ENCODEPACKETDATA_PACKETSERIALIZED_FAILED	3
#define ENCODEPACKETDATA_UNCOMPRESS_FAILED			4
#define ENCODEPACKETDATA_ENCRYPTED_FAILED			5
#define ENCODEPACKETDATA_SIGNED_FAILED				6
#define ENCODEPACKETDATA_EMPTY_RSASIGN				7
#define ENCODEPACKETDATA_PUBLICKEY_SIGNED_FAILED	8
#define ENCODEPACKETDATA_PRIVATEKEY_SIGNED_FAILED   9
#define DECODEPACKETDATA_DATASIGNATURE_FAILED		10
#define DECODEPACKETDATA_TAINTED_DATA				11
#define DECODEPACKETDATA_TAINTED_DECRYPTION			12






//we can't compress small buffers any thing under this size does not get compressed
#define MINIMUM_COMPRESSED_BUFFER_SIZE			100 





//------------------------------------------------------------------------------------------------------
//this will build the MsgPacket now used for the input serialized proto buffer
//and flags The order is Compress Data ->Encrypt Data -> Digest Data -> Sign Data -> Serialize MsgPacket
//and client data is needed returns a serialized string of MsgPacket type ready to be put
//in the packet
//returns false on errors and the error string will contain a message
//the server will use the private key to sign the data
//its encrypted per player client connection is needed to send
//--------------------------------------------------------------------------------------------------------
class cEnCodePacketData
{
	//std::string PrivateKeyHexStr;//only valid on the server side we do some different tascks
	//std::string PublicKeyHexStr;//in hex format same with private key
	std::string ProccessedData;//we add the data we want tp work with to this
	std::string DataSignature;//we use the clients SALT + IV + ProccessedData to create a check sum of the data encrypted then digest is best
	//if rsa is set we use the public or private keys to encrypt the DataSignature
	//std::string RsaDataSignature;//the DataSignature is encrypted with Private or public key

	bool Compressed;
	bool EnCrypted;
	bool RSASigned;

	bool ErrorPacketToLarge;

	int MaxPacketSize;

	int32_t UncompressedSize;//we need to keep the size of the uncompressed data
public:

	cEnCodePacketData(const std::string &inputdata, int maxpacketsize)
	{
		ProccessedData		= inputdata;
		Compressed			= false;
		EnCrypted			= false;
		RSASigned		= false;
		ErrorPacketToLarge = false;

		//get the size of the uncompressed data
		//we compress befor encryption
		UncompressedSize	= ProccessedData.size();

		MaxPacketSize = maxpacketsize - MSGPACKET_SIZE;//40 bytes less for our MsgPacket
		if(ProccessedData.size() >= MaxPacketSize)
			ErrorPacketToLarge = true;

	}

	~cEnCodePacketData()
	{
	}
	


	//------------------------------------------------------------------------
	//this will allow us to compress or encrypt or digest or sign or all of them
	//and return a serialize MsgPacket protocal ready for the network packet
	//------------------------------------------------------------------------------
	int EncodePacket(bool usingPrivateKey,//we need to know if we are server private = true client public false
		bool usecompression,//true is we want to compress the data
		bool encrypt,//true if we want to encrypt the data
		bool datasignature,//true if we want to create a digest DataSignature check sum
		bool rsasign,//true to use rsa public or private keys we sign the DataSignature
		bool hexcoded,//strings in hex or plain text
		int keyiterations,//when signing
		const std::string &KeyHexStr,//if usingPrivateKey is true this needs to be on the server and the private key or it the public key
		const std::string &PasswordDigest,//the clients digest for encryption
		const std::string &Salt,//clients salt
		const std::string &Iv,//clients IV
		std::string &serialized)//the out data with the transforms applied
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		if(ErrorPacketToLarge)
			return ENCODEPACKETDATA_TO_LARGE;

		if(usecompression)
		{
			error = Compress();
			if(error != ENCODEPACKETDATA_OK)
				return error;

		}//end compressing


		//encrypt the data
		if(encrypt)
		{
			cCryptography Digest;
			//we need to rebuild the clients digest
			Digest.StringToSalt(Salt);
			Digest.StringToIV(Iv);
			Digest.StringToDigest(PasswordDigest);

			error = AESEnCrypt(Digest, hexcoded);
			if(error != ENCODEPACKETDATA_OK)
				return error;

		}//end encryption


		//create the check sum of the data
		if(datasignature)
		{
			cCryptography Digest;
			Digest.StringToSalt(Salt);
			Digest.StringToIV(Iv);

			error = AESDigestData(Digest, hexcoded, keyiterations);
			if(error != ENCODEPACKETDATA_OK)
				return error;
		}//end datasignature


		//if we want to sign the with public or private key
		//server is private clients public
		if(rsasign)
		{
			if(usingPrivateKey)
			{
				//server uses the private key to sign
				error =  RSAPrivateSign(KeyHexStr);
				if(error != ENCODEPACKETDATA_OK)
					return error;
			}
			else
			{
				//client uses the public key to encrypt
				error = RSAPublicSign(KeyHexStr);
				if(error != ENCODEPACKETDATA_OK)
					return error;
			}

		}//end rsasign


		//we have to pack data into a MsgPacket proto buffer
		error = GenerateSerializedMsgPacket(serialized);

		return error;
	}//end EncodePacket
	////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////////


private:

	//--------------------------------------------------------------
	//this will apply the compression to the string
	//compress can change the size of the message so we check the size
	//after compression and return false if wher still to large
	//we only compress if the data is larger then MINIMUM_COMPRESSED_BUFFER_SIZE
	//--------------------------------------------------------------
	int Compress()
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;


		
		std::string compressed;
		
		//we cant compress small buffers under this value
		int size = ProccessedData.size();
		if(size <= MINIMUM_COMPRESSED_BUFFER_SIZE)
		{
			Compressed = false;
			return ENCODEPACKETDATA_OK;
		}

		//we need a compression buffer larger then the source so zlib can do stuff
		uLong destlen = ProccessedData.size() * 1.7;//after compression it will hold the size of the buffer we need to set
		compressed.resize(destlen);
	
		const Bytef *source = (Bytef *)ProccessedData.data();
		uLong sourceLen = ProccessedData.size();
		int v = compress2((Bytef*)compressed.data(), &destlen,// *dest,    *destLen,
                                 source , sourceLen,
                                  ENCODEPACKETDATA_COMPRESSIONLEVEL);
		
		
		if(v != Z_OK)
		{
			//std::stringstream ss;
			//if(v == Z_MEM_ERROR)
			//	ss << "Failed Compress::out of memory"<< " Error type=[Z_MEM_ERROR] " << v;
			//else
			//if(v == Z_BUF_ERROR)
			//	ss << "Compress::Failed Buffer To Small::" << " Error type=[Z_BUF_ERROR] " << v;
			//else
			//	ss << "Compress::Failed Unknown Error::"<< " Error type=[????] " << v;
			//MessageBox(NULL, ss.str().c_str(), "ServerMapDataLoadMap(LoadHeader)",MB_OK);

			Compressed = false;
		}//end error
		else
		{
		
			//resize the buffer to the new data compressed size
			compressed.resize(destlen);

			//set the new commpressed data
			ProccessedData = compressed;

			Compressed = true;
		}

		if(ProccessedData.size() >= MaxPacketSize)
		{
				ErrorPacketToLarge = true;
				error = ENCODEPACKETDATA_TO_LARGE;
		}
		else
		{
			ErrorPacketToLarge = false;//we fit
		}

		return error;
	}//end Compress
	//////////////////////////////////////////////////////////////////




	//-------------------------------------------------------------------------
	//there is 2 forms of encryption this one is AES using the clients password 
	//+ SALT + IV
	//cCryptography is the encryption key 
	//---------------------------------------------------------------------------
	int AESEnCrypt(cCryptography &Digest, bool Hexencoding)
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		//the digest is now valid in class ClientsCryptograph
		//ok we want to encrypt the test data with DIGEST and IV sent from the server
		std::string EncryptedData;
		if(Digest.EncryptData(ProccessedData, EncryptedData, Hexencoding) == false)
		{
		
			return ENCODEPACKETDATA_ENCRYPTED_FAILED;
		}

		EnCrypted = true;
		if(EncryptedData.size() >= MaxPacketSize)
		{
				ErrorPacketToLarge = true;
				error = ENCODEPACKETDATA_TO_LARGE;
		}
		else
		{
			ProccessedData = EncryptedData;
			ErrorPacketToLarge = false;//we fit
		}

		return error;
	}//end AESEnCrypt
	///////////////////////////////////////////////////////////////////////////////
	




	//----------------------------------------------------------------------------
	//this will create a check sum of the data using the SALT and IV + data
	//-----------------------------------------------------------------------------
	int AESDigestData(cCryptography &Digest, bool hexcoded, int iterations)
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		//we need to create a file digest but with the clients SALT + IV and data
		cCryptography SignedData;
		SignedData.SALT		= Digest.SALT;
		SignedData.IV		= Digest.IV;

		DataSignature = "";

		//ok we are ready to do a fancy check sum of the data
		//use SignedData to create a hash of the encrypted data
		//int iterations = 16384;//we can set less if we want I think ???????
		if(SignedData.GenerateHash(ProccessedData, iterations) == false)
		{
			return ENCODEPACKETDATA_SIGNED_FAILED;
		}


		//save the signature
		SignedData.GetDigest(DataSignature, hexcoded);

		return error;
	}//end AESDigestData
	///////////////////////////////////////////////////////////////////////////////
	
	



	//----------------------------------------------------------------------------------
	//if we want RSA encryption its done on the datas HMAC in AESDigestData stage
	//on the DataSignature
	//-----------------------------------------------------------------------------------
	int RSAPublicSign(const std::string &PublicKeyHexStr)
	{
		int error = ENCODEPACKETDATA_OK;

		if(DataSignature.empty())
			return ENCODEPACKETDATA_EMPTY_RSASIGN;
		
		//ok we now have a valid  DIGEST ready to be encrypted with RSA Key pair encryption
		//using the public key because we are simulating the client here
		std::string CipheredSignedDataHash;
	
		//keypair.PublicKey[0] = '0x2';
		if(RsaEncryptMessage<CryptoPP::AES>(PublicKeyHexStr, DataSignature,  CipheredSignedDataHash) == false)
		{
			return ENCODEPACKETDATA_PUBLICKEY_SIGNED_FAILED;
		}

		//end crypt the DataSignature
		DataSignature = CipheredSignedDataHash;


		RSASigned = true;
		return error;
	}//end RSAPublicSign
	///////////////////////////////////////////////////////////////////////////////
	


	//----------------------------------------------------------------------------------
	//if we want RSA encryption its done on the datas HMAC in AESDigestData stage
	//on the DataDigest
	//-----------------------------------------------------------------------------------
	int RSAPrivateSign(const std::string &PrivateKeyHexStr)
	{
		int error = ENCODEPACKETDATA_OK;

		if(DataSignature.empty())
			return ENCODEPACKETDATA_EMPTY;

		std::string CipheredSignedDataHash;
		//this bit differs because you can't encypt from a private key
		//but the private key can sign the data and no one can change it or the public key will fail
		// generate a signature for the message
		if(RsaSignMessage<CryptoPP::PSSR, CryptoPP::SHA1, CryptoPP::AES>(PrivateKeyHexStr, DataSignature, CipheredSignedDataHash) == false)
		{
			
			return ENCODEPACKETDATA_PRIVATEKEY_SIGNED_FAILED;
		}

		//now a signed data
		DataSignature = CipheredSignedDataHash;

		//end crypt the DataSignature
		RSASigned = true;
		return error;
	}//end RSAPrivateSign
	///////////////////////////////////////////////////////////////////////////////



	//-------------------------------------------------------------------------
	//last set this will Serialize MsgPacket to a out put string
	//returns our data we just proccessed with the above functions
	//--------------------------------------------------------------------------
	int GenerateSerializedMsgPacket(std::string &serialized)
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())//never set the data
			return ENCODEPACKETDATA_EMPTY;


		MsgPacket packet;
		packet.set_compressed(Compressed);
		packet.set_encrypted(EnCrypted);
		packet.set_usersa(RSASigned);
		packet.set_uncompressedsize(UncompressedSize);//we need the size of the file before compression

		if(DataSignature.size() > 0)//we dont need to do this
			packet.set_digest(DataSignature);

		packet.set_serializedprotobuffer(ProccessedData);


		//ok we can serialize and return
		if(packet.SerializeToString(&serialized) == false)
			return ENCODEPACKETDATA_PACKETSERIALIZED_FAILED;

		//check the size
		if(serialized.size() >= MaxPacketSize)
		{
			ErrorPacketToLarge = true;
			error = ENCODEPACKETDATA_TO_LARGE;
		}

		return error;
	}//end GenerateSerializedMsgPacket
	/////////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////////////




};// end cals cEnCodePacketData
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////


















//------------------------------------------------------------------------------------------------------
//this will Decode the MsgPacket google protocol buffer depending on the flags set in the proto buffer
//the decoding is the revers of encode 
//decrypt -> check signature ->decompress -> return valid serialized data that contains the real message
//--------------------------------------------------------------------------------------------------------
class cDeCodePacketData
{
	
	std::string ProccessedData;//we add the data we want tp work with to this
	std::string DataSignature;//we use the clients SALT + IV + ProccessedData to create a check sum of the data encrypted then digest is best
	//if rsa is set we use the public or private keys to encrypt the DataSignature
	//std::string RsaDataSignature;//the DataSignature is encrypted with Private or public key

	bool Compressed;
	bool EnCrypted;
	bool RSASigned;

	int32_t UncompressedSize;//we need to keep the size of the uncompressed data

public:

	//-----------------------------------------------------------------
	//pass in the serialized MsgPacket string
	//-----------------------------------------------------------------
	cDeCodePacketData()
	{
		Compressed			= false;
		EnCrypted			= false;
		RSASigned			= false;
		UncompressedSize	= 0;

	}

	~cDeCodePacketData()
	{
	}
	


	void SetDecodeData(const std::string &inputdata)
	{
		ProccessedData		= inputdata;
		Compressed			= false;
		EnCrypted			= false;
		RSASigned			= false;
		UncompressedSize	= 0;

	}

	//------------------------------------------------------------------------
	//this will allow us to decode the MsgPacket into its google protocol buffer
	//------------------------------------------------------------------------------
	int DecodePacket(bool usingPrivateKey,//we need to know if we are server private = true client public false
					bool Hexcoded,//true for hex string or false plain text
					std::string &serialized,//the out data a serialized brotocol buffer
					const std::string &HexKeyStr,//if usingPrivateKey is true its the server else public key
					const std::string &Salt,//the clients salt
					const std::string &Iv,//iv used for decryption
					const std::string &PasswordDigest,//the clients digest for encryption
					int iterations)//to generate the key
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;


		//the first thing to do is parse the serialized string into a MsgPacket proto buffer
		MsgPacket Packet;

		if(Packet.ParseFromString(ProccessedData) == false)
			return ENCODEPACKETDATA_PACKETSERIALIZED_FAILED;

		//clear the data we have it in the packet proto now
		ProccessedData = "";

		//see if we did any trans forms
		Compressed			= Packet.compressed();
		EnCrypted			= Packet.encrypted();
		RSASigned			= Packet.usersa();
		DataSignature		= Packet.digest();
		UncompressedSize	= Packet.uncompressedsize();


		//assign the data now
		ProccessedData = Packet.serializedprotobuffer();

		
		
		//if we signed the data with RSA we need to decrypt with RSA first
		//set this just in case we not using signing

		
				
		
		
		//we need to decrypt the DataSignature with the private or public key only if we rsa signed the data
		if(RSASigned)
		{
			if(usingPrivateKey)
			{
				//we need to build the data signature of the incomming data so we can validate it correctly
				cCryptography SignedData;
				SignedData.StringToSalt(Salt);
				SignedData.StringToIV(Iv);

				//ProccessedData is compressed encrypted encrypted
				if(SignedData.GenerateHash(ProccessedData, iterations) == false)
				{
					return DECODEPACKETDATA_DATASIGNATURE_FAILED;
				}

				//digests
				std::string generateddigest;
				std::string digestinput;
				SignedData.GetDigest(digestinput, Hexcoded);


				//server uses the private key to decrypt the DataSignature
				if(RsaDecryptMessage<CryptoPP::AES>(HexKeyStr, DataSignature, generateddigest) == false)
				{
					return DECODEPACKETDATA_TAINTED_DATA;
				}

				
				// datasignature all we need to do is compare the digests
				if(cCryptography::IsEqualDigest(generateddigest, digestinput) == false)
				{
					return DECODEPACKETDATA_TAINTED_DATA;
				}

				digestinput = generateddigest;
			}
			else
			{
				//we need to build the data signature of the incomming data so we can validate it correctly
				cCryptography SignedData;
				SignedData.StringToSalt(Salt);
				SignedData.StringToIV(Iv);

				//ProccessedData is compressed encrypted encrypted
				if(SignedData.GenerateHash(ProccessedData, iterations) == false)
				{
					return DECODEPACKETDATA_DATASIGNATURE_FAILED;
				}

				//digests
				std::string digestinput;
				SignedData.GetDigest(digestinput, Hexcoded);


				
				// verify signature against public key
				if(RsaVerifyMessage<CryptoPP::PSSR, CryptoPP::SHA1>(HexKeyStr,digestinput, DataSignature)== false) 
				{
					return DECODEPACKETDATA_TAINTED_DATA;
				}
			}

		}//end rsasign
		else
		{
			//at first connection we have noting activated
			if(DataSignature.empty() == false)
			{
				//we need to build the data signature of the incomming data so we can validate it correctly
				cCryptography SignedData;
				SignedData.StringToSalt(Salt);
				SignedData.StringToIV(Iv);

				//ProccessedData is compressed encrypted encrypted
				if(SignedData.GenerateHash(ProccessedData, iterations) == false)
				{
					return DECODEPACKETDATA_DATASIGNATURE_FAILED;
				}

				//digests
				std::string digestinput;
				SignedData.GetDigest(digestinput, Hexcoded);

				//we never used RSA on the datasignature all we need to do is compare the digests
				//this is like a check sum
				if(cCryptography::IsEqualDigest(digestinput, DataSignature) == false)
				{
					return DECODEPACKETDATA_TAINTED_DATA;
				}
			}

		}

		

		//decrypt the data
		if(EnCrypted)
		{
			//we can now decrypt the data with the clients key
			std::string DecipheredMessage;
			cCryptography Clientkdecipher;
			Clientkdecipher.StringToSalt(Salt);
			Clientkdecipher.StringToIV(Iv);
			Clientkdecipher.StringToDigest(PasswordDigest);

			//the signature is valid we can decrypt the data now
			if(Clientkdecipher.DecryptData(ProccessedData, DecipheredMessage) == false)
			{
				return DECODEPACKETDATA_TAINTED_DECRYPTION;
			}


			//all good copoy the data to our main data
			ProccessedData = DecipheredMessage;

		}//end encryption


		//last decompress the data
		if(Compressed)
		{
			error = DeCompress();
			if(error != ENCODEPACKETDATA_OK)
				return error;

		}//end compressing


		//ok we have done all our decoding return the serialized proto buffer
		serialized = ProccessedData;

		return error;
	}//end DecodePacket
	////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////////


private:

	//--------------------------------------------------------------
	//this will apply the compression to the string
	//compress can change the size of the message so we check the size
	//after compression and return false if wher still to large
	//--------------------------------------------------------------
	int DeCompress()
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		//to unzip the memory we need to know how large the origainal size was need to keep it some where
		std::string uncompressed;
		uncompressed.resize(UncompressedSize);

		uLong unCompressedSize = UncompressedSize;
		 // now uncompress
		int v = uncompress((Bytef*)uncompressed.data(),       // destination for the uncompressed
                                // data.  This should be the size of
                                // the original data, which you should
                                // already know.
								&unCompressedSize,  // length of destination (uncompressed)
														// buffer
								(Bytef*)ProccessedData.data(),   // source buffer - the compressed data
								ProccessedData.size() );   // length of compressed data in bytes

 
		if(v != Z_OK)
			error = ENCODEPACKETDATA_UNCOMPRESS_FAILED;
		else
		{
			//set the data
			ProccessedData = uncompressed;
		}

		return error;
	}//end DeCompress
	//////////////////////////////////////////////////////////////////



/*
	//-------------------------------------------------------------------------
	//there is 2 forms of encryption this one is AES using the clients password 
	//+ SALT + IV
	//cCryptography is the encryption key 
	//---------------------------------------------------------------------------
	int AESDeCrypt(cCryptography &Digest)
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		EnCrypted = true;
		if(ProccessedData.size() >= MaxPacketSize)
		{
				ErrorPacketToLarge = true;
				error = ENCODEPACKETDATA_TO_LARGE;
		}
		else
		{
			ErrorPacketToLarge = false;//we fit
		}

		return error;
	}//end AESDeCrypt
	///////////////////////////////////////////////////////////////////////////////
	




	//----------------------------------------------------------------------------
	//this will create a check sum of the data using the SALT and IV
	//-----------------------------------------------------------------------------
	int AESDigestData(cCryptography &Digest)
	{
		int error = ENCODEPACKETDATA_OK;
		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		//we need to create a file digest but with the clients SALT + IV and data
		cCryptography SignedData;
		SignedData.SALT		= Digest.SALT;
		SignedData.IV		= Digest.IV;

		DataSignature = "datasigned";
		return true;
	}//end AESDigestData
	///////////////////////////////////////////////////////////////////////////////
	
	*/



	//----------------------------------------------------------------------------------
	//if we want RSA encryption its done on the datas HMAC in AESDigestData stage
	//on the DataDigest
	//-----------------------------------------------------------------------------------
	int RSAPublicVerify(std::string &PublicKeyHexStr)
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		//end crypt the DataSignature
		RSASigned = true;
		return error;
	}//end RSAPublicVerify
	///////////////////////////////////////////////////////////////////////////////
	


	//----------------------------------------------------------------------------------
	//if we want RSA encryption its done on the datas HMAC in AESDigestData stage
	//on the DataDigest
	//-----------------------------------------------------------------------------------
	int RSAPrivateVerify(std::string &PrivateKeyHexStr)
	{
		int error = ENCODEPACKETDATA_OK;

		if(ProccessedData.empty())
			return ENCODEPACKETDATA_EMPTY;

		//end crypt the DataSignature
		RSASigned = true;
		return error;
	}//end RSAPrivateVerify
	///////////////////////////////////////////////////////////////////////////////


};// end cals cDeCodePacketData
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////





#endif//ENCODEPACKETDATA_H

This topic is closed to new replies.

Advertisement