lamport-crypto

摘要: 数字签字和认证机构是电子商务的核心技术。数字签名作为目前Internet中电子商务重要的技术,不断地进行改进,标准化。本文从数字签名的意义出发,详细介绍了数字签名中涉及到的内容与算法,并自行结合进行改进。 
   
  关键词:Internet 公钥加密 Hash函数 电子商务 加密 数字签名  
   
  数字签名简介 
   
  我们对加解密算法已经有了一定理解,可以进一步讨论"数字签名"(注意不要与数字认证混淆)的问题了,即如何给一个计算机文件进行签字。数字签字可以用对称算法实现,也可以用公钥算法实现。但前者除了文件签字者和文件接受者双方,还需要第三方认证,较麻烦;通过公钥加密算法的实现方法,由于用秘密密钥加密的文件,需要靠公开密钥来解密,因此这可以作为数字签名,签名者用秘密密钥加密一个签名(可以包括姓名、证件号码、短信息等信息),接收人可以用公开的、自己的公开密钥来解密,如果成功,就能确保信息来自该公开密钥的所有人。 
   
  公钥密码体制实现数字签名的基本原理很简单,假设A要发送一个电子文件给B,A、B双方只需经过下面三个步骤即可: 
   
  1. A用其私钥加密文件,这便是签字过程 
   
  2. A将加密的文件送到B 
   
  3. B用A的公钥解开A送来的文件 
   
  这样的签名方法是符合可靠性原则的。即: 
   
  签字是可以被确认的, 
  签字是无法被伪造的, 
  签字是无法重复使用的, 
  文件被签字以后是无法被篡改的, 
  签字具有无可否认性, 
  数字签名就是通过一个单向函数对要传送的报文进行处理得到的用以认证报文来源并核实报文是否发生变化的一个字母数字串。用这几个字符串来代替书写签名或印章,起到与书写签名或印章同样的法律效用。国际社会已开始制定相应的法律、法规,把数字签名作为执法的依据。 
   
  数字签名的实现方法 
   
  实现数字签名有很多方法,目前数字签名采用较多的是公钥加密技术,如基于RSA Data Security公司的PKCS(Public Key Cryptography Standards)、DSA(Digital Signature Algorithm)、x.509、PGP(Pretty Good Privacy)。1994年美国标准与技术协会公布了数字签名标准(DSS)而使公钥加密技术广泛应用。同时应用散列算法(Hash)也是实现数字签名的一种方法。 
   
  非对称密钥密码算法进行数字签名 
   
  算法的含义: 
   
  非对称密钥密码算法使用两个密钥:公开密钥和私有密钥,分别用于对数据的加密和解密,即如果用公开密钥对数据进行加密,只有用对应的私有密钥才能进行解密;如果用私有密钥对数据进行加密,则只有用对应的公开密钥才能解密。 
   
  使用公钥密码算法进行数字签名通用的加密标准有: RSA,DSA,Diffie-Hellman等。 
   
  签名和验证过程: 
   
  发送方(甲)首先用公开的单向函数对报文进行一次变换,得到数字签名,然后利用私有密钥对数字签名进行加密后附在报文之后一同发出。 
   
  接收方(乙)用发送方的公开密钥对数字签名进行解密交换,得到一个数字签名的明文。发送方的公钥可以由一个可信赖的技术管理机构即认证中心(CA)发布的。 
   
  接收方将得到的明文通过单向函数进行计算,同样得到一个数字签名,再将两个数字签名进行对比,如果相同,则证明签名有效,否则无效。 
   
  这种方法使任何拥有发送方公开密钥的人都可以验证数字签名的正确性。由于发送方私有密钥的保密性,使得接受方既可以根据结果来拒收该报文,也能使其无法伪造报文签名及对报文进行修改,原因是数字签名是对整个报文进行的,是一组代表报文特征的定长代码,同一个人对不同的报文将产生不同的数字签名。这就解决了银行通过网络传送一张支票,而接收方可能对支票数额进行改动的问题,也避免了发送方逃避责任的可能性。 
   
  对称密钥密码算法进行数字签名 
   
  算法含义 
   
  对称密钥密码算法所用的加密密钥和解密密钥通常是相同的,即使不同也可以很容易地由其中的任意一个推导出另一个。在此算法中,加、解密双方所用的密钥都要保守秘密。由于计算机速度而广泛应用于大量数据如文件的加密过程中,如RD4和DES,用IDEA作数字签名是不提倡的。 
   
  使用分组密码算法数字签名通用的加密标准有:DES,Tripl-DES,RC2,RC4,CAST等。 
   
  签名和验证过程 
   
  Lamport发明了称为Lamport-Diffle的对称算法:利用一组长度是报文的比特数(n)两倍的密钥A,来产生对签名的验证信息,即随机选择2n个数B,由签名密钥对这2n个数B进行一次加密交换,得到另一组2n个数C。 
   
  发送方从报文分组M的第一位开始,依次检查M的第I位,若为0时,取密钥A的第i位,若为1则取密钥A的第i+1位;直至报文全部检查完毕。所选取的n个密钥位形成了最后的签名。 
   
  接受方对签名进行验证时,也是首先从第一位开始依次检查报文M,如果M的第i位为0时,它就认为签名中的第i组信息是密钥A的第i位,若为1则为密钥A的第i+1位;直至报文全部验证完毕后,就得到了n个密钥,由于接受方具有发送方的验证信息C,所以可以利用得到的n个密钥检验验证信息,从而确认报文是否是由发送方所发送。 
   
  这种方法由于它是逐位进行签名的,只有有一位被改动过,接受方就得不到正确的数字签名,因此其安全性较好,其缺点是:签名太长(对报文先进行压缩再签名,可以减少签名的长度);签名密钥及相应的验证信息不能重复使用,否则极不安全。 
   
  结合对称与非对称算法的改进 
   
  对称算法与非对称算法各有利弊,所以结合各自的优缺点进行改进,可以用下面的模块进行说明: 
   
  Hash算法进行数字签名 
   
  Hash算法也称作散列算法或报文摘要,Hash算法将在数字签名算法中详细说明。 
   
  Hash算法数字签字通用的加密标准有: SHA-1,MD5等。 
   
  数字签名算法   
   
  数字签名的算法很多,应用最为广泛的三种是: Hash签名、DSS签名、RSA签名。这三种算法可单独使用,也可综合在一起使用。数字签名是通过密码算法对数据进行加、解密变换实现的,常用的HASH算法有MD2、MD5、SHA-1,用DES算法、RSA算法都可实现数字签名。但或多或少都有缺陷,或者没有成熟的标准。 
   
  Hash签名 
   
  Hash签名是最主要的数字签名方法,也称之为数字摘要法(digital digest)、数字指纹法(digital finger print)。它与RSA数字签名是单独的签名不同,该数字签名方法是将数字签名与要发送的信息紧密联系在一起,它更适合于电子商务活动。将一个商务合同的个体内容与签名结合在一起,比合同和签名分开传递,更增加了可信度和安全性。下面我们将详细介绍Hash签名中的函数与算法。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <time.h>
  5 #include <iostream>
  6 #include <string.h>
  7 #include <math.h>
  8 #include <algorithm>
  9 #include <random>
 10 
 11 using namespace std;
 12 
 13 const int S = 10;
 14 
 15 long long mult_mod(long long a, long long b, long long c)
 16 {
 17     a %= c;
 18     b %= c;
 19     long long ret = 0;
 20     while (b)
 21     {
 22         if (b & 1)
 23         {
 24             ret += a;
 25             ret %= c;
 26         }
 27         a <<= 1;
 28         if (a >= c)
 29             a %= c;
 30         b >>= 1;
 31     }
 32     return ret;
 33 }
 34 
 35 //计算 ret =  x^n %c
 36 long long pow_mod(long long x, long long n, long long mod) //x^n%c
 37 {
 38     if (n == 1)
 39         return x % mod;
 40     x %= mod;
 41     long long tmp = x;
 42     long long ret = 1;
 43     while (n)
 44     {
 45         if (n & 1)
 46             ret = mult_mod(ret, tmp, mod);
 47         tmp = mult_mod(tmp, tmp, mod);
 48         n >>= 1;
 49     }
 50     return ret;
 51 }
 52 
 53 bool check(long long a, long long n, long long x, long long t)
 54 {
 55     long long ret = pow_mod(a, x, n);
 56     long long last = ret;
 57     for (int i = 1; i <= t; i++)
 58     {
 59         ret = mult_mod(ret, ret, n);
 60         if (ret == 1 && last != 1 && last != n - 1)
 61             return true; //合数
 62         last = ret;
 63     }
 64     if (ret != 1)
 65         return true;
 66     return false;
 67 }
 68 
 69 bool Miller_Rabin(long long n) //Miller_Rabin算法判断素数
 70 {
 71     if (n < 2)
 72         return false;
 73     if (n == 2)
 74         return true;
 75     if ((n & 1) == 0)
 76         return false; //偶数
 77     long long x = n - 1;
 78     long long t = 0;
 79     while ((x & 1) == 0)
 80     {
 81         x >>= 1;
 82         t++;
 83     }
 84     for (int i = 0; i < S; i++)
 85     {
 86         long long a = rand() % (n - 1) + 1;
 87         if (check(a, n, x, t))
 88             return false; //合数
 89     }
 90     return true;
 91 }
 92 
 93 long long gcd(long long a, long long b)
 94 {
 95     if (a == 0)
 96         return 1;
 97     if (a < 0)
 98         return gcd(-a, b);
 99     while (b)
100     {
101         long long t = a % b;
102         a = b;
103         b = t;
104     }
105     return a;
106 }
107 
108 bool Legendre(int a, int p)
109 {
110     int tmp = pow(a, (p - 1) / 2);
111     if (tmp % p == 1)
112         return true;
113     else
114         return false;
115 }
116 
117 int main()
118 {
119     cout << "*******************************************" << endl;
120     cout << "测试数据假定 p = 7 q = 11 ,进行签名和验证" << endl;
121     cout << "*******************************************" << endl
122          << endl
123          << endl;
124     static uniform_int_distribution<unsigned> u(1000000, 1000000000);
125     static default_random_engine e(time(0));
126     long long p = 6, q = 6;
127 
128     //随机产生素数p q
129     while (!Miller_Rabin(p))
130         p = u(e);
131     while (!Miller_Rabin(q))
132         q = u(e);
133 
134     //cout << p << " " << q << endl;
135     long long n = p * q;
136     cout << "素数p,q生成完毕!" << endl;
137     p = 7;
138     q = 11;
139 
140     //签名生成
141     cout << "请输入 m 进行签名:" << endl;
142     long long m;
143     cin >> m;
144 
145     if (!(Legendre(m, p) && Legendre(m, q)))
146     {
147         while (!(Legendre(m, p) && Legendre(m, q)))
148             m = m - 1;
149     }
150 
151     long long s = ((long long)sqrt(m)) % n;
152 
153     //签名验证
154     cout << "请输入s进行签名验证:" << endl;
155     int ss;
156     cin >> ss;
157     if (m == ss * ss % n)
158         cout << "true 验证成功!" << endl;
159     else
160         cout << "false 验证失败!" << endl;
161 
162     return 0;
163 }
164 
165 #if 0
166 #include <iostream>
167 #include <stdio.h>
168 #include <cmath>
169 #include <string>
170 
171 using namespace std;
172 
173 int quickpow(int m, int n, int k)
174 {
175     int b = 1;
176     while (n > 0)
177     {
178         if (n & 1)
179             b = (b * m) % k;
180         n = n >> 1;
181         m = (m * m) % k;
182     }
183     return b;
184 }
185 
186 int main()
187 {
188     int n, MOD;
189     cin >> n >> MOD;
190 
191     int y10, y11, y20, y21, y30, y31;
192     cin >> y10 >> y11 >> y20 >> y21 >> y30 >> y31;
193 
194     int z10, z11, z20, z21, z30, z31;
195 
196     z10 = quickpow(n, y10, MOD);
197     z11 = quickpow(n, y11, MOD);
198     z20 = quickpow(n, y20, MOD);
199     z21 = quickpow(n, y21, MOD);
200     z30 = quickpow(n, y30, MOD);
201     z31 = quickpow(n, y31, MOD);
202 
203     string cl;
204     cin >> cl;
205     int len = cl.size();
206     int Sign[100];
207 
208     if (cl[0] == '0')
209         Sign[0] = y30;
210     else
211         Sign[0] = y31;
212     if (cl[1] == '0')
213         Sign[1] = y20;
214     else
215         Sign[1] = y21;
216     if (cl[2] == '0')
217         Sign[2] = y10;
218     else
219         Sign[2] = y11;
220 
221     int Sign_ans[100];
222 
223     for (int i = 0; i < 3; i++)
224     {
225         Sign_ans[i] = quickpow(n, Sign[2 - i], MOD);
226         cout << Sign_ans[i] << endl;
227     }
228 
229     return 0;
230 }
231 #endif
View Code

 

posted @ 2018-07-29 09:05  sigmod  阅读(269)  评论(0编辑  收藏  举报