数字签名算法RSAWord格式.docx

上传人:b****7 文档编号:22688731 上传时间:2023-02-05 格式:DOCX 页数:20 大小:188.34KB
下载 相关 举报
数字签名算法RSAWord格式.docx_第1页
第1页 / 共20页
数字签名算法RSAWord格式.docx_第2页
第2页 / 共20页
数字签名算法RSAWord格式.docx_第3页
第3页 / 共20页
数字签名算法RSAWord格式.docx_第4页
第4页 / 共20页
数字签名算法RSAWord格式.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

数字签名算法RSAWord格式.docx

《数字签名算法RSAWord格式.docx》由会员分享,可在线阅读,更多相关《数字签名算法RSAWord格式.docx(20页珍藏版)》请在冰豆网上搜索。

数字签名算法RSAWord格式.docx

如果一个消息的签名是从别处复制得到的,则任何人都可以发现消息与签名之间的不一致性,从而可以拒绝签名的消息;

4)签名的消息是不可改变的:

经签名的消息不能篡改,一旦签名的消息被篡改,任何人都可以发现消息与签名之间的不一致性;

5)签名是不可抵赖的:

签名者事后不能否认自己的签名。

可以由第三方或仲裁方来确认双方的信息,以做出仲裁。

2、各模块功能描述

模块一创建创建密钥容器,得到CSP句柄

微软的CryptoAPI是PKI推荐使用的加密API。

其功能是为应用程序开发者提供在Win32环境下使用加密、验证等安全服务时的标准加密接口。

CryptoAPI处于应用程序和CSP之间(见图一)。

图一

从图一可以看到,每个CSP有一个密钥库,密钥库用于存储密钥。

而每个密钥库包括一个或多个密钥容器(KeyContainers)。

每个密钥容器中含属于一个特定用户的所有密钥对。

每个密钥容器被赋予一个唯一的名字。

在销毁密钥容器前CSP将永久保存每一个密钥容器,包括保存每个密钥容器中的公/私钥对。

在这个模块中,实现创建密钥容器,得到CSP密钥句柄的作用,并且它被绑定到以UserName为名的密钥容器上。

模块二计算Hash值,签名

在这个模块中,实现实现对原始报文的签名。

首先,对原始报文进行散列值的计算。

此处通过CryptoAPI中的函数,直接调用实现。

然后调用CryptSignHash(),对散列值进行签名。

过程如图二所示。

图二

模块三验证签名

负责验证签名的人在收到签名者发来的公钥、数据及签名后,先用CryptImportKey()将签名者的公钥导入密钥容器中,验证者通过对原文的Hash计算,并与收到的Hash值对比,验证是否是发送方发送的消息,并可验证其正确性。

过程如图三所示。

图三

三、概要设计

1、函数CryptAcquireContext(),获得指定CSP容器的句柄。

主要参数表如下:

PhProv()CSP句柄指针

PszContainer()密钥容器名称,指向密钥容器的字符串指针

Pszprovider()指向CSP名称的字符串指针

这个函数用来实现取得指定CSP句柄密钥容器,以后任何的加密都是针对这个CSP句柄而言。

2、函数CryptGenKey(),用来随即产生密钥。

主要参数如下:

hCryptProv,CSP句柄

AT_SIGNATURE,创建的密钥对类型为signaturekeypair

0,key类型,这里用默认值

&

hKey创建成功返回新创建的密钥对的句柄

3、函数CryptCreateHash(),用来创建Hash对象。

参数如下:

HCRYPTPROVhProv,CSP句柄

ALG_IDAlgid,选择hash算法,比如CALG_MD5等

HCRYPTKEYhKey,HMAC和MAC算法时有用

DWORDdwFlags,保留,传入0即可

HCRYPTHASH*phHash返回hash句柄

4、函数CryptHashData(),用来Hash数据。

HCRYPTHASHhHash,hash对象

BYTE*pbData,被hash的数据

DWORDdwDataLen,数据的长度

DWORDdwFlags微软的CSP这个值会被忽略

5函数CryptDeriveKey(),用于 

调用CryptDeriveKey获取对话密码,参数如下:

hCryptProv, 

 

CSP句柄

CALG_RC2, 

一个ALG_ID结构,用来指定对称密钥生成的算法

hHash, 

哈希对象

CRYPT_EXPORTABLE, 

指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。

但是它不能用于非对称密码中。

hKey指向生成的密钥

5、总体设计

发送方验证方

四、详细设计

1、RSA算法描述

RSA算法是一种公钥密码算法,实现RSA算法包括生成RSA密钥,加密和解密数据。

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。

RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。

即RSA的重大缺陷是无法从理论上把握它的保密性能如何,而且密码学界多数人士倾向于因子分解不是NP-C问题。

