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

📄 veridlg.cpp

📁 实现文件加密解密与数字签名,主要采用RES,AES算法
💻 CPP
字号:
// VeriDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PKI.h"
#include "PKIDlg.h"
#include "VeriDlg.h"
#include "SetDlg.h"
#include <stdio.h>
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>

#define ENCRYPT_BLOCK_SIZE 8 

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CVeriDlg dialog


CVeriDlg::CVeriDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CVeriDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CVeriDlg)
	m_file_veri = _T("");
	m_letter_veri = _T("");
	m_pkey_veri = _T("");
	m_signed_veri = _T("");
	m_state_veri = _T("");
	//}}AFX_DATA_INIT

	m_alg_id_veri=CALG_RC4;
	m_hash_veri=CALG_MD5;
	m_prov_veri=PROV_RSA_FULL;
}


void CVeriDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CVeriDlg)
	DDX_Text(pDX, IDC_FILE_VERI_EDIT, m_file_veri);
	DDX_Text(pDX, IDC_LETTER_VERI_EDIT, m_letter_veri);
	DDX_Text(pDX, IDC_PKEY_VERI_EDIT, m_pkey_veri);
	DDX_Text(pDX, IDC_SIGNED_VERI_EDIT, m_signed_veri);
	DDX_Text(pDX, IDC_STATE_VERY_STATIC, m_state_veri);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CVeriDlg, CDialog)
	//{{AFX_MSG_MAP(CVeriDlg)
	ON_BN_CLICKED(IDC_VERI_BUTTON, OnVeriButton)
	ON_BN_CLICKED(IDC_LETTER_VERI_BUTTON, OnLetterVeriButton)
	ON_BN_CLICKED(IDC_PUB_KEY_VERI_BUTTON, OnPubKeyVeriButton)
	ON_BN_CLICKED(IDC_SIGN_FILE_VERI_BUTTON, OnSignFileVeriButton)
	ON_BN_CLICKED(IDC_FILE_VERI_BUTTON, OnFileVeriButton)
	ON_BN_CLICKED(IDC_YUANWEN_FILE_BUTTON, OnYuanwenFileButton)
	ON_BN_CLICKED(IDC_LET_BUTTON, OnLetButton)
	ON_BN_CLICKED(IDC_SET_VERI_BUTTON, OnSetVeriButton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVeriDlg message handlers

CString MyHandleError2(char *s)
{
	CString str;
	str.Format("程序运行时发生错误. \n错误代码: %x.\n", GetLastError());
	str+=s;
	AfxMessageBox(str);
	return str;
}

void CVeriDlg::OnVeriButton() 
{
	// TODO: Add your control notification handler code her

	
	HCRYPTPROV hProv;
	HCRYPTKEY hPubKey;
	BYTE *pbKeyBlob;
	DWORD dwBlobLen;
	HCRYPTHASH hHash;
	BYTE *pbSignature;			//数字签名
	DWORD dwSigLen;
	LPTSTR szDescription = "";

	UpdateData(TRUE);
	m_state_veri="";
	//--------------------------------------------------------------------
	// 获得CSP句柄,密钥容器名为登陆用户名
	if(CryptAcquireContext(
		&hProv, 
		NULL, 
		NULL, 
		PROV_RSA_FULL, 
		0))
	{
		m_state_veri+="已获取CSP,秘钥生成算法:"+GetProvType(m_prov_veri)+"\n";
	}
	else
		//密钥容器不存在创建之
	{
		if(CryptAcquireContext(
			&hProv, 
			NULL, 
			NULL, 
			PROV_RSA_FULL, 
			CRYPT_NEWKEYSET)) 
			m_state_veri+="已创建一个新的密钥容器秘钥生成算法:"+GetProvType(m_prov_veri)+"\n";
		else
		{	m_state_veri+=MyHandleError2("在获取密钥容器时发生错误,退出\n");UpdateData(FALSE);return;}
	}




	CFile signdatafile,yuanwenfile,pubkeyfile;
	if(m_pkey_veri==""||!pubkeyfile.Open(m_pkey_veri,CFile::modeReadWrite))
	{
		MessageBox("请选择正确的公钥文件!");return;
	}
	if(m_file_veri==""||!yuanwenfile.Open(m_file_veri,CFile::modeReadWrite))
	{
		MessageBox("请选择正确的原文件!");return;
	}	
	if(m_signed_veri==""||!signdatafile.Open(m_signed_veri,CFile::modeReadWrite))
	{
		MessageBox("请选择正确的签名文件!");return;
	}


	dwBlobLen=pubkeyfile.GetLength();
	
	pbKeyBlob=(BYTE *)malloc(dwBlobLen);
	pubkeyfile.Read(pbKeyBlob,dwBlobLen);


	if(CryptImportKey(
		hProv,
		pbKeyBlob,
		dwBlobLen,
		0,
		0,
		&hPubKey))
		m_state_veri+="公钥已经成功导入!\n\n";
	else
	{
		m_state_veri+=MyHandleError2("公钥导出出错.\n");UpdateData(FALSE);return;
	}

	//--------------------------------------------------------------------
	// 创建哈希对象
	if(CryptCreateHash(
		hProv, 
		m_hash_veri,//CALG_MD5, 
		0, 
		0, 
		&hHash)) 
		m_state_veri+="已经获取hash对象,hash算法"+GetHashType(m_hash_veri)+"\n\n";
	else
	{
		m_state_veri+=MyHandleError2("创建hash对象时出错,退出");UpdateData(FALSE);return;
	}

	//--------------------------------------------------------------------
	// 跟生成时一样对数据进行hash运算
	BYTE *pbBuffer;

	pbBuffer=(BYTE *)malloc(yuanwenfile.GetLength());
	yuanwenfile.Read(pbBuffer,yuanwenfile.GetLength());

	

	DWORD dwBufferLen = yuanwenfile.GetLength();

	
	pbSignature=(BYTE *)malloc(signdatafile.GetLength());
	signdatafile.Read(pbSignature,signdatafile.GetLength());

	dwSigLen = signdatafile.GetLength();
	if(CryptHashData(
		hHash, 
		pbBuffer, 
		dwBufferLen, 
		0)) 
		m_state_veri+="对数据hash运算成功!\n\n";
	else
	{
		m_state_veri+=MyHandleError2("对数据进行hash运算出错,退出");UpdateData(FALSE);return;
	}

	//--------------------------------------------------------------------
	// 验证数字签名
	if(CryptVerifySignature(
		hHash, 
		pbSignature,	//数字签名数据
		dwSigLen, 
		hPubKey,		//签名者的公钥
		szDescription, 
		0)) 
	{
		MessageBox("恭喜:是正确的数字签名!");
		m_state_veri+="恭喜:是正确的数字签名!";
	}
	else
	{
		MessageBox("错误:签名是错误的\n");
		m_state_veri+="错误:签名是错误的\n请检查参数是否设置正确,若正确则请联系发送方";
	}


	UpdateData(FALSE);
	//--------------------------------------------------------------------
	// Free memory to be used to store signature.
	if(pbSignature)
		free(pbSignature);

	if(pbKeyBlob)
		free(pbKeyBlob);
	
	//--------------------------------------------------------------------
	// Destroy the hash object.
	if(hHash) 
		CryptDestroyHash(hHash);
	
	//--------------------------------------------------------------------
	// Release the provider handle.
	if(hProv) 
		CryptReleaseContext(hProv, 0);
	signdatafile.Close(),yuanwenfile.Close(),pubkeyfile.Close();
}

void CVeriDlg::OnLetterVeriButton() 
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(TRUE,NULL,".\\数字信封",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);
	if(dlg.DoModal()==IDOK)
	{
		m_letter_veri=dlg.GetPathName();
	}
	else m_letter_veri="";
	UpdateData(FALSE);
}

