最近在弄DSA签名的工作,本以为很简单的事情 但却因为客户是 .net的开发环境而产生的很多麻烦的事情
在查看了相关文档尤其是 徐某人的 (http://archive.cnblogs.com/a/1687902/)这篇文章之后,有了很大的启发并得到了如下的解决方案!
我们先来看DER编码规则
DSA签名产生得到的是r和s两个整数。对于DSAWithSHA1来说,这两个整数都不会超过20字节。由于DSA签名需要使用一个随机数,所以每次签名的结果是不同的。
JAVA产生的DSAWithSHA1的签名结果是个下面ASN.1结构的DER编码:
Dss-Sig-Value ::= SEQUENCE {
r INTEGER,
s INTEGER }
.NET要求的签名结果40字节,前面20字节是r,后面20字节是s,采用大端字节序。
DER编码采用TLV的形式,每种类型有个Tag的编码,是为T部分的编码,接着是长度的编码,是为L部分的编码,最后是内容的编码,是为V部分的编码。
对于SEQUENCE来说,Tag的编码为0x30,其内容编码就是其容纳的ASN.1对象的逐个TLV编码拼起来。
对于INTEGER来说,Tag的编码为0x02,其内容编码就是使用最小的字节进行的补码形式。前9位不能全为1或者全为0。最高位为0表示正数,最高位为1表示负数。由于这里都是正数,所以如果最高位为1的话,前面要补0,也就是说最长的整数内容部分的编码长度为20+1=21字节。
长度的编码对于不超过127的来说,只占有一个字节,编码就是值本身。这里就是这种情况。
例子说明:
Java的签名
30 2C
02 14
1C FA 3A BB 5C 0F 37 FB D7 74 CB 51 E5 64 B5 76 B9 26 4F 7A
02 14
62 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 D2 78 5A 72 5B
30表示是SEQUENCE
2C表示后面编码有0x2c字节
02表示是INTEGER
14表示后面编码有0x14字节
1C FA 3A BB 5C 0F 37 FB D7 74 CB 51 E5 64 B5 76 B9 26 4F 7A这部分就是r内容的编码
这里r内容的编码刚好是20自己,直接拷贝即可。如果小于20字节,则前面补0到20字节。如果是21字节,则去掉最前面的1个字节,这个字节应该是0,表示r是正数;如果这个字节不是0则签名是错的。
02 表示是INTEGER
14表示后面编码有0x14字节
62 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 D2 78 5A 72 5B这部分是s内容的编码。处理方式和r内容的编码一样。
最后转换得到.NET的签名为
1C FA 3A BB 5C 0F 37 FB D7 74 CB 51 E5 64 B5 76 B9 26 4F 7A 62 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 D2 78 5A 72 5B
以上文字来自徐某人的博客的文章
java平台生成的DSA签名有45,46,47,48等几种而.net平台只能是40位 这时候就需要他们的相互转化了
length=45
48 43
2 19
94 116 4 99 101 -21 -74 83 89 -78 50 25 28 12 95 50 22 -8 83
2 20
120 85 -101 -40 27 123 57 -55 -7 -124 119 -13 67 -106 -106 119 95 64 61 -15
length=46
48 44
2 20
38 7 -93 -28 -103 111 105 -59 -75 -70 -43 26 63 75 -121 75 -97 -102 -90 -92
2 20
104 66 -83 22 -38 12 69 -6 -44 46 57 81 -37 47 -88 126 -121 104 -88 50
length=47
48 45
2 21
0 -106 -47 -114 -27 -22 103 14 37 16 -119 -91 -123 14 19 -112 -105 -77 -28 57 4
2 20
46 -68 -40 45 -57 -126 25 103 -44 91 92 108 -28 40 5 54 -10 11 -61 -10
length=48
48 46
2 21
0 -117 25 28 49 -117 2 -115 -13 -31 2 49 35 -64 -39 109 -76 107 14 -25 7
2 21
0 -120 122 114 -56 -6 84 13 -19 41 95 -68 29 -53 63 -98 -56 -113 -96 28 -53
通过分析 发现如下 规律
1. 46位是标准格式 前四位是 48 44 2 20 第25和26位 是 2 ,20
20代表后面的字节个数 .net 只需截取 5-24 和 27-46 这40位的数字即可
2.45 位是因为前段或后端的数据有一个是19位 转成 .net 前面加零补齐即可
3. 47位是因为有组数据为21位 去掉那组数据的开始的第一位数据 即可
4. 48位是因为有两组数据为21位 去掉那组数据的开始的第一位数据 即可
转化代码如下:
public static byte[] changeDSANet2java(String sign) {
byte tx[] = decryptBASE64(sign);
byte[] tx_new = new byte[46];
tx_new[0] = 48;
tx_new[1] = 44;
tx_new[2] = 2;
tx_new[3] = 20;
for (int x = 0; x < 20; x++) {
tx_new[x + 4] = tx[x];
}
tx_new[24] = 2;
tx_new[25] = 20;
for (int x = 20; x < 40; x++) {
tx_new[x + 6] = tx[x];
}
return tx_new;
}
分享到:
相关推荐
DSA数字签 DSA数字签DSA数字签名 DSA数字签名
来自StackOverflow的 Jeffrey Walton 的文章中dsa数字签名算法的java实现,包括生成签名,消息签名,验证签名三个功能的实现。
java写的DSA数字签名算法,是密码学中的典型算法
DSA签名程序和DSA验证程序。 签名程序流程: a. 读入字符串(从屏幕或文本文件中),字符串内容应包含自己的学号或姓名; b. 计算该字符串的SHA-1值; c. 生成DSA密钥对(利用dsa_make_key); d. 利用dsa_export...
来自StackOverflow的 Jeffrey Walton 的文章中dsa数字签名算法的C#实现,包括生成签名,消息签名,验证签名三个功能的实现。
实现数字签名功能,通过DSA算法实现,包含源程序等
DSA数字签名算法 包括MD5,sha1的信息摘要算法。文件导入功能
私钥为OpenSSL生成的PEM文件,本资源用C#从文件中读取私钥并加密,可以使用。
rsa Elgamal及DSA的使用实例,运用此类算法加密解密及签名验签
详细的DSA源码,并经过验证和分析,对DSA数字签名的安全分析非常有用
我不知道是这个DSA算法本身有问题还是什么.验证签名这块也有问题
通过实现数字签名算法(DSA),加深对数字签名算法的理解,同时学习Hash算法的实现。 1)利用C\C++语言实现DSA算法。 2)DSA中的Hash函数采用SHA算法。
实现数字签名算法以及验证数字签名算法的正确性。本程序经本人验证
BM算法求线性综合解和DES加密是用C++写的,DSA签名使用java写的。
用java实现dsa的签名算法,解决DSA签名的一些问题
数字签名标准(DSS)的研究与实现 1. 引言 5 2.数论基础 6 2.1 基本定义 6 2.2 散对数问题 7 3.数字签名标准DSS 9 3.1 DSA算法描述 9 3.1.1 DSA算法参数 9 3.1.2 DSA签名过程 9 3.1.3 DSA签名验证 10 3.2 DSA算法...
数字签名算法(Digital Signature Algorithm ,DSA),它也是一种非对称加密算法,被美国NIST作为数字签名标准(DigitalSignature Standard, DSS)。但是 应用于数字签名中。DSA算法比RSA产生密钥的速度要快一些,且安全...
RSA DSA 对称 非对称 加密 解密 XML 数字签名 C#.NET 安全编程这门课的大作业 里面有详细的例子,方便大家学习
DSA 数字签名算法 VC++实现 绝对好用 能够对文件进行数字签名 防止篡改
1)利用C\C++语言实现DSA算法。 2)DSA中的Hash函数采用SHA算法。 (1)消息填充:因为我们存储的时候是以字节为单位存储的,所以消息的长度(单位:位)一定是 8 的倍数。而我们填充的时候也一定是 8 位、8 位...