XD现代密码学大作业-DSA签名算法的安全性

实验名称:DSA签名算法的安全性

实验原理:

DSA是在ElGamal和Schnorr两个签名方案的基础上设计的,其安全性基于求离散对数的困难性。生成签名长度 320 bit,算法描述如下:
(1) 全局公开钥

  • p:满足2L-1<p<2L 的大素数,其中512≤L≤1024且L是64的倍数。
  • q:p-1的素因子,满足2159<q<2160 ,即q长为160比特。
  • g:g=h(p-1)/q mod p,h是满足1<h<p-1且使得h(p-1)/q mod p >1的任一整数。
    (2) 用户秘密钥x
  • x是满足0<x<q的随机数或伪随机数。
    (3) 用户的公开钥y
  • y≡gx mod p。
    (4) 用户为待签消息选取的秘密数k
  • k是满足0<k<q的随机数或伪随机数。
    (5) 签名过程
  • 用户对消息M的签名为(r, s),其中r≡(gk mod p) mod q
  • s≡[k-1(H(M)+xr)] mod q,H(M)是由SHA1求出的哈希值。
    (6) 验证过程
  • 设接收方收到的消息为M,签名为(r,s)。
  • 计算
    w≡(s)-1 mod q , u1≡[H(M)w] mod q
    u2≡rw mod q , v≡[(gu1yu2) mod p] mod q
  • 检查v=r 是否成立,若相等,则认为签名有效。

实验目的:

1、学习密码学的基本编程方法,学会利用python库函数等;
2、理解数字签名的参数的作用,数字签名的签名和验证算法;
2、通过本实验理解DSA签名中的随机数k是不能泄露的,理解数字签名的安全性。

实验内容:

DSA签名的安全参数p,q,g和公开钥y如下。下面也给出了被签名的消息m及其哈希值和相应的签名(r, s),已知签名用的"k" 的范围是 0 到2^16,恢复DSA的秘密钥x。
p = 800000000000000089e1855218a0e7dac38136ffafa72eda7
859f2171e25e65eac698c1702578b07dc2a1076da241c76c6
2d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebe
ac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2
b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc87
1a584471bb1
q = f4f47f05794b256174bba6e9b396a7707e563c5b
g = 5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119
458fef538b8fa4046c8db53039db620c094c9fa077ef389b5
322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a047
0f5b64c36b625a097f1651fe775323556fe00b3608c887892
878480e99041be601a62166ca6894bdd41a7054ec89f756ba
9fc95302291
y = 84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4
abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004
e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed
1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07b
bb283e6633451e535c45513b2d33c99ea17
被签名的消息为:For those that envy a MC it can be hazardous to your health
So be friendly, a matter of life and death, just like a etch-a-sketch
它的SHA1 值为(十六进制):0xd2d0714f014a9784047eaeccf956520045c45265。
得到的签名为:
r = 548099063082341131477253921760299949438196259240
s = 857042759984254168557880549501802188789837994940

请编程恢复DSA的秘密钥x,并给出它的SHA1 值。

实验器材(设备、元器件):

一台PC,安装Windows10等操作系统,VC++\Python等开发环境。

实验思路,代码及运行结果:

(1)解题思路或方法:
首先,简单的梳理一下实验思路。在本实验中使用的是DSA签名算法。在DSA签名算法中,公开的有安全参数p,q,g和公开钥y,接收者会接受到被签名的消息m及其算出的哈希值和相应的签名(r, s)。在如何判断签名为私钥拥有者签名的问题中,实验上面的说明部分已经解释很清楚:如果被签名的消息为假,那么最后的签名r会与通过s算出来的r不一样。如果r、s、被签名的消息均为假,那么就说明侵入者自制了个k以及x,但在验证环节中由于验证公式中含变量y(y≡gx mod p),故验收时通过s’算出来的r’还是会与侵入者伪造的r’不同,从而完成对签名为私钥拥有者签名的判断。可见,只有知道k和x的情况下才能成功伪造被签名的消息和签名。
那为了达成实验目的,该如何求出私秘钥x呢?按理说,给了2个未知数x和k,又给了2个方程,那么刚好可以求出x和k。但方程太复杂数字又大,没有办法对其进行求解。那我们直接可以对k进行暴力求解,因为k的范围为0~2^16比较小,可以试出k的大小之后再反带入求s的公式,求出x。(从s≡[k-1(H(M)+xr)] mod q,可以继续推出x≡r-1*[ks-H(M)] mod q),再将x通过python的hashlib库的sha1相关函数求出其的SHA1值。
(2)代码

import hashlib

#DSA签名的安全参数标为p1,q1,g1和公开钥y1
p="800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1"
p1=int(p,16)
q="f4f47f05794b256174bba6e9b396a7707e563c5b"
q1=int(q,16)
#print(p1)
g="5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291"
g1=int(g,16)
y="84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17"
y1=int(y,16)
#hm1、r、s分别为被签名的消息的SHA1值、签名r、s
hm="d2d0714f014a9784047eaeccf956520045c45265"
hm1=int(hm,16)
r=548099063082341131477253921760299949438196259240
s=857042759984254168557880549501802188789837994940
#快速求幂模函数:y=x0^y0 mod z0
def miqumo (x0,y0,z0):
    result=1
    while y0!=0:
        if (y0&1)==1:
            result=(result*x0)%z0
        y0>>=1
        x0=(x0*x0)%z0
    return result
number=0
for k in range (2**16):
    temp=miqumo(g1,k,p1)
    temp%=q1
    number+=1
    if temp==r:
        break
    else:
        pass
print("k=",k)
x2=1
y2=0
def exgcd(a,b):
    global x2
    global y2
    if(b==0):
        x2=1
        y2=0
        return a
    ngcd=exgcd(b,a%b)
    temp=x2
    x2=y2
    y2=temp-a//b*y2
    return ngcd
def inverse(a,p):
    global x2
    gcd=exgcd(a,p)
    if(gcd==1):
        x2=(x2%p+p)%p
        return x2
    else:
        print("求乘法逆元时两数字不互质")
#r2为r1的mod q1情况下的乘法逆元
r2=inverse(r,q1)
x=r2*(k*s-hm1)%q1
print("x=",x,"\n")
x1=hex(x) [2:]
a3=hashlib.sha1()
b3=str(x1)
c3=b3.encode(encoding="utf-8")
a3.update(c3)
d3=a3.hexdigest()
print("数据(16进制)的sha1值如下:\n",d3)
input("执行完毕,按任意键退出")

(3)运行结果:
运行结果

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值