signdlg.cpp

来自「实现文件加密解密与数字签名,主要采用RES,AES算法」· C++ 代码 · 共 624 行 · 第 1/2 页

CPP
624
字号
		szDescription, 
		0, 
		NULL, 
		&dwSigLen)) //得到数字签名大小
		m_state_sign+="已获取数字签名的大小,";
	else
	{	m_state_sign+=MyHandleError("计算数字签名大小时发生错误,退出.");UpdateData(FALSE);return;}


	//--------------------------------------------------------------------
	// 为数字签名缓冲区分配内存
	if((pbSignature = (BYTE *)malloc(dwSigLen)))
		m_state_sign+="已为数字签名分配缓冲\n";
	else
	{	m_state_sign+=MyHandleError("为数字签名分配内存时异常,退出.");UpdateData(FALSE);return;}

	//--------------------------------------------------------------------
	// 得到数字签名
	if(CryptSignHash(
		hHash, 
		AT_SIGNATURE, 
		szDescription, 
		0, 
		pbSignature, //这里将返回数字签名,同被签名的数据一起发送给接收方
		&dwSigLen)) 
	{
		m_sign_file.Write(pbSignature,dwSigLen);
		m_state_sign+="已导出数字签名,存储在"+m_sign_file.GetFilePath()+"\n\n";
	}
	else
	{
		m_state_sign+=MyHandleError("导出数字签名时发生异常,退出.");UpdateData(FALSE);return;
	}

	//--------------------------------------------------------------------
	// 销毁hash对象.
	if(hHash)
	{
		CryptDestroyHash(hHash);
		m_state_sign+="销毁hash对象\n\n";
	}
	m_state_sign+="数字签名成功\n\n";
	//关闭文件
	m_pubkey_file.Close(),m_sign_file.Close(),m_signdatafile.Close();
	MessageBox("数字签名成功!","",MB_OK);
	UpdateData(FALSE);
}

void CSignDlg::OnLetterButton() 
{
	// TODO: Add your control notification handler code here
	FILE *hSource  = NULL;
	FILE *hDestination = NULL;
	INT eof = 0;
	HCRYPTPROV hProv   = 0;
	HCRYPTKEY hKey = 0;
	HCRYPTKEY hXchgKey = 0;
	HCRYPTHASH hHash   = 0;
	PBYTE pbKeyBlob = NULL;
	DWORD dwKeyBlobLen;
	PBYTE pbBuffer = NULL;
	DWORD dwBlockLen;
	DWORD dwBufferLen;
	DWORD dwCount;
	CFile m_letterfile,m_signdatafile;
	CString str;


	UpdateData(TRUE);

	if(m_letter_sign==""||!m_letterfile.Open(m_letter_sign,CFile::modeCreate|CFile::modeReadWrite))
	{
			MessageBox("请选择正确保存数字信封的文件路径");return;
	}
	if(m_file_sign==""||!m_signdatafile.Open(m_file_sign,CFile::modeReadWrite))
	{
			MessageBox("请选择正确的文件路径");return;
	}
	m_letterfile.Close();
	m_signdatafile.Close();
	m_state_sign="";

	char *yuanwen,*letter;
	int len=m_file_sign.GetLength();
	int len2=m_letter_sign.GetLength();
	yuanwen=(char *)malloc(len+1);
	letter=(char *)malloc(len2+1);
	for(int i=0;i<len;i++)
		*(yuanwen+i)=m_file_sign[i];
	for(i=0;i<len2;i++)
		*(letter+i)=m_letter_sign[i];
	*(yuanwen+len)='\0';
	*(letter+len2)='\0';
	hSource = fopen(yuanwen,"rb");// 打开源文件.
	hDestination = fopen(letter,"wb") ;
	//.打开目标文件
   // 连接缺省的CSP
	if(CryptAcquireContext(&hProv, NULL, NULL, m_prov_sign, 0))
	{
		m_state_sign+="已经获取csp,秘钥生成算法:"+GetProvType(m_prov_sign)+"\n";
	}
	else{m_state_sign+="获取csp失败,退出";return;}
	
	// 产生随机会话密钥.
	if(CryptGenKey(hProv,m_alg_id_sign,CRYPT_EXPORTABLE, &hKey))
	{

		m_state_sign+="已经生成随机会话密钥,算法为"+GetSessionType(m_alg_id_sign)+"\n";
	}
	else{m_state_sign+="生成随机会话密钥失败\n";UpdateData(FALSE);return;}

	if(CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey))
		m_state_sign+="获取交换密钥对成功\n";
	else
	{
		if(CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hXchgKey))//创建新的交换密钥对
		{
			m_state_sign+="创建新的交换密钥对\n";
		}
		else 
		{
			m_state_sign+="获取获取交换密钥对失败,退出\n";UpdateData(FALSE);return;
		}
	} 




	// 计算隐码长度并分配缓冲区
	if(CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwKeyBlobLen))
		m_state_sign+="计算隐码长度!";
	else {m_state_sign+="计算隐码长度失败,退出\n";UpdateData(FALSE);return;}
	if(pbKeyBlob =(BYTE *) malloc(dwKeyBlobLen))
		m_state_sign+="为隐码分配内存\n";
	else {	m_state_sign+="为隐码分配内存失败,退出\n";UpdateData(FALSE);return;}

	// 将会话密钥输出至隐码
	if(CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwKeyBlobLen))
		m_state_sign+="会话密钥输出至隐码!\n";
	else {m_state_sign+="会话密钥输出至隐码失败,退出\n";UpdateData(FALSE);return;}

	// 释放密钥交换对的句柄
	CryptDestroyKey(hXchgKey);
	hXchgKey = 0;
	// 将隐码长度写入目标文件
	if(fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination))
		m_state_sign+="隐码长度写入目标文件\n";
	else{ m_state_sign+="隐码长度写入目标文件失败,退出\n";UpdateData(FALSE);return;}
	//将隐码长度写入目标文件
	if(fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination))
		m_state_sign+="隐码写入目标文件\n";
	else {m_state_sign+="隐码写入目标文件失败,退出\n";UpdateData(FALSE);return;}


	//计算一次加密的数据字节数,必须为ENCRYPT_BLOCK_SIZE的整数倍
	dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
	//如果使用块编码,则需要额外空间
	if(ENCRYPT_BLOCK_SIZE  > 1) {
		dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
	} else {
		dwBufferLen = dwBlockLen;
	}
	//分配缓冲区
	if(pbBuffer =(BYTE *) malloc(dwBufferLen))
		m_state_sign+="加密的数据分配缓冲区!\n";
	else{ m_state_sign+="加密的数据分配缓冲区失败,退出\n";UpdateData(FALSE);return;}
	//加密源文件并写入目标文件
	do {
		// 从源文件中读出dwBlockLen个字节
		dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
		eof = feof(hSource);
		//加密数据
		CryptEncrypt(hKey, 0, eof, 0, pbBuffer, &dwCount, dwBufferLen);
		// 将加密过的数据写入目标文件
		fwrite(pbBuffer, 1, dwCount, hDestination);
	} while(!feof(hSource));

	//关闭文件
	fclose(hSource);
	fclose(hDestination);
	m_state_sign+="生成数字信封成功!\nOK!";
	MessageBox("生成数字信封成功!");
	UpdateData(FALSE);
}


