DSA数字签名算法
1 引言
为了确保数据传输的安全性,不得不采取一系列的安全技术,如加密技术、数字签名、身份认证、密钥管理、防火墙、安全协议等。其中数字签名就是实现网上交易安全的核心技术之一,它可以保证信息传输的保密性、数据交换的完整性、发送信息的不可否认性、交易者身份的确定性等。DSA(Digital Signature Algorithm,数字签名算法,用作数字签名
的一部分),它是另一种公开密钥算法,它不能用作加密,只用作数字签名。DSA使用公开密钥,为接受者验证数据的完整性和数据发送者的身份。它也可用于由第三方去确定签名和所签数据的真实性。DSA算法的安全性基于解离散对数的困难性,这类签字标准具有较大的兼容性和适用性,成为网络安全体系的基本构件之一。
2. 数字签名
2.1 数字签名的概念
数字签名在ISO7498—2标准中定义为:“附加在数据单元上的一些数据,或是对数据单元所作的密码变换,这种数据和变换允许数据单元的接收者用以确认数据单元来源和数据单元的完整性,并保护数据,防止被人(例如接收者)进行伪造”。
数字签名是通过一个单向函数对要传送的信息进行处理得到的用以认证信息来源并核实信息在传送过程中是否发生变化的一个字母数字串。数字签名提供了对信息来源的确定并能检测信息是否被篡改。
数字签名要实现的功能是我们平常的手写签名要实现功能的扩展。平常在书面文件上签名的主要作用有两点,一是因为对自己的签名本人难以否认,从而确定了文件已被自己签署这一事实;二是因为自己的签名不易被别人模仿,从而确定了文件是真的这一事实。采用数字签名,也能完成这些功能:
(1)确认信息是由签名者发送的;
(2)确认信息自签名后到收到为止,未被修改过;
签名者无法否认信息是由自己发送的。
数字签名和手签的区别是:手签是模拟的,易伪造,而数字签名是基于数学原理的,更难伪造。
数字签名的技术基础是公钥密码技术。密钥必须以某种安全的方式告诉解密方。大家熟悉的DES加密标准就是一种对称加密技术。1976年,Diffie和Hellman在一篇名叫“New Direction in Cryptog raphy(密码学的新方向)”一文中提出了一个新的思想,即:不仅加密算法本身可以公开,就是加密用的密钥本身也可以公开。这就是公钥密码体制。其中使用的密钥被分解为一对:一把公钥和一把私钥。只要私钥保密就可以了,公钥可以发到因特网(如网站的黄页)等公开地方供别人查询和下载。
2.2 数字签名的原理
图1. 数字签名的原理图
处理过程: (采用双重加密)
(1)使用SHA编码将发送文件加密产生128bit的数字摘要;
(2)发送方用自己的专用密钥对摘要再加密,形成数字签名;
(3)将原文和加密的摘要同时传给对方;
(4)接受方用发送方的公共密钥对摘要解密,同时对收到的文件用SHA编码加密产生同一摘要;
(5)将解密后的摘要和收到的文件在接受方重新加密产生的摘要相互对比,如果两者一致,则说明在传送过程中信息没有破坏和篡改。否则,则说明信息已经失去安全性和保密性。
3数字签名的
3.1 RSA数字签名系统
RSA算法中数字签名技术实际上是通过一个哈希函数来实现的。数字签名的特点
是它代
了文件的特征,文件如果发生改变,数字签名的值也将发生变化。不同的文件将得到不同的数字签名。
用RSA或其它公开密钥密码算法的最大方便是没有密钥分配问题。因为公开密钥加密使用两个不同的密钥,其中有一个是公开的,另一个是保密的。公开密钥可以保存在系统目录内、未加密的电子邮件信息中、电话黄页(商业电话)上或公告牌里,网上的任何用户都可获得公开密钥。
3.2 Hash签名
Hash签名是最主要的数字签名方法,也称之为数字摘要法(Digital Digest)或数字指纹法(Digital Finger Print)。它与RSA数字签名是单独的签名不同,该数字签名方法是将数字签名与要发送的信息紧密联系在一起,它更适合于电子商务活动。将一个商务
的个体内容与签名结合在一起,比合同和签名分开传递,更增加了可信度和安全性。
一个Hash函数满足:
?H可以作用于一个任意长度的数据块;
?H产生一个固定长度的输出;
?H(x)对任意给定的x计算相对容易,无论是软件还是硬件实现;
?对任意给定码h,找到x满足H(x)=h具有计算不可行性;
x具有计算不可行性; ?对任意给定的数据块x,找到满足H(y)=H(x)的y
?找到任意数据对(x,y),满足H(x) = H(y)是计算不可行的。
用Hash函数实验签名的方案如下:
发送方X:准备消息M,计算其散列码H(M),用X的私钥对散列值构成签名Kx-1[H(M)],并将消息M及签名Kx-1 [H(M)]发送给Y
接收方Y:对收到的消息M′计算用H(M′),利用公钥解密Kx-1[H(M)],然后比较Kx [Kx-1 [H(M)]]和H(M′),如果Kx [Kx-1 [H(M)]] , H(M′),则签名得到验证。 3.3 椭圆曲线数字签名算法(ECDSA)
椭圆曲线的数字签名具有与RSA数字签名和DSA数字签名基本上相同的功能,但实施起来更有效,因为椭圆曲线数字签名在生成签名和进行验证时要必RSA和DSA来得快。
椭圆曲线数字签名的速度要比RSA、DSA快,还可以用在一些较小、对资源有一定限制得设备如智能卡(含有微处理器芯片得塑料片)中。
3.4 美国数字签名标准(DSA)
数字签名算法(Digital Signature Algorithm,DSA)是Schnorr和ElGamal签名算法的变种,由美国国家标准化技术研究院(NIST)和国家安全局共同开发。DSA是基于离散对数的难度。
4 基于DSA数字签名的实现方法
建立在公钥密码技术上的数字签名方法有很多,有RSA签名、DSA签名和椭圆曲线数字签名算法(ECDSA)等等。下面对DSA签名进行详细分析。
(1)DSA算法参数说明
DSA算法中应用了下述参数:
p:L bits长的素数。L是64的倍数,范围是512到1024;
q:p - 1的160bits的素因子;
g:g = hp-1 mod p,h满足h < p - 1, h(p-1)/q mod p > 1;
x:1
LoadIcon(IDR_MAINFRAME);
//}}AFX_MSG }
DECLARE_MESSAGE_MAP()
void {
DMyDlg::DoDataExchange(CDataExchange* CDialog::OnInitDialog(); pDX)
{ // Add "About..." menu item to
CDialog::DoDataExchange(pDX); system menu.
//{{AFX_DATA_MAP(DMyDlg)
DDX_Text(pDX, IDC_P, m_P); // IDM_ABOUTBOX must be in the
DDX_Text(pDX, IDC_Q, m_Q); system command range.
DDX_Text(pDX, IDC_G, m_G); ASSERT((IDM_ABOUTBOX & 0xFFF0) ==
// mpdified in 2007.6.10 IDM_ABOUTBOX);
DDX_Text(pDX, IDC_Y, m_Y); ASSERT(IDM_ABOUTBOX < 0xF000);
DDX_Text(pDX, IDC_S, m_S);
DDX_Text(pDX, IDC_V, m_V); CMenu* pSysMenu =
DDX_CBIndex(pDX, IDC_COMBO, GetSystemMenu(FALSE);
m_Len); if (pSysMenu != NULL)
DDX_Text(pDX, IDC_OUTPUT, m_OUT); {
DDX_Text(pDX, IDC_INPUT, m_IN); CString strAboutMenu;
DDX_Text(pDX, IDC_EDITFILE,
m_file); strAboutMenu.LoadString(IDS_ABOUT
DDX_Text(pDX, IDC_STRING, BOX);
m_string); if (!strAboutMenu.IsEmpty())
//}}AFX_DATA_MAP {
}
pSysMenu->AppendMenu(MF_SEPARATORBEGIN_MESSAGE_MAP(DMyDlg, CDialog) );
//{{AFX_MSG_MAP(DMyDlg)
ON_WM_SYSCOMMAND() pSysMenu->AppendMenu(MF_STRING,
ON_WM_PAINT() IDM_ABOUTBOX, strAboutMenu);
ON_WM_QUERYDRAGICON() }
ON_BN_CLICKED(IDC_BUTTON_GET, }
OnButtonGet)
ON_BN_CLICKED(IDC_ENCRYPT, // Set the icon for this dialog. OnEncrypt) The framework does this automatically
ON_BN_CLICKED(IDC_DECRYPT, // when the application's main OnDecrypt) window is not a dialog
ON_BN_CLICKED(IDC_Btnfile, SetIcon(m_hIcon, TRUE); OnBtnfile) // Set big icon
ON_EN_CHANGE(IDC_EDITFILE, SetIcon(m_hIcon, FALSE); OnChangeEditfile) // Set small icon
ON_EN_CHANGE(IDC_STRING,
OnChangeString) // TODO: Add extra initialization
ON_BN_CLICKED(IDC_SHA1_RADIO, here
OnSha1Radio)
ON_BN_CLICKED(IDC_MD5_RADIO, CheckRadioButton(IDC_MD5_RADIO,IDOnMd5Radio) C_SHA1_RADIO,IDC_MD5_RADIO);
ON_CBN_EDITCHANGE(IDC_COMBO, UpdateData(FALSE);
OnEditchangeCombo)
ON_BN_CLICKED(IDC_BUTTON1, return TRUE; // return TRUE OnButton1) unless you set the focus to a control
//}}AFX_MSG_MAP }
END_MESSAGE_MAP()
void DMyDlg::OnSysCommand(UINT nID, /////////////////////////////////////LPARAM lParam)
/////////////////////////////////////{
/// if ((nID & 0xFFF0) == IDM_ABOUTBOX) // DMyDlg message handlers {
CAboutDlg dlgAbout;
BOOL DMyDlg::OnInitDialog() dlgAbout.DoModal();
} // TODO: Add your control
else notification handler code here
{ ready=1;
CDialog::OnSysCommand(nID, UpdateData(TRUE);
lParam); CTime t0=CTime::GetCurrentTime();
} /*
} int len=8; //int len=2; modified
in 2007 6. 9
// If you add a minimize button to your for(int i=0;i256)
w.Mov(w.Add(v[k])); {
r.Mov(r.Mul(t)); m_OUT=_T("N不得大于256位");
} UpdateData(FALSE);
s.Mov(pow2(2,b)); return;
v[k].Mov(v[k].Mod(s)); }
v[k].Mov(v[k].Mul(r)); K.Mov(makerandnumber(160));
w.Mov(w.Add(v[k])); R.Mov(G.RsaTrans(K,P));
r.Mov(w); R.Mov(R.Mod(Q));
r.Mov(r.Add(1)); S.Mov(K.Euc(Q));
w.Mov(w.Mod(q)); g.Get(m_IN);
r.Mov(r.Sub(w)); t.Mov(X.Mul(R));
p.Mov(r); t.Mov(t.Mod(Q));
while (p.Rab()==0) t.Mov(t.Add(g));
{ S.Mov(S.Mul(t));
S.Mov(S.Mod(Q)); C=C+1;
R.Put(m_OUT); N=N+n+1;
S.Put(m_S); if (C==4096) break;
/* p.Mov(p.Add(q)); for(int
p.Mov(p.Add(q)); i=0;i'9')&&(m_IN[i]<'A'))||
Q.Mov(q);
H.Mov(makerandnumber(g)); ((m_IN[i]>'F')&&(m_IN[i]<'a'))||
X.Mov(makerandnumber(g)); (m_IN[i]>'f'))
X.Mov(X.Mod(Q)); {
t.Mov(P.Sub(1)); m_OUT=_T("待加密数据必须
t.Mov(t.Div(Q)); 为0-9或A-F或a-f组成的整数");
G.Mov(H.RsaTrans(t, Q)); UpdateData(FALSE);
Y.Mov(G.RsaTrans(X, P)); return;
P.Put(m_P); }
Q.Put(m_Q); }*/
G.Put(m_G); // P.Get(m_IN);
Y.Put(m_Y); // if(P.Cmp(N)>=0) // m_D="10001"; // {
CTime t1=CTime::GetCurrentTime(); // m_OUT=_T("待加密数据必须小于
CTimeSpan t2=t1-t0; N");
m_OUT.Format("%d",t2.GetTotalSeco// UpdateData(FALSE); nds()); // return;
m_OUT+=" 秒"; // }
UpdateData(FALSE); // Q.Mov(P.RsaTrans(E,N)); } // Q.Put(m_OUT);
UpdateData(FALSE); void DMyDlg::OnEncrypt() }
{
// TODO: Add your control void DMyDlg::OnDecrypt() notification handler code here {
CBigInt g,t; CBigInt W,U1,U2,t;
if(ready==0) // TODO: Add your control
notification handler code here {
if((ready==0)||(Q.m_ulValue[0]==0int i,x,y;
))
{ for (i = 0;i < hashlen; i++)
m_OUT=_T("请先进行数字签名"); {
UpdateData(FALSE); y = hash[i] >> 4;
return;
} y += 0x30;
W.Mov(S.Euc(Q)); if (y > 0x39) y+= 0x07;
U1.Get(m_IN);
U1.Mov(U1.Mul(W)); x = hash[i] & 0x0F;
U1.Mov(U1.Mod(Q));
U2.Mov(R.Mul(W)); x += 0x30;
U2.Mov(U2.Mod(Q)); if (x > 0x39) x+= 0x07;
V.Mov(G.RsaTrans(U1,P));
V.Mov(V.Mod(P)); out[i << 1] = y;
t.Mov(Y.RsaTrans(U2,P)); out[(i << 1)+1] = x;
t.Mov(t.Mod(P)); }
V.Mov(V.Mul(t));
V.Mov(V.Mod(P)); out[hashlen << 1] = 0x00;
V.Mov(V.Mod(Q));
if (V.Cmp(R)==0) V.Put(m_V); }
R.Put(m_V);
void DMyDlg::OnChangeEditfile()
{
// Q.Get(m_OUT); // TODO: If this is a RICHEDIT // P.Mov(Q.RsaTrans(D,N)); control, the control will not // P.Put(m_OUT); // send this notification unless you
UpdateData(FALSE); override the CDialog::OnInitDialog() } // function and call
CRichEditCtrl().SetEventMask() void DMyDlg::OnBtnfile() // with the ENM_CHANGE flag ORed { into the mask.
// TODO: Add your control
notification handler code here // TODO: Add your control
CFileDialog m_FileOpen(TRUE); notification handler code here //设置打开窗体的标题 UpdateData(TRUE);
m_FileOpen.m_ofn.lpstrTitle = _T(" CString open=m_file; 打开文件"); MD5_CTX md5_ctx;
m_FileOpen.m_ofn.lpstrFilter = SHA1_CTX sha1_ctx; _T("文件 (*.*)\0*.*\0\0");
//点击浏览按钮 int hashradio;
if(IDOK == m_FileOpen.DoModal())
{ hashradio=GetCheckedRadioButton(I
//获取打开的文件路径 DC_MD5_RADIO,IDC_SHA1_RADIO);
CString m_FileName = if(hashradio==IDC_MD5_RADIO) m_FileOpen.GetPathName(); //MD5
CEdit* pEdit = {
(CEdit*)(GetDlgItem(IDC_EDITFILE)); int i;
//将选择的文件路径名显示到 unsigned char
IDC_EDITFILE表识的EDIT中 digest[16],output[16];
FILE* file;
pEdit->SetWindowText(m_FileName); unsigned char buffer[16384];
} MD5Init(&md5_ctx); } file = fopen(open, "rb");
i = fread(buffer, 1, 16384, void byte2strhash(unsigned char file);
*hash,int hashlen,unsigned char *out) MD5Update(&md5_ctx, buffer,
i); {
MD5Final(digest, &md5_ctx); unsigned char
fclose(file); digest[16],output[16];
UpdateData(TRUE);
byte2strhash(digest,16,output); CString context=m_string;
CString str(output);
SetDlgItemText(IDC_INPUT,str); MD5Init(&md5_ctx);
unsigned char *buf = (unsigned
} char*)context.GetBuffer(context.GetLe
ngth());
else //SHA-1 MD5Update(&md5_ctx,buf,
{ strlen(context));
int i; MD5Final(digest, &md5_ctx);
unsigned char context.ReleaseBuffer(); digest[20],output[20];
FILE* file;
unsigned char buffer[16384]; byte2strhash(digest,16,output);
SHA1Init(&sha1_ctx); CString str(output);
file = fopen(open, "rb");
i = fread(buffer, 1, 16384, SetDlgItemText(IDC_INPUT,str); file);
SHA1Update(&sha1_ctx, buffer, }
i);
SHA1Final(digest, &sha1_ctx); else //SHA1
fclose(file); {
unsigned char
digest[20],output[20];
byte2strhash(digest,20,output); UpdateData(TRUE);
CString str(output); CString context=m_string;
SetDlgItemText(IDC_INPUT,str); SHA1Init(&sha1_ctx);
} unsigned char *buf = (unsigned } char*)context.GetBuffer(context.GetLe
ngth());
void DMyDlg::OnChangeString() SHA1Update(&sha1_ctx,buf, { strlen(context));
// TODO: If this is a RICHEDIT SHA1Final(digest, &sha1_ctx); control, the control will not context.ReleaseBuffer();
// send this notification unless you
override the CDialog::OnInitDialog()
// function and call byte2strhash(digest,20,output); CRichEditCtrl().SetEventMask() CString str(output);
// with the ENM_CHANGE flag ORed
into the mask. SetDlgItemText(IDC_INPUT,str);
}
// TODO: Add your control }
notification handler code here
UpdateData(TRUE); void DMyDlg::OnSha1Radio()
MD5_CTX md5_ctx; {
SHA1_CTX sha1_ctx; // TODO: Add your control
notification handler code here
int hashradio;
}
hashradio=GetCheckedRadioButton(I
DC_MD5_RADIO,IDC_SHA1_RADIO); void DMyDlg::OnMd5Radio()
if(hashradio==IDC_MD5_RADIO) {
//MD5 // TODO: Add your control
notification handler code here // TODO: Add your control
notification handler code here } CDialog::OnOK();
void DMyDlg::OnEditchangeCombo() }
{
// TODO: Add your control void CAboutDlg::OnOK() notification handler code here {
// TODO: Add extra validation here}
CDialog::OnOK();
void DMyDlg::OnButton1() }
{