📄 signdlg.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_letter_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_LETTER_SIGN_EDIT, m_letter_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_FILE_SIGN_BUTTON, OnFileSignButton)
ON_BN_CLICKED(IDC_PUBKEY_SIGN_BUTTON, OnPubkeySignButton)
ON_BN_CLICKED(IDC_SIGNED_FILE_BUTTON, OnSignedFileButton)
ON_BN_CLICKED(IDC_LETTER_SIGN_BUTTON, OnLetterSignButton)
ON_BN_CLICKED(IDC_SIGN_BUTTON, OnSignButton)
ON_BN_CLICKED(IDC_LETTER_BUTTON, OnLetterButton)
ON_BN_CLICKED(IDC_SET_SIGN_BUTTON, OnSetSignButton)
//}}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::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);
}
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::OnLetterSignButton()
{
// TODO: Add your control notification handler code here
CFileDialog dlg(FALSE,NULL,".\\数字信封",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,NULL,NULL);
if(dlg.DoModal()==IDOK)
{
m_letter_sign=dlg.GetPathName();
}
else m_letter_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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -