码迷,mamicode.com
首页 > 其他好文 > 详细

密码学之《数字签名》

时间:2014-12-24 23:58:59      阅读:860      评论:0      收藏:0      [点我收藏+]

标签:

周六要考密码学了,恰逢身体不舒服,没心情看数字什么的,来整理整理数字签名的一点儿知识点~简简单单的几行文字,看官笑看即可~

 

什么是数字签名?有毛用?

数字签名主要用于对数字消息进行签名,以防消息的冒名伪造或篡改,也可以用作通信双方的身份鉴别。

为什么数字签名有这样那样的作用?

数字签名有这样几个特性:

1. 可信。任何人都可以验证签名的有效性

2. 不可伪造。除了合法的签名者,任何其他人伪造签名是困难的。

3. 不可复制。对一个消息的签名不能通过复制变成另一个消息的签名,若是复制得到,任何人都能检测出来,从而拒绝签名信息。

4. 不可篡改。一旦签名消息被篡改,任何人都可以发现消息与签名之间的不一致性。

5. 不可抵赖。签名者不能否认自己的签名。

既然数字签名这么刁扎天,那具体怎么实现呢?

数字签名的基础是公钥密码。至于公钥密码,之后再做整理。

这里介绍三种数字签名,RSA签名方案,EIGamal签名方案,DSA签名方案。

RSA签名方案过程:

1. A用保密密钥对消息m加密,密文s就是A对消息的签名

2. A将签名的消息(m,s)发给B

3. B用A的公开密钥对s进行解密,得到m‘。如果m‘=m,则为有效签名。

加密和解密的过程以及密钥的生成的过程都和RSA算法一致(细节见:http://www.cnblogs.com/kuoaidebb/p/4111865.html)

这样的签名方案有几个缺点。首先,对任意y,任何人都可以计算x=y^e mod n,任何人都可以伪造对随机消息x的签名y。其实,如果消息x1和x2的签名分别为y1,y2,任何知道x1,y1,x2,y2的人都可以伪造对消息x1x2的签名y1y2。这是因为在RSA中,Sig(x1,x2)=Sig(x1)Sig(x2).最后,是如果要加密的消息比较长,需要先对消息进行分组,然后对每组消息进行签名。这样做的后果是签名变长,签名速度变慢。解决上述问题的方法之一,是对消息进行签名之间做Hash变换,再对变换后的消息进行签名。

EIGamal签名方案过程:

1. 选取大素数p,g.p,g公开

2. 随机选取整数x作为保密密钥,1<=x<=p-2,计算公开密钥y=g^x mod p

3. 签名:秘密选取整数k(1<=k<=p-2),对消息m的签名如下:

  r=g^k mod p

  Sig(m)=(r, (m-xr)*k^-1 mod (p-1))

4. 签名验证:对得到的签名(r,o),如果满足如下条件,则为有效签名。

  y^r * r^o = g^m mod p

DSA签名过程:

细节比较繁琐,就不仔细列举了,原理跟上面的两种差不多,唯一特殊的一点是在加密之前对明文做了hash处理。

附上python版的实现,其中hash加密用了sha-1,从git上下载了一下稍微改了一下:

技术分享
dsa.py
#coding:utf-8
from random import randint
import math
from sys import exit
from sha1 import sha1

# n^-1 mod u
def ExtendedEuclid(n,u):
    x1=y2=1
    x2=y1=0
    if n>u:
        x3,y3=[n,u]
    else:
        x3,y3=[u,n]

    while 1:
        if y3==0:
            return x3+u
        elif y3==1:
            return y2+u

        q=x3/y3
        t1,t2,t3=[x1-q*y1,x2-q*y2,x3-q*y3]
        x1,x2,x3=[y1,y2,y3]
        y1,y2,y3=[t1,t2,t3]

def cal_g(p,q):
    h=randint(1,p-1)
    temp=h ** ((p-1)/q) % p
    if temp > 1:
        return temp;
    else:
        cal_g(p,q)

if __name__==__main__:
    p=839
    q=419
    g=cal_g(p,q)
    message=raw_input(请输入要加密的消息内容: )

    x = int(raw_input(请选择密钥,0~%d之间任意整数:  %(q)))
    y = g ** x % p
    print "公开参数如下:p:%d,q:%d,g:%d,y(公钥):%d" %(p,q,g,y)
    print "当前的私钥为:x:%d" %(x)

    k = randint(0,q)
    r = g ** k %p % q;
    s = ( ExtendedEuclid(k,q) * ( (long(sha1(message),16)+x*r)%q ) )%q;
    print("签名结果为:(r,s):(%d,%d)" %(r,s))

    w = ExtendedEuclid(s,q);
    u1 = long(sha1(message),16)*w % q
    u2 = r*w % q

    if (g**u1 * y**u2 %p)%q == r:
        print "签名可用"
    else:
        print "签名不可用"


sha1.py
#coding:utf-8
import struct

def _left_rotate(n, b):
    return ((n << b) | (n >> (32 - b))) & 0xffffffff
    
def sha1(message):
    h0 = 0x67452301
    h1 = 0xEFCDAB89
    h2 = 0x98BADCFE
    h3 = 0x10325476
    h4 = 0xC3D2E1F0
    
    original_byte_len = len(message)
    original_bit_len = original_byte_len * 8
    message += b\x80 #填充一位1
    message += b\x00 * ((56 - (original_byte_len + 1) % 64) % 64)  # 填充0到第448位
    message += struct.pack(b>Q, original_bit_len)     #最后64位填充前消息长度的前64位
    
    for i in range(0, len(message), 64):    # every range for 512 byte
        w = [0] * 80
        for j in range(16):
            w[j] = struct.unpack(b>I, message[i + j*4:i + j*4 + 4])[0]
        for j in range(16, 80):
            w[j] = _left_rotate(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1)

        a = h0
        b = h1
        c = h2
        d = h3
        e = h4
    
        for i in range(80):
            if 0 <= i <= 19:
                f = d ^ (b & (c ^ d))
                k = 0x5A827999
            elif 20 <= i <= 39:
                f = b ^ c ^ d
                k = 0x6ED9EBA1
            elif 40 <= i <= 59:
                f = (b & c) | (b & d) | (c & d) 
                k = 0x8F1BBCDC
            elif 60 <= i <= 79:
                f = b ^ c ^ d
                k = 0xCA62C1D6
    
            a, b, c, d, e = ((_left_rotate(a, 5) + f + e + k + w[i]) & 0xffffffff, a, _left_rotate(b, 30), c, d)
    
        h0 = (h0 + a) & 0xffffffff
        h1 = (h1 + b) & 0xffffffff 
        h2 = (h2 + c) & 0xffffffff
        h3 = (h3 + d) & 0xffffffff
        h4 = (h4 + e) & 0xffffffff
    
    return %08x%08x%08x%08x%08x % (h0, h1, h2, h3, h4)
View Code

 

 

参考资料:

《现代密码学》第二版 陈鲁生等著

 

密码学之《数字签名》

标签:

原文地址:http://www.cnblogs.com/kuoaidebb/p/4183605.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!