數字簽名演算法(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...