www.pudn.com > 密聊源程序.rar > SecretKeyEdit.cpp


// SecretKeyEdit.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "secretchat.h" 
#include "SecretKeyEdit.h" 
#include "RSA.h" 
#include "SecretChatDlg.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CSecretKeyEdit dialog 
 
 
CSecretKeyEdit::CSecretKeyEdit(CWnd* pParent /*=NULL*/) 
	: CDialog(CSecretKeyEdit::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CSecretKeyEdit) 
	m_email = _T(""); 
	m_qq = _T(""); 
	m_userName = _T(""); 
	m_secretKeyEdit = _T(""); 
	//}}AFX_DATA_INIT 
} 
 
 
void CSecretKeyEdit::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CSecretKeyEdit) 
	DDX_Text(pDX, IDC_EMAIL, m_email); 
	DDV_MaxChars(pDX, m_email, 32); 
	DDX_Text(pDX, IDC_QQ, m_qq); 
	DDV_MaxChars(pDX, m_qq, 32); 
	DDX_Text(pDX, IDC_USERNAME, m_userName); 
	DDV_MaxChars(pDX, m_userName, 32); 
	DDX_Text(pDX, IDC_SECRETKEY, m_secretKeyEdit); 
	//}}AFX_DATA_MAP 
} 
 
 
BEGIN_MESSAGE_MAP(CSecretKeyEdit, CDialog) 
	//{{AFX_MSG_MAP(CSecretKeyEdit) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CSecretKeyEdit message handlers 
DWORD WINAPI create_secret_key_thread(LPVOID param)	//创建密钥线程函数 
{ 
	CSecretKeyEdit * pKey = (CSecretKeyEdit *)param; 
 
	//查看文件是否存在 
	CFileFind find; 
	if( find.FindFile(pKey->m_user_private_key_file_name) ) 
	{ 
		//提示文件存在并退出 
		MessageBox( 
			NULL, 
			"文件已经存在", 
			"生成私钥文件", 
			MB_ICONEXCLAMATION); 
		pKey->SetWindowText("创建新的用户密钥"); 
		pKey->m_bCreate = TRUE;	//能再创建 
		return 0; 
	} 
 
	//生成密钥和用户信息 
	private_key key; 
	key.create(); 
	key.vlong_to_SK(pKey->m_secretKey.sk); 
	key.vlong_to_PK(pKey->m_secretKey.pk); 
	pKey->CStringToChar( 
		pKey->m_secretKey.userName, 
		pKey->m_userName, 
		32); 
	pKey->CStringToChar( 
		pKey->m_secretKey.qq, 
		pKey->m_qq, 
		32); 
	pKey->CStringToChar( 
		pKey->m_secretKey.email, 
		pKey->m_email, 
		32); 
	pKey->m_secretKey.version = SECRETKEY_VERSION; 
	pKey->m_secretKey.privateOrPublic = SECRETKEY_PRIVATE; 
	pKey->m_secretKey.ID = SECRETKEY_ID; 
 
 
	//把密钥信息写入文件,私钥文件 
	CFile file; 
	file.Open( 
		pKey->m_user_private_key_file_name, 
		CFile::modeCreate | CFile::modeReadWrite | CFile::typeBinary); 
	file.Write( 
		&pKey->m_secretKey, 
		sizeof(SecretKey));	//写入信息 
	file.Close(); 
 
	//把密钥信息写入文件,公钥文件 
	pKey->CreatePublicKey(pKey->m_user_private_key_file_name); 
 
	//提示成功 
	MessageBox( 
		NULL, 
		"已经生成密钥,可以安全的进行通讯。", 
		"密聊", 
		MB_ICONINFORMATION); 
	//更新列表,如果没m_publicKeyManagerDlg窗口就会出错 
	//pSecretChatDlg->m_setupDlg.ShowTabWindow(1); 
 
	pKey->m_bCreate = TRUE;	//可以再创建 
	pKey->SetWindowText("创建新的用户密钥"); 
 
	return 0; 
} 
 
