日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实现数字签名

發(fā)布時(shí)間:2025/3/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现数字签名 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

實(shí)現(xiàn)數(shù)字簽名

數(shù)字簽名算法(DSA)

數(shù)字簽名算法(DSA,Digital Signature Algorithm),是一種公開密鑰算法,不能用于加密,只能用于數(shù)字簽名。主要用作為接收者驗(yàn)證數(shù)字的完整性和數(shù)據(jù)發(fā)送者的身份,DSA算法的安全性基于解離散對(duì)數(shù)的困難性。

package mainimport ("crypto/dsa""crypto/rand""fmt" )func main() {var params dsa.Parameters//生成參數(shù) if e := dsa.GenerateParameters(&params, rand.Reader, dsa.L1024N160); e != nil {fmt.Println(e)}//生成私鑰 var priv dsa.PrivateKeypriv.Parameters = paramsif e := dsa.GenerateKey(&priv, rand.Reader); e != nil {fmt.Println(e)}//根據(jù)私鑰生成公鑰 pub := priv.PublicKey//消息 message := []byte("hello world")//使用私鑰進(jìn)行簽名,產(chǎn)生整數(shù)對(duì)(r,s) r, s, e := dsa.Sign(rand.Reader, &priv, message)if e != nil {fmt.Println(e)}//認(rèn)證 fmt.Printf("認(rèn)證 %q (r:%s,s:%s)\n", message, r, s)if dsa.Verify(&pub, message, r, s) {fmt.Println("認(rèn)證正確!")} else {fmt.Println("認(rèn)證失敗!")} }

公鑰加密算法(RSA)

公鑰加密算法于1987年首次公開,RSA是提出這個(gè)算法的三人姓氏開頭字母組成,可用于加密,也可以用于數(shù)字簽名。RSA的安全性基于大數(shù)分解的困難性。

加密算法:

  • 最優(yōu)非對(duì)稱加密填充(OAEP,Optimal Asymmetric Encryption Padding),在隨機(jī)預(yù)言模型下,用來處理非對(duì)稱加密前的明文;

  • 公鑰密碼學(xué)標(biāo)準(zhǔn)(PKCS,The Public-Key Cryptography Standards),是由美國RSA數(shù)據(jù)安全公司及其合作伙伴制定的一組公鑰密碼學(xué)標(biāo)準(zhǔn),其中包括證書申請(qǐng)、證書更新、證書作廢表發(fā)布、擴(kuò)展證書內(nèi)容以及數(shù)字簽名、數(shù)字信封的格式等方面的一系列相關(guān)協(xié)議。

簽名認(rèn)證:

  • 公鑰密碼學(xué)標(biāo)準(zhǔn)(PKCS);

  • 概率簽名方案(PSS,Probabilistic Signature Scheme),與PKCS不同的是,它支持添加鹽(Salt)。

package mainimport ("crypto""crypto/md5""crypto/rand""crypto/rsa""fmt" )func main() {//生成私鑰 priv, e := rsa.GenerateKey(rand.Reader, 1024)if e != nil {fmt.Println(e)}//根據(jù)私鑰產(chǎn)生公鑰 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.Println(e)}fmt.Printf("\t%x\n", ciphertext)//解密得到明文 fmt.Printf("解密:\n")plaintext, e = rsa.DecryptOAEP(md5.New(), rand.Reader, priv, ciphertext, nil)if e != nil {fmt.Println(e)}fmt.Printf("\t%q\n", plaintext)//消息先進(jìn)行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{SaltLength: rsa.PSSSaltLengthAuto, Hash: crypto.MD5}sig, e := rsa.SignPSS(rand.Reader, priv, crypto.MD5, hashed, opts)if e != nil {fmt.Println(e)}fmt.Printf("簽名:\n\t%x\n", sig)//認(rèn)證 fmt.Printf("驗(yàn)證結(jié)果:")if e := rsa.VerifyPSS(pub, crypto.MD5, hashed, sig, opts); e != nil {fmt.Println("失敗:", e)} else {fmt.Println("成功.")} }

橢圓曲線加密算法

ECDSA的全名是Elliptic Curve DSA,即橢圓曲線DSA。它是Digital Signature Algorithm (DSA)應(yīng)用了橢圓曲線加密算法的變種。橢圓曲線算法的原理很復(fù)雜,但是具有很好的公開密鑰算法特性,通過公鑰無法逆向獲得私鑰。

  • 簽名過程

    假設(shè)要簽名的消息是一個(gè)字符串:“Hello World!”。DSA簽名的第一個(gè)步驟是對(duì)待簽名的消息生成一個(gè)消息摘要。不同的簽名算法使用不同的消息摘要算法。而ECDSA256使用SHA256生成256比特的摘要。
    摘要生成結(jié)束后,應(yīng)用簽名算法對(duì)摘要進(jìn)行簽名:
    產(chǎn)生一個(gè)隨機(jī)數(shù)k
    利用隨機(jī)數(shù)k,計(jì)算出兩個(gè)大數(shù)r和s。將r和s拼在一起就構(gòu)成了對(duì)消息摘要的簽名。
    這里需要注意的是,因?yàn)殡S機(jī)數(shù)k的存在,對(duì)于同一條消息,使用同一個(gè)算法,產(chǎn)生的簽名是不一樣的。從函數(shù)的角度來理解,簽名函數(shù)對(duì)同樣的輸入會(huì)產(chǎn)生不同的輸出。因?yàn)楹瘮?shù)內(nèi)部會(huì)將隨機(jī)值混入簽名的過程。

  • 驗(yàn)證過程
    關(guān)于驗(yàn)證過程,這里不討論它的算法細(xì)節(jié)。從宏觀上看,消息的接收方從簽名中分離出r和s,然后利用公開的密鑰信息和s計(jì)算出r。如果計(jì)算出的r和接收到的r值相同,則表示驗(yàn)證成功。否則,表示驗(yàn)證失敗。

  • package mainimport ("fmt""crypto/ecdsa""crypto/elliptic""crypto/rand""crypto/sha256""math/big" )func main() {//明文 message := []byte("Hello world")key, err := NewSigningKey()if err != nil {return}signature, err := Sign(message, key)fmt.Printf("簽名后:%x\n", signature)if err != nil {return}if !Verify(message, signature, &key.PublicKey) {fmt.Println("驗(yàn)證失敗!")return}else{fmt.Println("驗(yàn)證成功!")} }func NewSigningKey() (*ecdsa.PrivateKey, error) {key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)return key, err }// Sign signs arbitrary data using ECDSA. func Sign(data []byte, privkey *ecdsa.PrivateKey) ([]byte, error) {// hash messagedigest := sha256.Sum256(data)// sign the hashr, s, err := ecdsa.Sign(rand.Reader, privkey, digest[:])if err != nil {return nil, err}// encode the signature {R, S}// big.Int.Bytes() will need padding in the case of leading zero bytesparams := privkey.Curve.Params()curveOrderByteSize := params.P.BitLen() / 8rBytes, 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 {// hash messagedigest := sha256.Sum256(data)curveOrderByteSize := pubkey.Curve.Params().P.BitLen() / 8r, s := new(big.Int), new(big.Int)r.SetBytes(signature[:curveOrderByteSize])s.SetBytes(signature[curveOrderByteSize:])return ecdsa.Verify(pubkey, digest[:], r, s) }

    總結(jié)

    以上是生活随笔為你收集整理的实现数字签名的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。