實現數字簽名

2021-08-20 11:08:26 字數 3705 閱讀 1434

數字簽名演算法(dsa,digital signature algorithm),是一種公開金鑰演算法,不能用於加密,只能用於數字簽名。主要用作為接收者驗證數字的完整性和資料傳送者的身份,dsa演算法的安全性基於解離散對數的困難性。

package main

import (

"crypto/dsa"

"crypto/rand"

"fmt"

)func main()

//生成私鑰

var priv dsa.privatekey

priv.parameters = params

if e := dsa.generatekey(&priv, rand.reader); e != nil

//根據私鑰生成公鑰

pub := priv.publickey

//訊息

message := byte("hello world")

//使用私鑰進行簽名,產生整數對(r,s)

r, s, e := dsa.sign(rand.reader, &priv, message)

if e != nil

//認證

fmt.printf("認證 %q (r:%s,s:%s)\n", message, r, s)

if dsa.verify(&pub, message, r, s) else

}

公鑰加密演算法於2023年首次公開,rsa是提出這個演算法的三人姓氏開頭字母組成,可用於加密,也可以用於數字簽名。rsa的安全性基於大數分解的困難性。

加密演算法:

簽名認證:

package main

import (

"crypto"

"crypto/md5"

"crypto/rand"

"crypto/rsa"

"fmt"

)func main()

//根據私鑰產生公鑰

pub := &priv.publickey

//明文

plaintext := byte("hello world")

//加密生成密文

fmt.printf("%q\n加密:\n", plaintext)

ciphertext, e := rsa.encryptoaep(md5.new(), rand.reader, pub, plaintext, nil)

if e != nil

fmt.printf("\t%x\n", ciphertext)

//解密得到明文

fmt.printf("解密:\n")

plaintext, e = rsa.decryptoaep(md5.new(), rand.reader, priv, ciphertext, nil)

if e != nil

fmt.printf("\t%q\n", plaintext)

//訊息先進行hash處理

h := md5.new()

h.write(plaintext)

hashed := h.sum(nil)

fmt.printf("%q md5 hashed:\n\t%x\n", plaintext, hashed)

//簽名

opts := &rsa.pssoptions

sig, e := rsa.signpss(rand.reader, priv, crypto.md5, hashed, opts)

if e != nil

fmt.printf("簽名:\n\t%x\n", sig)

//認證

fmt.printf("驗證結果:")

if e := rsa.verifypss(pub, crypto.md5, hashed, sig, opts); e != nil else

}

ecdsa的全名是elliptic curve dsa,即橢圓曲線dsa。它是digital signature algorithm (dsa)應用了橢圓曲線加密演算法的變種。橢圓曲線演算法的原理很複雜,但是具有很好的公開金鑰演算法特性,通過公鑰無法逆向獲得私鑰。

簽名過程

假設要簽名的訊息是乙個字串:「hello world!」。dsa簽名的第乙個步驟是對待簽名的訊息生成乙個訊息摘要。不同的簽名演算法使用不同的訊息摘要演算法。而ecdsa256使用sha256生成256位元的摘要。

摘要生成結束後,應用簽名演算法對摘要進行簽名:

產生乙個隨機數k

利用隨機數k,計算出兩個大數r和s。將r和s拼在一起就構成了對訊息摘要的簽名。

這裡需要注意的是,因為隨機數k的存在,對於同一條訊息,使用同乙個演算法,產生的簽名是不一樣的。從函式的角度來理解,簽名函式對同樣的輸入會產生不同的輸出。因為函式內部會將隨機值混入簽名的過程。

驗證過程

關於驗證過程,這裡不討論它的演算法細節。從巨集觀上看,訊息的接收方從簽名中分離出r和s,然後利用公開的金鑰資訊和s計算出r。如果計算出的r和接收到的r值相同,則表示驗證成功。否則,表示驗證失敗。

package main

import (

"fmt"

"crypto/ecdsa"

"crypto/elliptic"

"crypto/rand"

"crypto/sha256"

"math/big"

)func main()

signature, err := sign(message, key)

fmt.printf("簽名後:%x\n", signature)

if err != nil

if !verify(message, signature, &key.publickey) else

}func newsigningkey() (*ecdsa.privatekey, error)

// sign signs arbitrary data using ecdsa.

func sign(data byte, privkey *ecdsa.privatekey) (byte, error)

// encode the signature

// big.int.bytes() will need padding in the case of leading zero bytes

params := privkey.curve.params()

curveorderbytesize := params.p.bitlen() /8

rbytes, sbytes := r.bytes(), s.bytes()

signature := make(byte, curveorderbytesize*2)

copy(signature[curveorderbytesize-len(rbytes):], rbytes)

copy(signature[curveorderbytesize*2-len(sbytes):], sbytes)

return signature, nil

}// verify checks a raw ecdsa signature.

// returns true if it's valid and false if not.

func verify(data, signature byte, pubkey *ecdsa.publickey) bool

C 實現數字簽名

c 實現數字簽名 using system using system.collections.generic using system.windows.forms using system.security.cryptography namespace dsaexample private void...

數字簽名簽名概述

數字簽名的技術流程描述 1 傳送者使用摘要演算法對傳送資訊產生資訊摘要 2 傳送者使用自己的私鑰對資訊摘要進行簽名 3 傳送者將資訊本身和已簽名的摘要一起傳送出去 4 接收者使用相同的摘要演算法對資訊本身計算資訊摘要 5 接收者使用傳送者的公鑰對簽名的摘要就行驗籤,獲得資訊傳送者的資訊摘要 6 接收...

rsa數字簽名實現

使用openssl庫進行封裝實現,如下 static int base64 decode char str,int str len,char decode,int decode buffer len static int base64 encode char str,int str len,char...