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

📄 secretchatdlg.cpp

📁 一个用RSA算法实现加密通信的聊天程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	//把注册表好友公钥文件名改成现在的连线好友
	AfxGetApp()->WriteProfileString(
		"SecretKeySetup", 
		"FriendPublicKey",
		secretKeyEditDlg.CharToCString(secretKey.userName, 32) + ".pk");

	//提示成功
	MessageBox(
		"已经获得公钥 " + AfxGetApp()->GetProfileString("SecretKeySetup", "FriendPublicKey"),
		"密聊",
		MB_ICONINFORMATION);

	MyUpdateData();	//更新设置

	return TRUE;

}

BOOL CSecretChatDlg::ValidatePrivateKey()	//验证私钥的设置情况
{
	//连接之情必须要有一个私钥并且要有一个被选中
	WIN32_FIND_DATA wfd;
	HANDLE hSearch;

	//判断是否至少有一个私钥文件
	hSearch = ::FindFirstFile(
		m_appName + "\\user\\*.sk" ,
		&wfd);
	if(hSearch == INVALID_HANDLE_VALUE)
	{	//没有私钥存在,就要提示生成新的密钥
		MessageBox(
			"没有任何用户私钥文件,请先创建新的密钥",
			"密聊",
			MB_ICONINFORMATION);
		CSecretKeyEdit secretKeyEditDlg;
		secretKeyEditDlg.m_select = SELECT_CREATE;
		secretKeyEditDlg.DoModal();
		return FALSE;	//没有生成密钥将永远不能进行连接
	}
	
	hSearch = ::FindFirstFile(
		m_appName
		+ "\\user\\" 
		+ AfxGetApp()->GetProfileString("SecretKeySetup", "UserPrivateKey"),
		&wfd);
	if(hSearch == INVALID_HANDLE_VALUE)
	{	//没有选择私钥,提示要选择
		MessageBox(
			"通讯前必须选择用户私钥文件",
			"密聊",
			MB_ICONINFORMATION);
		m_setupDlg.m_index = 1;
		m_setupDlg.DoModal();	//选择私钥和公钥
		return FALSE;	//没有选中将永远不能进行连接
	}

	//还有判断它是合格的私钥文件
	CSecretKeyEdit secretKeyEditDlg;
	if(secretKeyEditDlg.validateSecretKey(	
		m_appName
		+ "\\user\\" 
		+ AfxGetApp()->GetProfileString("SecretKeySetup", "UserPrivateKey")) != SECRETKEY_PRIVATE)
	{
		MessageBox(
			AfxGetApp()->GetProfileString("SecretKeySetup", "UserPrivateKey") + " 不是合格的私钥文件",
			"密聊",
			MB_ICONINFORMATION);
		m_setupDlg.m_index = 1;
		m_setupDlg.DoModal();
		return FALSE;	//不合格将永远不能进行连接
	}

	if(!InstallPrivateKey())	//安装私钥文件
	{
		MessageBox(
			"无法安装用户私钥文件",
			"密聊",
			MB_ICONINFORMATION);
		return FALSE;
	}

	return TRUE;
}