void CSecretKeyEdit::OnOK()  
{ 
	if(!m_bCreate) 
	{ 
		MessageBox( 
			"创建密钥中", 
			"密聊", 
			MB_ICONINFORMATION); 
		return; 
	} 
 
	CSecretChatDlg * pSecretChatDlg = (CSecretChatDlg *)AfxGetMainWnd(); 
 
	if(!UpdateData()) return; 
 
	CEdit *pTemp; 
	if(m_userName == "") 
	{  
		pTemp = (CEdit *)GetDlgItem(IDC_USERNAME); 
		pTemp->SetFocus(); 
		//不能为空 
		MessageBox( 
			"不能为空", 
			"warning", 
			MB_ICONEXCLAMATION); 
		return; 
	} 
	else if(m_qq == "") 
	{  
		pTemp = (CEdit *)GetDlgItem(IDC_QQ); 
		pTemp->SetFocus(); 
		//不能为空 
		MessageBox( 
			"不能为空", 
			"warning", 
			MB_ICONEXCLAMATION); 
		return; 
	} 
	else if(m_email == "") 
	{  
		pTemp = (CEdit *)GetDlgItem(IDC_EMAIL); 
		pTemp->SetFocus(); 
		//不能为空 
		MessageBox( 
			"不能为空", 
			"warning", 
			MB_ICONEXCLAMATION); 
		return; 
	} 
 
	if(m_select == SELECT_CREATE) 
	{	 
		SetWindowText("创建新的用户密钥 (正在创建中)"); 
		m_user_private_key_file_name =  
			pSecretChatDlg->m_appName + "\\user\\" + m_userName + ".sk"; 
 
		m_bCreate = FALSE;	//不能再创建 
		unsigned long nThreadID; 
		::CreateThread( 
			NULL, 
			0, 
			create_secret_key_thread, 
			this, 
			0, 
			&nThreadID); 
		return; 
 
	} 
	else //SELECT_PRIVATE和SELECT_PUBLIC的处理相同 
	{	 
		CStringToChar( 
			m_secretKey.qq, 
			m_qq, 
			32); 
		CStringToChar( 
			m_secretKey.email, 
			m_email, 
			32); 
		//更改密钥信息写入私钥文件 
		CFile file; 
		file.Open( 
			m_fileName,//密钥的文件全路径 
			CFile::modeReadWrite | CFile::typeBinary); 
		file.SeekToBegin(); 
		file.Write( 
			&m_secretKey, 
			sizeof(SecretKey));	//写入信息 
		file.Close(); 
	} 
	 
	CDialog::OnOK(); 
} 
 
void CSecretKeyEdit::OnCancel()  
{ 
	if(!m_bCreate) 
	{ 
		MessageBox( 
			"创建密钥中", 
			"密聊", 
			MB_ICONINFORMATION); 
		return; 
	} 
	 
	CDialog::OnCancel(); 
} 
 
BOOL CSecretKeyEdit::OnInitDialog()  
{ 
	CDialog::OnInitDialog(); 
	 
	CEdit *pUserName = (CEdit *)GetDlgItem(IDC_USERNAME); 
	CStatic *pSecretKeyStatic = (CStatic *)GetDlgItem(IDC_SECRETKEYSTATIC); 
	CButton *pOK = (CButton *)GetDlgItem(IDOK); 
	CEdit *psecretKey = (CEdit *)GetDlgItem(IDC_SECRETKEY); 
	if(m_select == SELECT_CREATE) 
	{ 
		pSecretKeyStatic->SetWindowText("生成密钥说明:"); 
		pUserName->SetReadOnly(FALSE); 
		SetWindowText("创建新的用户密钥"); 
		pOK->SetWindowText("生成"); 
		 
		CString str; 
		str.LoadString(IDS_CREATEPUBLICKEYHELP); 
		psecretKey->SetWindowText(str); 
		//psecretKey->SetWindowText("    \"密聊\"采用 2048bit 的 RSA 数据加密算法对数据进行加密和数字签名,在使用前必须生成用户的私钥和公钥。\r\n    只要通过安全通道相互把公钥传递给通讯方后,彼此就可以进行安全的通话和身份验证了。\r\n    生成私有密钥文件 [用户名.sk] 和公开密钥文件 [用户名.pk] 的过程需要稍等几分钟..."); 
	} 
	else if(m_select == SELECT_PRIVATE) 
	{ 
		pSecretKeyStatic->SetWindowText("私钥信息(2048bit):"); 
		pUserName->SetReadOnly(); 
		SetWindowText("用户私钥编辑"); 
		pOK->SetWindowText("更改"); 
	} 
	else if(m_select == SELECT_PUBLIC) 
	{ 
		pSecretKeyStatic->SetWindowText("公钥信息(2048bit):"); 
		pUserName->SetReadOnly(); 
		SetWindowText("好友公钥编辑"); 
		pOK->SetWindowText("更改"); 
	} 
 
	m_bCreate = TRUE;	//可以再创建 
 
	return TRUE;  // return TRUE unless you set the focus to a control 
	              // EXCEPTION: OCX Property Pages should return FALSE 
} 
 