void CSignDlg::OnSetSignButton() 
{
	// TODO: Add your control notification handler code here
	CSetDlg dlg;
	//dlg.m_alg_id=m_alg_id_sign;
	GetProvType(m_prov_sign);
	dlg.m_prov=m_prov_type;

	GetHashType(m_hash_sign);
	dlg.m_hash=m_hash_type;

	GetSessionType(m_alg_id_sign);
	dlg.m_alg_id=m_session_type;

	if(IDOK==dlg.DoModal())
	{
		switch(dlg.m_alg_id)
		{
		case 0:
			m_alg_id_sign=CALG_RC2;break;
		case 1:
			m_alg_id_sign=CALG_RC4;break;
		default:m_alg_id_sign=CALG_RC2;break;
		}

		switch(dlg.m_hash)
		{
		case 0:
			m_hash_sign=CALG_HMAC;break;
		case 1:
			m_hash_sign=CALG_MAC;break;
		case 2:
			m_hash_sign=CALG_MD2;break;
		case 3:
			m_hash_sign=CALG_MD5;break;
		case 4:
			m_hash_sign=CALG_SHA;break;
		default:m_hash_sign=CALG_MD5;break;
		}
		switch(dlg.m_prov)
		{
		case 0:
			m_prov_sign=PROV_RSA_FULL;break;
		case 1:
			m_prov_sign=PROV_RSA_SIG;break;
		case 2:
			m_prov_sign=PROV_DSS;break;
		case 3:
			m_prov_sign=PROV_DSS_DH;break;
		case 4:
			m_prov_sign=PROV_FORTEZZA;break;
		case 5:
			m_prov_sign=PROV_MS_EXCHANGE;break;
		case 6:
			m_prov_sign=PROV_RSA_SCHANNEL;break;
		case 7:
			m_prov_sign=PROV_SSL;break;
		default:
			m_prov_sign=PROV_RSA_FULL;break;
		}
	}
	//dlg.SetAlgID();
}

CString CSignDlg::GetHashType(unsigned int hash)
{

		CString str;
		switch(hash)
		{
		case CALG_HMAC:
			str="HMAC";m_hash_type=0;break;
		case CALG_MAC:
			str="MAC";m_hash_type=1;break;
		case CALG_MD2:
			str="MD2";m_hash_type=2;break;
		case CALG_MD5:
			str="MD5";m_hash_type=3;break;
		case CALG_SHA:
			str="SHA";m_hash_type=4;break;
		default:str="MD5";m_hash_type=3;break;
		}
		return str;
}

CString CSignDlg::GetSessionType(unsigned int session)
{
		CString str;
		switch(session)
		{
		case CALG_RC2:
			str="RC2";m_session_type=0;break;
		case CALG_RC4:
			str="RC4";m_session_type=1;break;
		default:str="RC4";m_session_type=1;break;
		}
		return str;
}

CString CSignDlg::GetProvType(unsigned int prov)
{
		CString str;
		switch(prov)
		{
		case PROV_RSA_FULL:
			m_prov_type=0;str="RSA_FULL";break;
		case PROV_RSA_SIG:
			m_prov_type=1;str="RSA_SIG";break;
		case PROV_DSS:
			m_prov_type=2;str="DSS";break;
		case PROV_DSS_DH:
			m_prov_type=3;str="DSS_DH";break;
		case PROV_FORTEZZA:
			m_prov_type=4;str="FORTEZZA";break;
		case PROV_MS_EXCHANGE:
			m_prov_type=5;str="MS_EXCHANGE";break;
		case PROV_RSA_SCHANNEL:
			m_prov_type=6;str="RSA_SCHANNEL";break;
		case PROV_SSL:
			m_prov_type=7;str="SSL";break;
		default:
			m_prov_type=0;str="RSA_FULL";break;
		}
		return str;
}

⌨️ 快捷键说明

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