调试国密算法验签遇到的问题
2017-07-08 00:00
246 查看
项目要求服务端与客户端支持国密证书建立ssl通道.在本地demo中可以建立完整的ssl连接并通信.
服务端建立ssl时直接使用openssl加载根证书,服务端证书,服务端私钥.这里毫无问题.
但是客户端必须调用windows的csp接口,而且windows系统目前不支持导入国密证书,所以建立连接的方式只能是通过usekey的形式(usebkey可以想象为银行u盾),usbkey中实现了csp接口.
摘要算法的过程有三个,1初始化init ,2 update ,3 final.其有一个特点,就是中间的update可以分多次调用,即
init();update("123");final(); 等同于init();update("1");update("2");update("3");final();
握手过程中,未避免保存大量待摘要内容,每次握手都是增量调用摘要update,在最后一次握手时调用final就可以了.
国密算法要求计算摘要前需要计算Z值,计算Z值需要对方的公钥,而且usbkey只支持在内部计算摘要并签名,不能只调用其签名接口,这就产生了如下矛盾:
1.客户端必须保存签名前的所有握手信息,极其占用空间
2.服务端必须在第一次握手时就计算出Z值加在握手信息前摘要,否则无法验签.而第一次握手时服务端没有客户端公钥无法计算Z值,所以服务端也必须保存一份极占空间的握手信息,这种做法在访问量大的时候是个灾难.
解决方法:只要能够保证握手信息的完整性,并且服务端和客户端信息一致就可以.所以不对原始握手信息进行摘要,而对openssl计算的摘要信息进行再摘要.逻辑如下:
客户端:sign( 摘要(Z值+openssl摘要) ) 服务端:verify( 摘要(Z值+openssl摘要) )
所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。
而在Big-endian模式CPU内存中的存放方式则为:
服务端建立ssl时直接使用openssl加载根证书,服务端证书,服务端私钥.这里毫无问题.
但是客户端必须调用windows的csp接口,而且windows系统目前不支持导入国密证书,所以建立连接的方式只能是通过usekey的形式(usebkey可以想象为银行u盾),usbkey中实现了csp接口.
问题1,handshake摘要
openssl在建立连接的过程中,会将握手过程的信息做摘要保存在handshake_dgst[]数组,数组中每个索引对应一种摘要算法,每种支持的摘要算法都算一遍摘要保存.摘要算法的过程有三个,1初始化init ,2 update ,3 final.其有一个特点,就是中间的update可以分多次调用,即
init();update("123");final(); 等同于init();update("1");update("2");update("3");final();
握手过程中,未避免保存大量待摘要内容,每次握手都是增量调用摘要update,在最后一次握手时调用final就可以了.
国密算法要求计算摘要前需要计算Z值,计算Z值需要对方的公钥,而且usbkey只支持在内部计算摘要并签名,不能只调用其签名接口,这就产生了如下矛盾:
1.客户端必须保存签名前的所有握手信息,极其占用空间
2.服务端必须在第一次握手时就计算出Z值加在握手信息前摘要,否则无法验签.而第一次握手时服务端没有客户端公钥无法计算Z值,所以服务端也必须保存一份极占空间的握手信息,这种做法在访问量大的时候是个灾难.
解决方法:只要能够保证握手信息的完整性,并且服务端和客户端信息一致就可以.所以不对原始握手信息进行摘要,而对openssl计算的摘要信息进行再摘要.逻辑如下:
客户端:sign( 摘要(Z值+openssl摘要) ) 服务端:verify( 摘要(Z值+openssl摘要) )
问题2:大端小端问题
在签名与验签过程中,始终不能通过,打印过程中的参数都没有错误.最后确认为:usbkey实现的csp接口返回的签名是已小端方式存储的.服务端实现的是大端存储方式的验签算法.所以将csp接口返回的签名(r,s)分别倒序,验签通过.大小端区别如下: 转载自http://blog.csdn.net/zhaoshuzhaoshu/article/details/37600857/所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。
2.为什么会有大小端:
为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。3.大小端在内存中的存放方式举例:
例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:内存地址 | 0x4000 | 0x4001 |
存放内容 | 0x34 | 0x12 |
内存地址 | 0x4000 | 0x4001 |
存放内容 | 0x12 | 0x34 |
相关文章推荐
- 调试lmhub所遇到的问题
- 在调试微软的ajax包的updateprogress时遇到的问题
- VisualStudio用IE8调试时遇到的问题(转)
- 忆龙2009:BREW+VS2005 安装调试遇到常见问题
- 笔记--调试C程序时遇到的问题
- IE下调试网页的时候遇到的很恶心的JS问题
- 用ads调试时遇到的一些问题
- 程序调试中遇到的几种问题
- 调试Release模式下遇到的问题 - Debug和Release的差异。
- Silverlight3+WCF遇到的问题(一):调试资源字符串不可用。密钥和参数通常提供足够的信息用以诊断该问题
- .Net在web服务器上启动调试开始运行时遇到的几个问题
- ArcGIS Server开发调试中经常遇到的问题
- 最近oracle开发中遇到的一些问题及解决办法(四):调试存储过程--待续
- VisualStudio用IE8调试时遇到的问题
- 如题,我用的是vs2008(测试版)和UltraEdit-32 version 12.10我一运行或者调试web 程序就会遇到这个问题
- VC调试遇到的问题
- 对调用了TypeMock.net的代码进行调试遇到的怪问题--在vs.net中启动resharper自带的unit test的过程和方式是什么样的?
- asp调试环境遇到问题
- 控件调试时遇到的一个问题
- 在IE8中调试ActiveX遇到的问题