CString CSecretKeyEdit::CharToHexToString(char m)	//把一个字符转换成十六进制再用字符表示 
{ 
	char hex; 
	CString strHex; 
	//左边4位的表示 
	hex = m & (char)0xf0; 
	hex = hex >> 4; 
	hex = hex & (char)0xf;	//有时被移进来的为会为1 
	switch(hex) 
	{ 
	case 0: 
		strHex = "0"; 
		break; 
	case 1: 
		strHex = "1"; 
		break; 
	case 2: 
		strHex = "2"; 
		break; 
	case 3: 
		strHex = "3"; 
		break; 
	case 4: 
		strHex = "4"; 
		break; 
	case 5: 
		strHex = "5"; 
		break; 
	case 6: 
		strHex = "6"; 
		break; 
	case 7: 
		strHex = "7"; 
		break; 
	case 8: 
		strHex = "8"; 
		break; 
	case 9: 
		strHex = "9"; 
		break; 
	case 10: 
		strHex = "A"; 
		break; 
	case 11: 
		strHex = "B"; 
		break; 
	case 12: 
		strHex = "C"; 
		break; 
	case 13: 
		strHex = "D"; 
		break; 
	case 14: 
		strHex = "E"; 
		break; 
	case 15: 
		strHex = "F"; 
		break; 
	} 
 
	//右边4位的表示 
	hex = m & (char)0xf; 
	switch(hex) 
	{ 
	case 0: 
		strHex += "0"; 
		break; 
	case 1: 
		strHex += "1"; 
		break; 
	case 2: 
		strHex += "2"; 
		break; 
	case 3: 
		strHex += "3"; 
		break; 
	case 4: 
		strHex += "4"; 
		break; 
	case 5: 
		strHex += "5"; 
		break; 
	case 6: 
		strHex += "6"; 
		break; 
	case 7: 
		strHex += "7"; 
		break; 
	case 8: 
		strHex += "8"; 
		break; 
	case 9: 
		strHex += "9"; 
		break; 
	case 10: 
		strHex += "A"; 
		break; 
	case 11: 
		strHex += "B"; 
		break; 
	case 12: 
		strHex += "C"; 
		break; 
	case 13: 
		strHex += "D"; 
		break; 
	case 14: 
		strHex += "E"; 
		break; 
	case 15: 
		strHex += "F"; 
		break; 
	} 
 
	return strHex; 
} 
 
