python Crypto中DSA签名的源码分析(1)——**生成
DSA需要的**有三种,分别是全局公开钥:p、q、g;私钥x;公钥y,具体要求如下:
-全局公钥p:满足的大素数,其中512≤L≤1024且L是64的倍数;
-全局公钥q:p-1的素因子,满足,即q一定是160bit;
-全局公钥g:,其中h是满足1<h<p-1且使得
的任一整数;
-服务器私钥x:满足0<x<q的随机数或伪随机数;
-服务器公钥y:;
整个代码的结构如下图所示:
(1)首先确定一个随机数生成器,如果未指定,则使用AES加密算法中的随机数生成器(这部分未深入研究,不清楚具体随机数生成算法),代码如下:
def _get_randfunc(self, randfunc):
if randfunc is not None:
return randfunc
elif self._current_randfunc is None:
self._current_randfunc = Random.new().read
return self._current_randfunc
(2)生成全局公钥q,函数generateQ(先生成q,再生成p,因为q是p-1的素因子),先利用上一步得到的随机数生成器生成一个20位的随机数,然后每次取两个hash值的一位作异或,再将异或之后的值加到上一次运算结果的左移八位的值上,最后一次保证是奇数(函数isPrime有两个部分,第一部分是利用10000以内的素数判断素性,第二部分利用Miller-Rabin算法检测素数,此算法主要是利用费马小定理,是一种概率检测,但是目前最好的算法),最后保证q是160bit。大素数生成一般步骤,生成一个大奇数,先用一些素数判定此数的素性,再用Miller-Rabin检测素性。
def generateQ(randfunc):
S=randfunc(20)
hash1=SHA.new(S).digest()
hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest()
q = bignum(0)
for i in range(0,20):
c=bord(hash1[i])^bord(hash2[i])
if i==0:
c=c | 128
if i==19:
c= c | 1
q=q*256+c
while (not isPrime(q)):
q=q+2
if pow(2,159L) < q < pow(2,160L):
return S, q
raise RuntimeError('Bad q value generated')
(3)生成全局公钥p,前面的代码一直到p=X-(X%(2*obj.q)-1)这句代码前都是在生成一个大数X,且这个大数一定是等于2的bits-1次方的,然后通过p=X-(X%(2*obj.q)-1)生成p,通过移位等式变为p-1=X-X%(2*obj.q),后面部分保证了是2q的倍数,所以一定p-1一定是q的倍数,满足了q是p-1的素因子,最后在判断p是否满足位数和是否是素数。
n=divmod(bits-1, 160)[0]
C, N, V = 0, 2, {}
b=(obj.q >> 5) & 15
powb=pow(bignum(2), b)
powL1=pow(bignum(2), bits-1)
while C<4096:
for k in range(0, n+1):
V[k]=bytes_to_long(SHA.new(S+bstr(N)+bstr(k)).digest())
W=V[n] % powb
for k in range(n-1, -1, -1):
W=(W<<160L)+V[k]
X=W+powL1
p=X-(X%(2*obj.q)-1)
if powL1<=p and isPrime(p):
break
C, N = C+1, N+n+1
if C<4096:
break
(3)生成全局公钥g,这个没什么好说的,完全按照g的定义来的,代码如下:
power=divmod(p-1, obj.q)[0]
if progress_func:
progress_func('h,g\n')
while (1):
h=bytes_to_long(randfunc(bits)) % (p-1)
g=pow(h, power, p)
if 1<h<p-1 and g>1:
break
obj.g=g
(4)私钥x的生成,这个也没什么好说的,直接生成一个随机数,然后再看满足条件么,代码如下:
while (1):
x=bytes_to_long(randfunc(20))
if 0 < x < obj.q:
break
(5)公钥y的生成,这个也没什么好说的,按照定义来就行,代码如下:
obj.x, obj.y = x, pow(g, x, p)
好了,到此为止Crypto包中DSA签名算法的所有**生成源码分析完毕,下篇分析签名和验证签名