void CVeriDlg::OnPubKeyVeriButton() 
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(TRUE,NULL,".\\公钥",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);
	if(dlg.DoModal()==IDOK)
	{
		m_pkey_veri=dlg.GetPathName();
	}
	else m_pkey_veri="";
	UpdateData(FALSE);
}

void CVeriDlg::OnSignFileVeriButton() 
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(TRUE,NULL,".\\签名后的文件",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);
	if(dlg.DoModal()==IDOK)
	{
		m_signed_veri=dlg.GetPathName();
	}
	else m_signed_veri="";
	UpdateData(FALSE);
}

void CVeriDlg::OnFileVeriButton() 
{
	// TODO: Add your control notification handler code here
	
}

void CVeriDlg::OnYuanwenFileButton() 
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(FALSE,NULL,".\\原文.txt",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);
	if(dlg.DoModal()==IDOK)
	{
		m_file_veri=dlg.GetPathName();
	}
	else m_file_veri="";
	UpdateData(FALSE);
}

void CVeriDlg::OnLetButton() 
{
	// 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 letterfile,file;

	UpdateData(TRUE);
	if(m_letter_veri==""||!letterfile.Open(m_letter_veri,CFile::modeReadWrite))
	{
		MessageBox("请选择正确的数字信封!");return;
	}
	if(m_file_veri==""||!file.Open(m_file_veri,CFile::modeCreate|CFile::modeReadWrite))
	{
		MessageBox("请选择正确的保存文件地址!");return;
	}

	letterfile.Close();
	file.Close();
	m_state_veri="";
	char *yuanwen,*letter;
	int len=m_file_veri.GetLength();
	int len2=m_letter_veri.GetLength();
	yuanwen=(char *)malloc(len+1);
	letter=(char *)malloc(len2+1);
	for(int i=0;i<len;i++)
		*(yuanwen+i)=m_file_veri[i];
	for(i=0;i<len2;i++)
		*(letter+i)=m_letter_veri[i];
	*(yuanwen+len)='\0';
	*(letter+len2)='\0';

	hSource = fopen(letter,"rb");// 打开源文件.
	hDestination = fopen(yuanwen,"wb") ;

	
	if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))
		m_state_veri+="已经获取CSP,秘钥生成算法:"+GetProvType(m_prov_veri)+"\n\n";

	// 读隐码的长度并分配内存
	if(fread(&dwKeyBlobLen, sizeof(DWORD), 1, hSource))
		m_state_veri+="已经计算出会话密钥的长度!\n\n";
	else
	{	m_state_veri+="计算会话密钥长度出错,退出\n\n";UpdateData(FALSE);return;}
	if(pbKeyBlob =(BYTE *) malloc(dwKeyBlobLen))
		m_state_veri+="为会话密钥分配内存\n";
	else{ m_state_veri+="为会话密钥分配内存失败,退出\n\n";UpdateData(FALSE);return;}

	// 从源文件中读隐码.
	if(fread(pbKeyBlob, 1, dwKeyBlobLen, hSource))
		m_state_veri+="已经读入会话密钥!\n\n";
	else
	{	m_state_veri+="已经读入会话密钥!失败,退出\n\n";UpdateData(FALSE);return;}

	// 将隐码输入CSP
	if(CryptImportKey(hProv, pbKeyBlob, dwKeyBlobLen, 0, 0, &hKey))
		m_state_veri+="已经把会话密钥导入CSP\n\n";
	else 
	{	m_state_veri+="会话密钥导入CSP失败,退出\n\n";UpdateData(FALSE);return;}
		


	dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
	if(ENCRYPT_BLOCK_SIZE  > 1) 
	{
		dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
	} 
	else
	{
		dwBufferLen = dwBlockLen;
	}

	pbBuffer =(BYTE *)malloc(dwBufferLen);

	//解密源文件并写入目标文件
	do {
		dwCount = fread(pbBuffer, 1, dwBlockLen,hSource);
		//dwCount=hs.Read(pbBuffer,dwBlockLen);
		eof = feof(hSource);
		//eof=hs.;
		// 解密数据
		CryptDecrypt(hKey, 0, eof, 0, pbBuffer, &dwCount);
		// 将解密过的数据写入目标文件
		fwrite(pbBuffer, 1, dwCount, hDestination);
		} while(!feof(hSource));
	m_state_veri+="已经解密成功,并且保存在"+m_file_veri+"\n\n";
	fclose(hSource);
	fclose(hDestination);
	MessageBox("解开数字信封成功!");
	UpdateData(FALSE);
	//MessageBox("OK\n");
}