int CSecretKeyEdit::validateSecretKey(CString fileName)	 
{ //验证是不是密钥文件(私钥为1,公钥为2,都不是为0) 
	m_fileName = fileName; 
	CFile file; 
	if(!file.Open( 
		fileName, 
		CFile::modeReadWrite | CFile::typeBinary)) 
		return 0; 
	if(file.GetLength() != sizeof(SecretKey)) 
		return 0; 
	file.SeekToBegin(); 
	file.Read(&m_secretKey, sizeof(SecretKey)); 
	file.Close(); 
 
	if(m_secretKey.ID != SECRETKEY_ID) 
		return 0; 
 
	m_userName = CharToCString(m_secretKey.userName, 32); 
	m_qq = CharToCString(m_secretKey.qq, 32); 
	m_email = CharToCString(m_secretKey.email, 32); 
 
	char chTemp[2048 / 8]; 
	if(m_secretKey.privateOrPublic == SECRETKEY_PRIVATE) 
	{		 
		::MoveMemory( 
			chTemp,						//目标 
			(char *)&m_secretKey.sk,	//源内容 
			2048 / 8); 
	} 
	else 
	{	 
		::MoveMemory( 
			chTemp,						//目标 
			(char *)&m_secretKey.pk,	//源内容 
			2048 / 8); 
	} 
	 
	//将密钥换成二进制显示 
	m_secretKeyEdit = ""; 
	for(int i = 0;i < 256;i++) 
	{ 
		m_secretKeyEdit += CharToHexToString(chTemp[i]) + " "; 
		if(!(i == 0 || i == 255)) 
		{ 
			if((i + 1) % 16 == 0) 
				m_secretKeyEdit += "\r\n"; 
		} 
	} 
 
	return m_secretKey.privateOrPublic; 
} 
 
void CSecretKeyEdit::CStringToChar(char *ch, CString str,int n) 
{	//字符串转到字符数组 
	for( int i = 0;i < str.GetLength();i++) 
	{ 
		if( i == n) return; 
		ch[i] = str[i]; 
	} 
	if( i == n) return;	//为了使数组char[n]不越界,才要这样做的 
	ch[i] = NULL; 
} 
 
CString CSecretKeyEdit::CharToCString(char *ch, int n/*char数组的大小*/) 
{	////字符数组转到字符串 
	CString str; 
	char * pbuf = new char[n + 1]; 
	pbuf[n] = NULL; 
 
	for( int i = 0;i <  n;i++) 
		pbuf[i] = ch[i]; 
	str = pbuf; 
	delete[] pbuf; 
	return str; 
} 
 
 
BOOL CSecretKeyEdit::CreatePublicKey(CString fileName)	//生成公钥 
{ 
	SecretKey secretKey; 
 
	CFile file; 
	if(!file.Open( 
		fileName, 
		CFile::modeReadWrite | CFile::typeBinary)) 
		return FALSE; 
	if(file.GetLength() != sizeof(SecretKey)) 
		return FALSE; 
	file.SeekToBegin(); 
	file.Read(&secretKey, sizeof(SecretKey)); 
	file.Close(); 
 
	//私钥文件名要转换成对应的公钥文件名 
	fileName.SetAt( 
		fileName.GetLength() - 2, 
		'p'); 
 
	//把密钥信息写入文件,公钥文件 
	char chTemp[2048 / 8]; 
	for(int i = 0;i < (2048 / 8);i++) 
	{ 
		chTemp[i] = 0; 
	} 
	::MoveMemory( 
		(char *)&secretKey.sk,	//目标 
		chTemp,	//源内容 
		2048 / 8); 
	secretKey.privateOrPublic = SECRETKEY_PUBLIC; 
 
	//查看文件是否存在 
	WIN32_FIND_DATA wfd; 
	HANDLE hSearch = ::FindFirstFile( 
		fileName,//密钥的文件全路径 
		&wfd); 
	if( hSearch != INVALID_HANDLE_VALUE) //文件存在 
	{ 
		//提示文件存在并退出 
		if(MessageBox( 
			"文件已经存在。覆盖 " + fileName + " 文件吗?", 
			"生成公钥文件", 
			MB_YESNO | MB_ICONQUESTION) == IDNO) 
		{ 
			return FALSE; 
		} 
 
	} 
	file.Open( 
		fileName,//密钥的文件全路径 
		CFile::modeCreate | CFile::modeReadWrite | CFile::typeBinary); 
	file.Write( 
		&secretKey, 
		sizeof(SecretKey));	//写入信息 
	file.Close(); 
 
	return TRUE; 
}