数字签名分类及解析

数字签名在信息安全,包括身份认证、数据完整性、不可否认性以及匿名性有着重要应用,是现代密码学的重要分支。

attachments-2018-03-9MDlTgOS5aa74ab46b850.png

作者:菲菲

原来链接:http://t.cn/EGlvnIE

本文约4700字+,阅读(观看)需要26分钟

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


数字签名在信息安全,包括身份认证、数据完整性、不可否认性以及匿名性有着重要应用,是现代密码学的重要分支。签名隶属于公钥密码学。签名过程:发送方用自己的私钥对发送信息进行所谓的加密运算,得到一个hash值,该hash值就是签名。使用时需要将签名和信息发给接收方。接受者用发送方公开的公钥和接收到的信息对签名进行验证,通过认证,说明接收到的信息是完整的、准确的,否则说明消息来源不对。


简单描述数字签名:私钥签名;公钥验签。


1 普通签名


签名只是用一把私钥,并且是发送方自己进行地签名动作,这类签名就是普通签名。常用的签名方法有较多,包括RSA数字签名、DSS数字签名、ElGamal数字签名、ECDSA数字签名等等。其中RSA和ECDSA签名已经在加密算法中有讲解。区块链项目中最常用的签名方法是ECDSA数字签名。签名和验签的原理不作讲解,感兴趣可以翻阅之前的章节。


因为ECDSA数字签名在区块链的重要性,我接下来只对它进行讲解如何应用。


下边代码展示简单地用ECDSA签名对数据BLOCK进行签名,上链之前需要先进行验证,验证通过之后才能上链。具体解析在代码中有说明。


过程:


1.通过ecdsa.GenerateKey产生一私钥;输出的私钥是指针类型;

2.通过私钥产生公钥;

3.对数据BLOCK进行hash运算,实际公链中就是挖矿过程;

4.为了可以给任何长度的data进行签名,我们创建自己的签名方法;

5.验证数据是否合法,也就是通过公钥对签名进行验证,通过后才能对数据进行上链动作。


package main


import (


    "bytes"

    "encoding/binary"

    "log"

    "time"

    "crypto/sha256"

    "fmt"

    "crypto/ecdsa"

    "crypto/elliptic"

    "crypto/rand"

    "math/big"

)


//简单的区块链块结构

type Block struct {

    //1. 区块高度

    Height int64

    //2. 上一个区块HASH

    PrevBlockHash []byte

    //3. 交易数据

    Data []byte

    //4. 时间戳

    Timestamp int64

    //5. 实际通过挖矿得到Hash

    Hash []byte

    // 6. 随机数Nonce

    Nonce int64


}


func main()  {


   //调用底层函数,产生私钥

    prk,_:=ecdsa.GenerateKey(elliptic.P256(),rand.Reader)


    //生成公钥

    pubkey:=prk.PublicKey


    //需要上链的数据

    data:=[]byte("helloworld")


    //手动创建一个区块信息,实际中,通过交易来触发自动创建block

    block:=&Block{2,nil,data,time.Now().Unix(),nil,0}


    //将block信息内容拼接成字节数组

    blockbytes:=prepareData(block)


    //对block进行hash运算,实际中是挖矿过程

    blockHash:=sha256.Sum256(blockbytes)


  //签名

    signatrue,_:=Sign(blockHash[:],prk)


   //验证,如果通过就进行上链处理,否则rollback

    if Verify(blockHash[:],signatrue,&pubkey){

        fmt.Println("该block合法,可以上链")

    }else {

        fmt.Println("该Block不合法,rollback")

    }

}


//数据拼接

func  prepareData(block *Block) []byte {

    Block:=block

    data := bytes.Join(

        [][]byte{

            Block.PrevBlockHash,

            Block.Data,

            IntToHex(Block.Timestamp),

            Block.Data,

            IntToHex(int64(Block.Nonce)),

            IntToHex(int64(Block.Height)),

        },

        []byte{},

    )

    return data

}


// 将int64转换为字节数组

func IntToHex(num int64) []byte {

    buff := new(bytes.Buffer)

    err := binary.Write(buff, binary.BigEndian, num)

    if err != nil {

        log.Panic(err)

    }


    return buff.Bytes()

}


func Sign(data []byte, privkey *ecdsa.PrivateKey) ([]byte, error) {

    // 对要签名的信息进行sha256散列,生成一个长度为32的字节数组

    digest := sha256.Sum256(data)


    // 通过椭圆曲线方法对散列后的明文进行签名,返回两个big.int类型的大数

    r, s, err := ecdsa.Sign(rand.Reader, privkey, digest[:])

    if err != nil {

        return nil, err

    }

    //将大数转换成字节数组,并拼接起来,形成签名

    signature := append(r.Bytes(), s.Bytes()...)

    return signature, nil

}


// 通过公钥验证签名

