⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 securechatiocp.cpp

📁 提供加密的c/s 聊天程序。用到对称加密算法和非对称加密算法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		pContext->m_ContextLock.Unlock();
		AppendLog("Secure connection established.");		
#endif
	}
}


/*
* Handle the Public Key B according to Diffie-Hellman 
* key exchange procedure.  	
*  
* Send the respons as Public Key P. 
* 
*/
inline void SecureChatIOCP::OnPKG_PUBLIC_KEYB(CIOCPBuffer *pOverlapBuff, int nSize, ClientContext *pContext)
{	

	// Be safe
	if ( !pContext || !pContext->m_pPublickey || !pOverlapBuff)
		return;

	if ( ComputeAndSetSessionKey(pOverlapBuff,nSize,pContext) )
	{
		// The Server is not Protected from "man in middle attack"
		// the server should authorize the client by a password or something 
		// else. 
		pContext->m_ContextLock.Lock();
		pContext->m_bGotSessionKey=TRUE;
		pContext->m_ContextLock.Unlock();


		// Compute and send Signature. . 
		// FIXME : Should post this part into the 
		// IOCP for fair cpu clock distribution.
		// Takes about > 500ms.. 
#ifdef USE_SIGNATURE
		ComputeAndSendSignature(pContext);
#endif
	}
}




/* 
* EnCryptBuffer(CIOCPBuffer *pBuff, ClientContext *pContext)
* 
* Encrypts The buffer with the Rijndael, Cipher Block Chaining (CBC) cipher. 
* designed by Joan Daemen and Vincent Rijmen as a candidate algorithm for the AES
* The cipher operates on 16 byte blocks and 256 bits keylength. 
*
* The function also computes an CRC16 (two bytes) checksum and add it to the buffer 
* to recognize incorrect decryption on the other side. 
* 
* If the buffer size plus the two bytes that come from the CRC16 is not a multiple of 
* 16 bytes (needed for the encryption), random data is added at the end.
*
* Returns NULL if something went wrong or the encrypted buffer. 
*
*/

CIOCPBuffer *SecureChatIOCP::EnCryptBuffer(CIOCPBuffer *pBuff, ClientContext *pContext)
{

	if ( pBuff==NULL || pContext==NULL )
	{
		ReleaseBuffer(pBuff);
		return NULL;
	}
	if ( !pContext->m_bGotSessionKey)
	{
		ReleaseBuffer(pBuff);
		return NULL;
	}

	CIOCPBuffer *pCrypBuff=NULL;

	//
	// Allocate Buffer for the encrypted pkg. 
	//
	pCrypBuff=AllocateBuffer(IOWrite);

	if ( pCrypBuff!=NULL )
	{
		//
		// Compute CRC16
		// 
		unsigned short usCRC16;
		pContext->m_cCryptor.crc16_init(&usCRC16);
		pContext->m_cCryptor.crc16_update(&usCRC16,pBuff->GetBuffer(),pBuff->GetUsed());
		pContext->m_cCryptor.crc16_final(&usCRC16);

		// 
		// Add the CRC16 to the Buffer
		//
		if ( !pBuff->AddData(usCRC16) )
		{
			AppendLog("Error pBuff->AddData(usCRC16) in EnCryptBuffer");
			DisconnectClient(pContext->m_Socket);
			ReleaseBuffer(pCrypBuff);
		}

		//
		//  Check if The Buffer size is a multiple of the blocksize, if not 
		//  add some random nr. 
		// 

		int iBlockSize=16; 
		int iBufferRest=0;
		UINT iBufferLenght=0;
		iBufferLenght=pBuff->GetUsed();
		iBufferRest=iBufferLenght%iBlockSize;

		// How Much is needed to make the buffersize to be a multible of the block size? 
		if ( iBufferRest!=0 )
		{
			iBufferRest=iBlockSize-iBufferRest;
		}
		// add random Numbers at the end so we will have an cryptable buffer. 
		for ( int i=0; i<iBufferRest; i++ )
		{
			if ( !pBuff->AddData((BYTE)(rand()%255)) )
			{
				AppendLog("Error pBuff->AddData((BYTE)(rand()%255) in EnCryptBuffer");
				DisconnectClient(pContext->m_Socket);
				ReleaseBuffer(pCrypBuff);
			}
		}

		// We have a new length. 
		iBufferLenght=pBuff->GetUsed();
		// For the package type. 
		iBufferLenght++;

		//
		// Configure the new package. 
		//
		if ( iBufferLenght+MINIMUMPACKAGESIZE>MAXIMUMPACKAGESIZE )
		{
			AppendLog("Error package to big to fit in the buffer");
			DisconnectClient(pContext->m_Socket);
			ReleaseBuffer(pCrypBuff);
		}
		// Add the size of the buffer to the beging.We will not crypt this part.
		pCrypBuff->AddData(iBufferLenght);
		// Add the Type. 
		pCrypBuff->AddData((BYTE)PKG_ENCRYPTED);

		//
		// Encrypt and add to payload. 
		//
		try
		{	
			pContext->m_ContextLock.Lock();
			pContext->m_cCryptor.ResetChain();	// Because of CBC
			pContext->m_cCryptor.Encrypt((char const*)pBuff->GetBuffer(),(char*)pCrypBuff->GetBuffer()+MINIMUMPACKAGESIZE+1,iBufferLenght-1,1);
			pContext->m_ContextLock.Unlock();
		}
		catch(exception& roException)
		{

			AppendLog("Error Could not encrypt in EnCryptBuffer");
			DisconnectClient(pContext->m_Socket);
			ReleaseBuffer(pCrypBuff);	
			pContext->m_ContextLock.Unlock();
			pCrypBuff=NULL;
			return NULL;

		}

		// add the payload. 
		pCrypBuff->Use(pBuff->GetUsed());

		ReleaseBuffer(pBuff);

		// 
		// Finished... 
		// 
	}else
	{
		AppendLog("Error Could not allocate memory in EnCryptBuffer");
	}
	return pCrypBuff;
}