void CVeriDlg::OnSetVeriButton() 
{
	// TODO: Add your control notification handler code here
	CSetDlg dlg;

	GetProvType(m_prov_veri);
	dlg.m_prov=m_prov_type;

	GetHashType(m_hash_veri);
	dlg.m_hash=m_hash_type;

	GetSessionType(m_alg_id_veri);
	dlg.m_alg_id=m_session_type;

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

		switch(dlg.m_hash)
		{
		case 0:
			m_hash_veri=CALG_HMAC;break;
		case 1:
			m_hash_veri=CALG_MAC;break;
		case 2:
			m_hash_veri=CALG_MD2;break;
		case 3:
			m_hash_veri=CALG_MD5;break;
		case 4:
			m_hash_veri=CALG_SHA;break;
		default:m_hash_veri=CALG_MD5;break;
		}

		switch(dlg.m_prov)
		{
		case 0:
			m_prov_veri=PROV_RSA_FULL;break;
		case 1:
			m_prov_veri=PROV_RSA_SIG;break;
		case 2:
			m_prov_veri=PROV_DSS;break;
		case 3:
			m_prov_veri=PROV_DSS_DH;break;
		case 4:
			m_prov_veri=PROV_FORTEZZA;break;
		case 5:
			m_prov_veri=PROV_MS_EXCHANGE;break;
		case 6:
			m_prov_veri=PROV_RSA_SCHANNEL;break;
		case 7:
			m_prov_veri=PROV_SSL;break;
		default:
			m_prov_veri=PROV_RSA_FULL;break;
		}
	}
}


CString CVeriDlg::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 CVeriDlg::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 CVeriDlg::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;
}

void CVeriDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	CPKIDlg dlg;
	dlg.DoModal();
	CDialog::OnCancel();
}

⌨️ 快捷键说明

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