RSA的缺点主要有:

A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。

B)分组长度太大,为保证安全性,n至少也要600bits。

RSA算法的实现原理:

1)随机选择两个不同的素数p和q,它们的宽度是密钥宽度的二分之一。

2)计算出p和q的乘积n。

3)在2和Φ(n)之间随机选择一个数e,e必须和Φ(n)互素,整数e用做加密密钥(其中Φ(n)=(p-1)*(q-1))。

4)从公式ed≡1modΦ(n)中求出解密密钥d。

5)得公钥(e,n),私钥(d,n)。

6)公开公钥,但不公开私钥。

7)将明文P(假设P是一个小于n的整数)加密为密文C,计算方法为:

C=P^emodn;

8)将密文C解密为明文P,计算方法为:

P=C^dmodn;

然而只根据n和e(不是p和q)要计算出d是不可能的。

因此,任何人都可对明文进行加密,但只有授权用户(知道d)才可对密文解密。

2、创建密钥容器,得到CSP句柄

此处调用函数CryptAcquireContext(),创建密钥容器,当Flagvalues值为零,说明以UserName为名的密钥容器存在,那么我们已经得到了CSP的句柄

具体实现代码如下:

if(CryptAcquireContext(

hCryptProv,//返回CSP句柄

UserName,//密码容器名

NULL,//NULL时使用默认CSP名(微软RSABaseProvider)

PROV_RSA_FULL,//CSP类型

0))//Flagvalues

{

printf("

得到了CSP句柄"

UserName);

}

如果密钥容器不存在,我们需要重新创建这个密钥容器:

&

hCryptProv,

UserName,

NULL,

PROV_RSA_FULL,

CRYPT_NEWKEYSET))//创建以UserName为名的密钥容器

{

//创建密钥容器成功,并得到CSP句柄

一个新的密钥容器被创建\n"

);

else

HandleError("

创建失败.\n"

}

此时就已经创建了密钥容器,并得到了CSP的句柄。

也可以这样理解,我们得到了一个CSP的句柄,并且它被绑定到以UserName为名的密钥容器上。

可以如下删除密钥容器。

CryptAcquireContext(&

hCryptProv,userName,NULL,PROV_RSA_FULL,CRYPT_DELETEKEYSET);

3、RSA算法描述

具体程序实现如下:

1、读取原文

voidCGenRsaKey:

:

OnSOpenButton()

//TODO:

Addyourcontrolnotificationhandlercodehere

UpdateData(TRUE);

charszFilter[]="

全部文件(*.*)|*.*||"

;

CFileDialogOpenFile(TRUE,NULL,"

*.*"

OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR,szFilter,NULL);

if(OpenFile.DoModal()!

=IDOK)

return;

m_strSSrcPath=OpenFile.GetPathName();

UpdateData(FALSE);

return;

}

//产生随机密钥

OnVerifySaveButton()

staticcharszFilter[]="

CFileDialogsaveFileDlg(FALSE,NULL,"

OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR,szFilter,NULL);

if(saveFileDlg.DoModal()!

m_strVDestPath=saveFileDlg.GetPathName();

OnRsaSign()

if(m_strSSrcPath=="

"

m_strVDestPath=="

MessageBox("

请选择待签名/待验证文件路径!

//读取签名原文失败

CFilefpSrcFile;

if(fpSrcFile.Open(m_strVDestPath,CFile:

modeRead)==0)

读取签名原文失败!

nSrcLen=fpSrcFile.GetLength();

pbSrcData=newunsignedchar[nSrcLen+1];

memset(pbSrcData,0x00,nSrcLen+1);

fpSrcFile.Read(pbSrcData,nSrcLen);

fpSrcFile.Close();

2、获得CSP句柄

intCKeyOperation:

CRYPTAPI_RSAVerify(unsignedchar*pbSrcData,intnSrcLen,

unsignedchar*pbDestData,intnDestLen)

if(!

m_hProv,"

ASYSIGN"

MS_ENHANCED_PROV,PROV_RSA_FULL,0))

return-1;

CryptGetUserKey(m_hProv,AT_SIGNATURE,&

m_hKey))

if(m_hProv)

CryptReleaseContext(m_hProv,0);

return-2;

}

3、创建Hash对象并Hash数据

HCRYPTHASHhHash;

CryptCreateHash(m_hProv,CALG_SHA,0,0,&

hHash))//创建HASH对象

//释放CSP句柄

return-3;

CryptHashData(hHash,pbSrcData,(unsignedlong)nSrcLen,0))//hash数据

if(hHash)

CryptDestroyHash(hHash);

//释放Hash句柄

4、签名数据

//获得签名数据长度