BOOL CSecretChatDlg::ValidatePublicKey()	//验证公钥的设置情况
{	
	WIN32_FIND_DATA wfd;
	HANDLE hSearch;

	//连接成功后,就要判断有没好友公钥
	//判断是否至少有一个公钥文件
	hSearch = ::FindFirstFile(
		m_appName + "\\friend\\*.pk" ,
		&wfd);
	if(hSearch == INVALID_HANDLE_VALUE)
	{	//没有公钥存在,就要提示请求获取新的公钥
		if(MessageBox(
			"没有任何好友公钥文件,是否请求获取对方的公钥?",
			"密聊",
			MB_YESNO | MB_ICONQUESTION) == IDYES)
		{	//获取对方的公钥

			AskPublicKey();
		}
		return FALSE;
	}

	//查看公钥是否被选中
	hSearch = ::FindFirstFile(
		m_appName
		+ "\\friend\\" 
		+ AfxGetApp()->GetProfileString("SecretKeySetup", "FriendPublicKey"),
		&wfd);
	if(hSearch == INVALID_HANDLE_VALUE)
	{	//没有选择公钥,提示要选择和获取新的公钥

		if(MessageBox(
			"请选择好友公钥文件或请求获取对方的公钥,\r\n是否请求获取对方的公钥?",
			"密聊",
			MB_YESNO | MB_ICONQUESTION) == IDYES)
		{	//获取对方的公钥

			AskPublicKey();
		}
		else
		{
			m_setupDlg.m_index = 2;
			m_setupDlg.DoModal();
		}
		return FALSE;
	}

	//还有判断它是合格的公钥文件
	CSecretKeyEdit secretKeyEditDlg;
	if(secretKeyEditDlg.validateSecretKey(	
		m_appName
		+ "\\friend\\" 
		+ AfxGetApp()->GetProfileString("SecretKeySetup", "FriendPublicKey")) != SECRETKEY_PUBLIC)
	{
		MessageBox(
			AfxGetApp()->GetProfileString("SecretKeySetup", "FriendPublicKey") + " 不是合格的公钥文件",
			"密聊",
			MB_ICONINFORMATION);
		m_setupDlg.m_index = 2;
		m_setupDlg.DoModal();
		return FALSE;	//不合格将永远不能进行连接
	}

	if(!InstallPublicKey())	//安装公钥文件
	{
		MessageBox(
			"无法安装好友公钥文件",
			"密聊",
			MB_ICONINFORMATION);
		return FALSE;
	}


	return TRUE;
}