/* 
* DeCryptBuffer(CIOCPBuffer *pBuff, ClientContext *pContext)
*
* Decrypts the encrypted buffer. (see EnCryptBuffer(..) for more info) 
*
* Returns the decrypted Buffer or return NULL if failed (or CRC16 did not mach)
*
*/

CIOCPBuffer* SecureChatIOCP::DeCryptBuffer(CIOCPBuffer *pBuff, ClientContext *pContext)
{
	if ( pBuff==NULL || pContext==NULL )
		return NULL;

	if ( !pContext->m_bGotSessionKey )
		return NULL;


	CIOCPBuffer *pCrypBuff=NULL;
	//
	// Allocate Buffer for the encrypted pkg. 
	//
	pCrypBuff=AllocateBuffer(IOWrite);
	if ( pCrypBuff!=NULL )
	{


		//
		// Decrypt 
		//

		int iBufferLenght=pBuff->GetPackageSize();
		try
		{
			pContext->m_ContextLock.Lock();
			pContext->m_cCryptor.ResetChain();	// Because of CBC
			pContext->m_cCryptor.Decrypt((char const*)pBuff->GetBuffer()+MINIMUMPACKAGESIZE+1,(char *)pCrypBuff->GetBuffer(),iBufferLenght-1,1);
			pContext->m_ContextLock.Unlock();
		}
		catch(exception& roException)
		{
			AppendLog("Error Could not encrypt in DeCryptBuffer");
			ReleaseBuffer(pCrypBuff);	
			pCrypBuff=NULL;
			return NULL;
		}

		//
		// Get the CRC Data from the Decrypted package and Make a package test. 
		//

		// First we have to tell it that it have a header. 
		pCrypBuff->Use(MINIMUMPACKAGESIZE);

		// Get the PackageSize. 
		iBufferLenght=pCrypBuff->GetPackageSize();

		//
		// Check if the size was correct
		//
		if ( iBufferLenght>MAXIMUMPACKAGESIZE-MINIMUMPACKAGESIZE )
		{
			AppendLog("Error Could not dencrypt in DeCryptBuffer. (the header size was to big)");
			ReleaseBuffer(pCrypBuff);
			return NULL;
		}

		// well we have to tell our buffer that it has the data.
		pCrypBuff->Use(iBufferLenght);


		unsigned short uspkgCRC16;

		// We put the two byte long CRC cheksum at the end of package..
		memcpy(&uspkgCRC16,pCrypBuff->GetBuffer()+MINIMUMPACKAGESIZE+iBufferLenght,sizeof(unsigned short));

		//
		// Compute CRC16
		// 
		unsigned short usCRC16;
		pContext->m_cCryptor.crc16_init(&usCRC16);
		pContext->m_cCryptor.crc16_update(&usCRC16,pCrypBuff->GetBuffer(),pCrypBuff->GetUsed());
		pContext->m_cCryptor.crc16_final(&usCRC16);

		// The package is not Decrypted correctly. 
		if ( uspkgCRC16!=usCRC16 )
		{
			AppendLog("CRC16 cheksum Error. in DeCryptBuffer.");
			ReleaseBuffer(pCrypBuff);
			return NULL;
		}

		// 
		// Finished... 
		// 
	}else
	{
		AppendLog("Error Could not allocate memory in EnCryptBuffer");
		//DisconnectClient(pContext->m_Socket);
	}
	return pCrypBuff;

}



int SecureChatIOCP::MaxEncyptedPayloadSize(int iMaxLength)
{
	//
	// For encryption we need some extra space. . 
	// 

	// We have to make room for another sizeheader,type header  
	// and also The CRC Checksum 
	iMaxLength-=(MINIMUMPACKAGESIZE+sizeof(unsigned short)+1);
	// Furthermore we have to be sure that the maximumsize is 
	// a multipe of the blocksize (16). 
	// e.g a maximum size of 500 or 499 ot 488 results will be increased 
	// to 512 because of encryption algorithm.. The total size of the data 
	// must be a multiple of 16. 
	int iMaxCryptSize=MAXIMUMENCRYPSIZE-MINIMUMPACKAGESIZE-MINIMUMPACKAGESIZE-sizeof(unsigned short)-1;
	//iMaxLength=(iMaxLength>iMaxCryptSize) ? iMaxCryptSize : iMaxLength;
	return min(iMaxLength,iMaxCryptSize);
}