func Verify(data, signature []byte, pubkey *ecdsa.PublicKey) bool {

    // 将明文转换成字节数组

    digest := sha256.Sum256(data)


    //声明两个大数r,s

    r := big.Int{}

    s := big.Int{}

    //将签名平均分割成两部分切片,并将切片转换成*big.int类型

    sigLen := len(signature)

    r.SetBytes(signature[:(sigLen / 2)])

    s.SetBytes(signature[(sigLen / 2):])


    //通过公钥对得到的r,s进行验证

    return ecdsa.Verify(pubkey, digest[:], &r, &s)

}


2 群签名


1991年,Chaum和Van Heyst首次提出了群签名的概念。群签名允许一个群体中的任意一个成员以匿名的方式代表整个群体对消息进行签名。


群签名需要有一个集体,一般是公司。管理员通过认证添加群签名的成员,每个成员的签名都代表集体。利用群签名可以很好的隐藏组织结构。例如,一个公司的职员可以利用群签名方案代表公司进行签名,验证者(可能是公司顾客)只需要利用公司的群公钥进行签名的合法性验证。验证者并不知道该签名是由哪个职员所签名的。当发生争议时,群管理员可以识别出实际的签名者。当然,群签名还可以应用于电子投票、电子投标和电子现金等。


如何实现群签名呢?


入群:群成员在入群之前都会向群管理进行申请入群,通过后,申请人会和群管理员达成交互式协议,该协议可生成群成员的私钥。群管理员对该密钥进行签名,并颁发给申请人,完成入群。群成员群管理员将群公钥对外公开。


签名:群成员通过自己的群密钥和群公钥对消息进行签名,得到群签名。


验证:通过输入群公钥和群签名用公开的某种验证方法进行验证,返回值只有真假,验证者无法计算得到签名者是群公钥里的具体人员,只知道该签名者属于群公钥里的,可以代表群体。


追踪:群管理员可以通过群签名得到具体是哪个群成员进行签名的。

群签名是一个中心化的签名结构,该结构的算法都是群管理员定的,造成签名者的隐私没有做到真正的保障。


所以总结群签名有三点:


1.只有群体中的合法成员才能代表整个群体进行签名;

2.接收者可以用群公钥验证群签名的合法性,但不知道该群签名是群体具体哪个成员所签;

3.在发生争议时,群管理员可以识别出实际的签名者。


3 环签名


环签名由Rivest,shamir和Tauman三位密码学家在2001年首次提出。因签名中参数Ci(i=1,2,…,n)根据一定的规则首尾相接组成环状而得名。其实就是实际的签名者用其他可能签名者的公钥产生一个带有断口的环,然后用私钥将断口连成一个完整的环。


环签名可以认为是不可追踪的群签名,实际的操作过程都是自己完成的,没有群管理员。


签名者是某个群体的成员,他把其他群体的公钥拿来并加上自己的公钥组合成一个群公钥,然后用自己的私钥和群公钥对要发布的信息进行环签名。接收者接收到群公钥、签名和信息,然后对签名进行验证,如果签名来自群公钥,那么验证成功,否则消息不合法。


群公钥中签名者的公钥只是迷惑作用,并不对数据有任何操作。


形成的签名因为是每个其它群公钥产生的数据和自己用私钥产生的数据组成的环,自己的数据隐藏环中,攻击者很难找到签名者的公钥。所以签名者的隐私很好地被保护起来了。


4 代理签名


1996年,Mambo等人首次提出了代理签名的概念。在代理签名方案中,允许一个原始签名者把他的签名权利委托给一个称为代理签名者的人,然后代理签名者就可以代表原始签名者进行签名。代理签名者可用于需要委托权力的密码协议中,如电子现金、移动代理和移动通信等。


5 盲签名


1982年Chaum首次提出了盲签名的概念。盲签名允许使用者获得一个消息的签名,而签名者既不知道该消息的内容,也不知道该消息的签名。盲签名可用于需要提供匿名性的密码协议中,如电子投票和电子现金。


一个盲签名方案由以下部分组成。


1)消息盲化:使用者利用盲因子对要签名的信息进行盲化处理,然后将盲化后的消息发送给签名者。

2)盲消息签名:签名者对盲化后的消息进行签名,因此他并不知道真实消息的具体内容。

3)恢复签名:使用者除去盲因子,得到真实消息的签名。


6 零知识证明


零知识证明:实质上是一种涉及两方或更多方的协议,即两方或更多方完成一项任务所需采取的一系列步骤。证明者向验证者证明并使其相信自己知道或拥有某一消息,但证明过程不能向验证者泄漏任何关于被证明消息的信息。简单理解,就是证明者能够在不向验证者提供任何有用信息的情况下,让验证者相信你。


文章发布只为分享区块链技术内容,版权归原作者所有,观点仅代表作者本人,绝不代表区块链兄弟赞同其观点或证实其描述。

attachments-2018-02-kL1zBfXx5a7ffd0b78798.jpg

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
不写代码的码农
社区运营-小以

626 篇文章

作家榜 »

  1. 社区运营-小以 626 文章
  2. 社区运营-小链 243 文章
  3. 涂晶 81 文章
  4. 于中阳Mercina-zy 79 文章
  5. 李晓琼 44 文章
  6. 兄弟连区块链培训 42 文章
  7. 吴寿鹤 36 文章
  8. John-smith 25 文章