LRESULT CSecretChatDlg::RunHide(WPARAM wParam,LPARAM lParam)	//运行时隐藏窗口
{
	if(wParam == 0)
	{
		ShowWindow(SW_HIDE);	//隐藏窗口
		MoveWindow(m_rect);
		return 0;
	}
	if(wParam == 1)//询问打开接收到的文件
	{
		if(MessageBox(
			"是否打开 " + m_receive_file_name + " 文件?",
			"密聊",
			MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
		{
			::ShellExecute(
				NULL, 
				"open",
				m_receive_file_name, 
				"", 
				"",
				SW_SHOW);
		}
		return 0;
	}
	if(wParam == 2)
	{
		int arithmometer(0);
		while(!(ValidatePrivateKey() && ValidatePublicKey()))
		{//必须要把私钥和公钥安装好了,才能开始接收消息
			if(arithmometer++ == 5)
				break;
		};
		if(arithmometer != 5)
		{	//向对方发送"你好!我们可以进行安全通话了。"

			
		}
	}
	return 0;
}

void CSecretChatDlg::TrayIcon()	//设置状态区图标
{
	if(AfxGetApp()->GetProfileInt("General", "Tray", 1))
	{	
		//必须先删除图标才能用这种方法更改任务栏状态区图标
		MyTaskBarDeleteIcon( 
			101,
			m_hWnd);		
		if(m_online)
		{
			MyTaskBarAddIcon(
				m_hWnd,
				101,
				m_hOnline,
				"文件密使 - 密聊(已连接)");//在任务栏状态区添加图标	
		}
		else
		{
			MyTaskBarAddIcon(
				m_hWnd,
				101,
				m_hOffline,
				"文件密使 - 密聊(未连接)");//在任务栏状态区添加图标	
		}
	}
	else
	{	
		MyTaskBarDeleteIcon( 
			101,
			m_hWnd);	//从任务栏状态区删除图标
	}
}

void CSecretChatDlg::TextToMessagePackage(MessagePackage &package, CString strm)	//将明文strm转化成消息包
{
	MessageDollop *pDollop;
	__DWORD128 b1, b2;
	int quotient, remainder, i, j;
	CSecretKeyEdit secretKeyEditDlg;	//只为了转换时间格式

	char chm[DATA_LENGTH];	//明文
//	package.n/*明文长度*/ = strm.GetLength();
	secretKeyEditDlg.CStringToChar(chm, strm, package.n);

	quotient = (package.n * 2) / sizeof(MessageDollop);
	remainder = (package.n * 2) % sizeof(MessageDollop);
	if(remainder != 0)
	{
		quotient++;
		//多余的补零
		for(i = package.n;i < (package.n + (int)sizeof(MessageDollop) / 2 - remainder);i++)
		{
			chm[i] = 0;
		}
	}
 
	pDollop = new MessageDollop[quotient];	//消息块是消息包的元素

	//分配每条消息块和总消息包的ID
	b2.Nil();
	for(i = 0;i < quotient;i++)
	{	
		b1.RandCount();	//没有生成随机的数吗?
		b2 = b2 + b1;
		b1.Store(pDollop[i].messageDollop_ID/*每个消息块的ID*/);
	}
/*	for(int s = 0;s < 32;s++)
	{
		if(b2 == m_send_message_package_ID[s])
		{	//这里表示b1.RandCount()没有生成随机数
			//TRACE("这里出错了");
			AfxMessageBox("出现了相同的随机数了");
		}
	}*/
	//把它添加到发送消息ID数组中,可以等下查询
	m_send_message_package_ID_add(b2/*这里b2变成了消息包的ID了*/);

	//获得当前的时间
	CTime time = CTime::GetCurrentTime();
	m_send_time = time.Format("%Y-%m-%d %H:%M:%S");

	//写入数字标识
	b1.DigitalID();//这里b1变成了数字标识了

	for(i = 0;i < quotient;i++)
	{
		//把消息块合并成消息包

		//必须为0,否则会无法进行加解密
		pDollop[i].nil[0] = 0;	

		//消息包ID
		b2.Store(pDollop[i].messagePackage_ID); 

		//数字标识
		b1.Store(pDollop[i].digital_ID); 

		//发送时间
		secretKeyEditDlg.CStringToChar(
			pDollop[i].time,
			m_send_time, 
			20);

		//获得正文内容
		::MoveMemory(
			pDollop[i].text,
			chm + i * sizeof(MessageDollop) / 2,
			sizeof(MessageDollop) / 2);//除2是因为只要得到正文信息

		//设置随机数
		srand((unsigned)::GetTickCount());	//播撒随机数的种子,rand()才能生成随机数
		for(j = 0;j < 16;j++)
		{
			pDollop[i].randCount[j] = (char)(0x41+rand()%0xAF);
			//pDollop[j应该是i的这样会产生无法回复的错误].randCount[j] = (char)rand();
		}

		//把信息存储到消息包中
		::MoveMemory(
			package.data + i * sizeof(MessageDollop),//目标
			(char *)&pDollop[i],						//源内容
			sizeof(MessageDollop));

	}
	//设置消息包的头信息
	package.head = HEAD_TEXT;

	delete[] pDollop;
}

void CSecretChatDlg::MessagePackageToText(MessagePackage &package)//将消息包转化成明文
{
	MessageDollop *pDollop;
	__DWORD128 b1, b2;
	BOOL bMessagePackageID = TRUE;	//只要有一个数字标识不合就永远不能给m_receive_digital_ID合
	int quotient, remainder, i;
	CSecretKeyEdit secretKeyEditDlg;	//只为了转换时间格式

	quotient = (package.n * 2) / sizeof(MessageDollop);
	remainder = (package.n * 2) % sizeof(MessageDollop);
	quotient = remainder?++quotient:quotient;//quotient代表有几个消息块

	pDollop = new MessageDollop[quotient];	//消息块是消息包的元素

	m_receive_message_dollop_ID.Nil();

	for(i = 0;i < quotient;i++)
	{
		//把消息包分成若干块
		::MoveMemory(
			(char *)&pDollop[i],					//目标
			package.data + i * sizeof(MessageDollop),//源内容
			sizeof(MessageDollop));

		//获得正文内容
		::MoveMemory(
			m_receive_text + i * sizeof(MessageDollop) / 2,
			pDollop[i].text,
			sizeof(MessageDollop) / 2);//除2是因为只要得到正文信息

		//获得数字标识
		if(bMessagePackageID)
		{
			b1.Load(pDollop[i].digital_ID);	//对方签名的数字标识
			b2.DigitalID();
			if(!(b1 == b2))//只要有一个消息块不合,就不能使得m_messagePackageID合格
			{
				bMessagePackageID = FALSE;
			}
			m_receive_digital_ID = b1;
		}

		//获得消息包的ID
		b1.Load(pDollop[i].messageDollop_ID/*每个消息块的ID*/);
		m_receive_message_dollop_ID = m_receive_message_dollop_ID + b1;

	}
	//获得整个消息包的ID
	m_receive_message_package_ID.Load(pDollop[0].messagePackage_ID/*消息包的ID*/);
	
	//获得消息发送的时间
	m_receive_time = secretKeyEditDlg.CharToCString(pDollop[0].time, 20);

	//获取正文的长度
	m_receive_text_length = package.n;

	delete[] pDollop;

}

CString CSecretChatDlg::GetUserName()	//获得通信的用户名
{
	CString fileName =
		m_appName 
		+ "\\user\\" 
		+ AfxGetApp()->GetProfileString("SecretKeySetup", "UserPrivateKey");

	CFile file;
	SecretKey secretKey;
	if(!file.Open(
		fileName,
		CFile::modeReadWrite | CFile::typeBinary))
		return "";
	if(file.GetLength() != sizeof(SecretKey))
		return "";
	file.SeekToBegin();
	file.Read(&secretKey, sizeof(SecretKey));
	file.Close();

	if(secretKey.ID != SECRETKEY_ID)
		return "";
	if(secretKey.privateOrPublic != SECRETKEY_PRIVATE)
		return "";

	return secretKey.userName;
}

CString CSecretChatDlg::GetFriendName()	//获得通信的好友名
{
	CString fileName =
		m_appName 
		+ "\\friend\\" 
		+ AfxGetApp()->GetProfileString("SecretKeySetup", "FriendPublicKey");

	CFile file;
	SecretKey secretKey;
	if(!file.Open(
		fileName,
		CFile::modeReadWrite | CFile::typeBinary))
		return "";
	if(file.GetLength() != sizeof(SecretKey))
		return "";
	file.SeekToBegin();
	file.Read(&secretKey, sizeof(SecretKey));
	file.Close();

	if(secretKey.ID != SECRETKEY_ID)
		return "";
	if(secretKey.privateOrPublic != SECRETKEY_PUBLIC)
		return "";

	return secretKey.userName;

}

void CSecretChatDlg::send_or_receive_tip(BOOL sendOrReceive)//发送和收到消息提示信息和处理
{
	CString nowMessage;	//现在获得的信息
	CFileFind find;		//查找文件用
	CFile	file;
	CString fileName;	//消息记录文件名
	if(sendOrReceive)
	{	//发送
		nowMessage = 
			"(" 
			+ 
			m_send_time 
			+ ")\t" 
			+ GetUserName() 
			+ "\r\n" 
			+ m_message 
			+ "\r\n";
		m_messageNote += nowMessage;

		m_statusMessages.SetWindowText("发送消息");
		m_messageNoteEdit.SetWindowText(m_messageNote);
		//将消息记录框滚动到最尾
		m_messageNoteEdit.LineScroll(m_messageNoteEdit.GetLineCount());
		m_messageEdit.SetWindowText("");
		//焦点再回到消息输入框
		m_messageEdit.SetFocus();

		PlayWaveSound(IDR_MESSAGESEND);
	}
	else
	{		
		CSecretKeyEdit secretKeyEditDlg;	//只为了转换密文格式
		nowMessage = 
			"(" 
			+ m_receive_time 
			+ ")\t" 
			+ GetFriendName() 
			+ "\r\n" 
			+ secretKeyEditDlg.CharToCString(m_receive_text, m_receive_text_length) 
			+ "\r\n";
		m_mes

⌨️ 快捷键说明

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