void SecureChatIOCP::SendTextMessage(CString msg)
{
	// FIXME: Should post this into IOCP so it is handled by IOWORKERS. 
	m_ContextMapLock.Lock();

	UINT nSize= m_ContextMap.GetCount();
	if ( m_ContextMap.GetCount()>0 )
	{
		POSITION pos = m_ContextMap.GetStartPosition ();
		// Here we must check if the m_ContextMap.GetCount() is > 0 because 
		// One or more clients can be disconnected handling SendTextMessageTo(..)
		while ( pos != NULL && m_ContextMap.GetCount()>0 ) 
		{

			unsigned int iKey;
			ClientContext *pContext=NULL;
			m_ContextMap.GetNextAssoc (pos, iKey,pContext);
			if ( pContext!=NULL )
			{
				SendTextMessageTo(pContext,msg);
			}
		}
	}
	m_ContextMapLock.Unlock(); 	

}

/*
* Send Message to Client with ID  iClientID	
*
*/
BOOL SecureChatIOCP::SendTextMessageTo(int iClientID, CString sMsg)
{

	BOOL bRet=FALSE;
	m_ContextMapLock.Lock();
	ClientContext* pContext = FindClient(iClientID);

	if ( pContext == NULL )
	{
		m_ContextMapLock.Unlock();
		return FALSE;
	}

	bRet=SendTextMessageTo(pContext,sMsg); 
	m_ContextMapLock.Unlock();
	return bRet;
}

/*
* Returns true if we have active connections. 
*
*/
BOOL SecureChatIOCP::IsConnected()
{
	UINT nSizeOfConnectedClients=0;
	m_ContextMapLock.Lock();
	nSizeOfConnectedClients=m_ContextMap.GetCount();
	m_ContextMapLock.Unlock();
	return nSizeOfConnectedClients>0;
}


BOOL SecureChatIOCP::SendTextMessageTo(ClientContext* pContext, CString sMsg)
{

	if ( !pContext->m_bGotSessionKey )
	{
		//AppendLog("Client is not authorized");
		return FALSE;
	}

	UINT nBufLen = sMsg.GetLength();
	// Add one to the size header for the null termination byte. 
	nBufLen++;
	// Add one for the Payload type (text)
	nBufLen++;

	if ( nBufLen>=MaxEncyptedPayloadSize(MAXIMUMPAYLOADSIZE-2) )
	{
		AppendLog("SendMessageTo FAILED Message to long for encryption..");
		return FALSE;
	}

	if ( nBufLen>=MAXIMUMPAYLOADSIZE || nBufLen<=0 )
	{
		AppendLog("SendMessageTo FAILED Message to long or zero..");
		return FALSE;
	}

	CIOCPBuffer *pBuff=AllocateBuffer(IOWrite);

	if ( !pBuff )
	{
		AppendLog("SendMessageTo FAILED pOverlapBuff=NULL");
		return FALSE;
	}

	pBuff->EmptyUsed();
	// Size Header
	pBuff->AddData(nBufLen);
	// Payload Header 
	pBuff->AddData((BYTE)PKG_TEXT_TO_ALL);
	// Add the string. 
	int length=sMsg.GetLength();
	pBuff->AddData((PBYTE) sMsg.GetBuffer(length),length);
	//Extra Null Teriminate (for Strings) 
	pBuff->AddData((BYTE)'\0');
	// Encrypt the buffer
	pBuff=EnCryptBuffer(pBuff,pContext);
	// Send it. 
	ASend(pContext,pBuff);
	return TRUE;

}


BOOL SecureChatIOCP::SendErrorMessageTo(int iClientID, CString sMsg)
{
	UINT nBufLen = sMsg.GetLength();
	// Add one to the size header for the null termination byte. 
	nBufLen++;
	// Add one for the message type (encrypted/SessionExchange/ERROR_MESSAGE)..  
	nBufLen++;
	// Add one for the Payload type (text)
	nBufLen++;

	if ( nBufLen>=MAXIMUMPAYLOADSIZE || nBufLen<=0 )
	{
		AppendLog("SendMessageTo FAILED Message to long or zero..");
		return FALSE;
	}

	CIOCPBuffer *pBuff=AllocateBuffer(IOWrite);

	if ( !pBuff )
	{
		AppendLog("SendMessageTo FAILED pOverlapBuff=NULL");
		return FALSE;
	}

	// Make sure that buffer is empty  
	pBuff->EmptyUsed();
	// Size Header
	pBuff->AddData(nBufLen);
	// Message Header
	pBuff->AddData((BYTE)PKG_ERRORMSG);
	// Payload Header 
	pBuff->AddData((BYTE)PKG_ERRORMSG);
	// Add the string. 
	int length=sMsg.GetLength();
	pBuff->AddData((PBYTE) sMsg.GetBuffer(length),length);
	//Extra Null Teriminate (for Strings) 
	pBuff->AddData((BYTE)'\0');
	ASend(iClientID,pBuff);
	return TRUE; 

}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -