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