CryptSignHash(hHash,AT_SIGNATURE,NULL,0,NULL,(unsignedlong*)pnDestLen))

return-4;

//签名HASH数据

CryptSignHash(hHash,AT_SIGNATURE,NULL,0,pbDestData,(unsignedlong*)pnDestLen))

return-5;

if(hHash)

CryptDestroyHash(hHash);

if(m_hProv)

return0;

5、读取签名数据

CFilefpDestFile;

if(fpDestFile.Open(m_strSSrcPath,CFile:

nDestLen=fpDestFile.GetLength();

fpDestFile.Read(pbDestData,nDestLen);

fpDestFile.Close();

CFilefpDestFile;

6、Hash待验证数据

//创建HASH对象

hHash))

//HASH待验证数据

CryptHashData(hHash,pbSrcData,nSrcLen,0))

7、验证签名数据

//验证签名数据

CKeyOperationobj_Verify;

intr=obj_Verify.CRYPTAPI_RSAVerify(pbSrcData,nSrcLen,pbDestData,nDestLen);

if(r!

=0)

验证签名失败!

delete[]pbSrcData;

pbSrcData=NULL;

MessageBox("

验证签名成功!

if(!

CryptVerifySignature(hHash,pbDestData,nDestLen,m_hKey,NULL,0))

if(hHash)

CryptReleaseContext(m_hProv,0);

五、测试数据及其结果分析

测试时,在签名原文中输入数据:

1234567890

生成RSA密钥对,并导出公钥

程序显示产生RSA密钥对成功,说明在签名时产生密钥对运行没有问题。

对签名原文进行签名,程序运行如下:

程序运行显示签名数据成功,签名后数据长度为128字节,签名后的数据存放在.txt文档中,便于在下一步进行验证比较。

签名后的数据显示如下:

记事本显示为乱码,因为输出为16进制,在记事本中的显示就为乱码,当放入控制台时,显示就为16进制数。

发现数据长度为128字节,签名正确。

对签名进行验证,程序运行如下:

待验证文件选择为签名后的数据,签名原文选择原文件。

按下验证签名按钮,产生对话框,说明验证签名成功,程序运行无误。

六、软件设计总结

本次的课程设计,主要是熟悉了数字签名的具体过程,并了解了RSA算法的具体实现步骤,更重要的是学会了CryptoAPI的使用,通过调用其中的函数,很方便的实现了加密以及签名的功能。

再次总结一下收获。

1、关于CSP

CSP是真正执行加密工作的独立的模块。

物理上一个CSP由两部分组成:

一个动态链接库,一个签名文件。

若加密算法用硬件实现,则CSP还包括硬件装置。

其决定了以下因素:

(1) 

有且仅有一个密钥交换算法;

(2) 

有且仅有一个签名算法;

(3) 

特定的Key 

Blob格式;

(4) 

特定的数字签名格式;

(5) 

特定的密钥推导模式;

(6) 

特定的密钥长度;

(7)特定的分组加密算法的缺省模式。

2、 

几个误区

通过本次数字签名的实验,我通过上网查阅资料等方式,发现存在着这样几个误区。

误区一:

大家对公钥私钥区分得太死板了。

其实当你把公钥保密不公开的时候,公钥就是私钥了;

当你把私钥公开的时候,私钥也是公钥了。

没必要记得这么死的。

密钥与私钥只是相对的概念,RSA中产生的e与d,当把e公布出去时,e就是公钥,d就是私钥。

相反的e就变成了私钥。

误区二:

对RSA算法的原理理解不够,实际上所谓的公钥和私钥只是RSA算法(说穿了RSA就是个数学方程式)的参数(未知数),比如X+Y+M=Z,X就可以说是私钥,Y就可以说是公钥,M就是需要加密的内容,Z就是加密后的密文,当然RSA中不可能只有X和Y两个未知数的,所以就经常有朋友问,到底X是私钥还是Y是

钥。

其实这个就要取决于你用在时候,什么地方了。

误区三:

对Security.Cryptography命名空间不熟悉。

“数字签名”一般的做法是:

A先计算出文件M的HASH码,再对HASH码进行加密(这个步骤就是签名),再把M(文件M不要加密,第三方可以查阅)和加密后的HASH码传送给B,B再用A的公钥来解密刚才得到的加密HASH码,如果能解密,那就说明这个文件是A发的,具有法律效应。

再计算出得到的文件M的HASH码,再和刚才解密出来的HASH码比较(这个步骤叫验证签名),如果一致就说明文件M在传输过程中没有被修改。

但是需要解密RSA,就必须提供公钥和私钥,当然这和我们的现实不符,因为A不可能把他的私钥给B。

许多人就是在这里难住了。

其实Security.Cryptography命名空间中有RSA

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1