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

📄 signdlg.cpp

📁 该程序能实现将数字签名嵌入到BMP图片中形成数字印章
💻 CPP
字号:
// SignDlg.cpp : implementation file
//

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

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

/////////////////////////////////////////////////////////////////////////////
// CSignDlg dialog


CSignDlg::CSignDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSignDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSignDlg)
	m_file_sign = _T("");
	m_pkey_sign = _T("");
	m_signed_sign = _T("");
	m_state_sign = _T("");
	//}}AFX_DATA_INIT

	m_alg_id_sign=CALG_RC4;
	m_hash_sign=CALG_MD5;
	m_prov_sign=PROV_RSA_FULL;
}


void CSignDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSignDlg)
	DDX_Text(pDX, IDC_FILE_SIGN_EDIT, m_file_sign);
	DDX_Text(pDX, IDC_PKEY_SIGN_EDIT, m_pkey_sign);
	DDX_Text(pDX, IDC_SIGNED_SIGN_EDIT3, m_signed_sign);
	DDX_Text(pDX, IDC_STATE_SIGN_STATIC, m_state_sign);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CSignDlg, CDialog)
	//{{AFX_MSG_MAP(CSignDlg)
	ON_BN_CLICKED(IDC_PUBKEY_SIGN_BUTTON, OnPubkeySignButton)
	ON_BN_CLICKED(IDC_SIGNED_FILE_BUTTON, OnSignedFileButton)
	ON_BN_CLICKED(IDC_SIGN_BUTTON, OnSignButton)
	ON_BN_CLICKED(IDC_FILE_SIGN_BUTTON, OnFileSignButton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSignDlg message handlers

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


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

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

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

void CSignDlg::OnSignButton() 
{
	// TODO: Add your control notification handler code here
	HCRYPTPROV hProv;//秘钥容器句柄 
	BYTE *pbBuffer;//被签名的数据

	HCRYPTHASH hHash;
	HCRYPTKEY hKey;
	BYTE *pbKeyBlob;			//签名者得公钥数据
	BYTE *pbSignature;			//数字签名
	DWORD dwSigLen;
	DWORD dwBlobLen;
	DWORD dwBufferLen;
	LPTSTR szDescription = ""; 

	CFile m_pubkey_file,m_sign_file,m_signdatafile;

	if(m_pkey_sign==""||!m_pubkey_file.Open(m_pkey_sign,CFile::modeCreate|CFile::modeReadWrite))
	{
		MessageBox("请选择正确的保存公钥的文件路径");return;
	}

	if(m_file_sign==""||!m_signdatafile.Open(m_file_sign,CFile::modeReadWrite))
	{
			MessageBox("请选择正确的文件路径");return;
	}

	if(m_signed_sign==""||!m_sign_file.Open(m_signed_sign,CFile::modeCreate|CFile::modeReadWrite))
	{
			MessageBox("请选择正确保存数字签名的文件路径");return;
	}

	UpdateData(TRUE);
	m_state_sign="";


	//获取缺省的秘钥容器
	if(CryptAcquireContext(
		&hProv, 
		NULL, 
		NULL, 
		m_prov_sign,
		0))
	{
		m_state_sign+="已获取CSP上下文,秘钥生成算法:"+GetProvType(m_prov_sign)+"\n";
	}
	else
		//密钥容器不存在创建之
	{
		if(CryptAcquireContext(
			&hProv, 
			NULL, 
			NULL, 
			m_prov_sign, 
			CRYPT_NEWKEYSET)) 
			m_state_sign+="已创建一个新的密钥容器,秘钥生成算法:"+GetProvType(m_prov_sign)+"\n";
		else
		{	m_state_sign+=MyHandleError("在获取CSP时发生错误,程序停止.");UpdateData(FALSE);return;}
	}

	//--------------------------------------------------------------------
	// 从密钥容器中取数字签名用的密钥
	if(CryptGetUserKey(   
		hProv,    
		AT_SIGNATURE,    
		&hKey)) 
		m_state_sign+="签名密钥已经获取. \n";
	else
	{
		if(GetLastError() == NTE_NO_KEY) //密钥容器里不存在signature key pair创建之
		{
			if(CryptGenKey(
				hProv,			//CSP句柄
				AT_SIGNATURE,	//创建的密钥对类型为signature key pair
				0,		//key类型,这里用默认值
				&hKey)) 		//创建成功返回新创建的密钥对的句柄
				m_state_sign+="创建一个秘钥对\n";
			else
			{	m_state_sign+=MyHandleError("在创建签名密钥对时发生错误,程序停止.\n"); UpdateData(FALSE);return;}
			
		}
		else
		{
			m_state_sign+=MyHandleError("在获取签名密钥时发生错误,程序停止.");UpdateData(FALSE);return;
		}
	}

	//--------------------------------------------------------------------
	// 因为接收消息者要验证数字签名,所以要导出公钥给接收者。
	if(CryptExportKey(   
		hKey,    
		NULL,    
		PUBLICKEYBLOB,
		0,    
		NULL, 
		&dwBlobLen)) //得到公钥的大小
		m_state_sign+="已获取公钥的大小,";
	else
	{	m_state_sign+=MyHandleError("计算公钥大小时发生错误,程序停止.");UpdateData(FALSE);return;}


	//--------------------------------------------------------------------
	// 为存储公钥的缓冲区分配内存。
	if((pbKeyBlob = (BYTE*)malloc(dwBlobLen))) 
		m_state_sign+="已为公钥分配内存\n";
	else
	{	m_state_sign+=MyHandleError("为公钥分配内存时出现异常,退出. \n");UpdateData(FALSE);return;}

	//--------------------------------------------------------------------
	// 真正导出公钥数据
	if(CryptExportKey(   
		hKey, 
		NULL,    
		PUBLICKEYBLOB,    
		0,    
		pbKeyBlob,    //公钥  这个数据可以存入文件,发送给接收者。一般被存入数字证书
		&dwBlobLen))
	{
		m_pubkey_file.Write(pbKeyBlob,dwBlobLen);
		m_state_sign+="已导出公钥,存储在"+m_pubkey_file.GetFilePath()+"\n";
	}
	else
	{
		m_state_sign+=MyHandleError("导出公钥时发生错误,退出");UpdateData(FALSE);return;
	}


	//--------------------------------------------------------------------
	// 创建hash对象
	if(CryptCreateHash(
		hProv, 
		m_hash_sign,//CALG_MD5, 
		0, 
		0, 
		&hHash)) 
	{
		m_state_sign+="已创建hash对象,加密算法"+GetHashType(m_hash_sign)+"\n\n";
	}
	else
	{	m_state_sign+=MyHandleError("在创建hash对象时发生错误,退出");UpdateData(FALSE);return;}

	//--------------------------------------------------------------------
	
		//把签名的数据读入内存
	//分配空间

	if((pbBuffer=(BYTE *)malloc(m_signdatafile.GetLength())))
		m_state_sign+="已经为数据"+m_signdatafile.GetFilePath()+"分配空间\n\n";
	else
	{   m_state_sign+=MyHandleError("为数据分配内存时发生异常,退出");UpdateData(FALSE);return;}

	if(m_signdatafile.Read(pbBuffer,m_signdatafile.GetLength()))//把数据读入内存
		m_state_sign+="数据已经读入内存!";
	else {m_state_sign+=MyHandleError("数据读入内存发生错误,退出");UpdateData(FALSE);return;}

	dwBufferLen = m_signdatafile.GetLength();
	
	// 对数据进行hash运算
	if(CryptHashData(
		hHash, 
		pbBuffer, 
		dwBufferLen, 
		0)) 
		m_state_sign+="已对数据进行hash运算\n";
	else
	{	m_state_sign+=MyHandleError("在对数据进行hash运算时发生错误,退出.");UpdateData(FALSE);return;}


	//--------------------------------------------------------------------
	// 使用signature key pair的私钥对hash数据签名

	dwSigLen= 0;
	if(CryptSignHash(
		hHash, 
		AT_SIGNATURE, 
		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);
}

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;
}

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

⌨️ 快捷键说明

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