數字簽名就是隻有消息的發送者才能產生的別人沒法僞造的一段數字串,這段數字串是對信息真實性的有效證實。算法
非對稱加密中,公鑰用於加密,私鑰用於解密
。數字簽名中相反,私鑰生成簽名,公鑰驗證簽名
。編程
先用單向散列函數求出消息的散列值,而後再將散列值進行加密。數組
案例一緩存
package main import ( "crypto/rsa" "crypto/rand" "fmt" "crypto/md5" "encoding/base64" "crypto" ) //用公鑰加密,私鑰解密 //用私鑰簽名,公鑰驗證 //公鑰是公開的,任何人能夠使用公鑰,私鑰非公開(保存好) //一,編程實現,公鑰加密,私鑰解密的過程 func crypt() { //建立私鑰 priv, _ := rsa.GenerateKey(rand.Reader, 1024) fmt.Println("輸出系統自動產生的私鑰", priv) //建立公鑰 pub := priv.PublicKey //準備加密的明文 org := []byte("hello kongyixueyuan") //公鑰加密 cipherTxt, _ := rsa.EncryptOAEP(md5.New(), rand.Reader, &pub, org, nil) //打印密文 fmt.Println("密文爲:", cipherTxt) fmt.Println("密文爲:", base64.StdEncoding.EncodeToString(cipherTxt)) //用私鑰解密 plaintext, _ := rsa.DecryptOAEP(md5.New(), rand.Reader, priv, cipherTxt, nil) //打印解密後的結果 fmt.Println("明文爲:", string(plaintext)) } //二,編程實現,私鑰簽名,公鑰驗證的過程 func sign() { //建立私鑰 priv, _ := rsa.GenerateKey(rand.Reader, 1024) //建立公鑰 pub := &priv.PublicKey plaintxt := []byte("zhaoyingkui") //實現hash散列 h := md5.New() h.Write(plaintxt) hashed := h.Sum(nil) //經過RSA實現數字簽名 //數組簽名的做用爲驗證是否被篡改,A->B,當B收到數據時,驗證是否由A傳遞的消息 opts := rsa.PSSOptions{rsa.PSSSaltLengthAuto, crypto.MD5} sig, _ := rsa.SignPSS(rand.Reader, priv, crypto.MD5, hashed, &opts) fmt.Println("簽名的結果爲", sig) //經過公鑰實現驗證簽名 err := rsa.VerifyPSS(pub, crypto.MD5, hashed, sig, &opts) if err == nil { fmt.Println("驗證成功") } } func main() { //crypt() sign() }
案例二
server.go網絡
package main import ( "net" "fmt" "encoding/pem" "crypto/x509" "crypto/rsa" "crypto/md5" "crypto" ) //接收網絡傳送過來的數據 //公鑰驗籤 var publicKey = []byte(` -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyOnQ8Dbm1/UIkmSfeMKd K1LRJGX7T18vjZ7P4w3f/Jft/LKCwkxyC2H7x03An+EdHP7dreRhNytzbQaseIgH EYjFapaCEz+JpMNm+qY4ZpApzvPvqm/tut4T1J0HG33iiBqnyMJRZg8LjUXV2tEw fnHm5yCX36kOkN/YCW7ZbeO6aqw7gMyvJDiLGIYgCy2Daqe1MH1RP91djrt6tWcf qVmUR+HxvJFkvUZZHqFUUZyJefNcY7JQDLSz5F22VB7ZLd9sSX38My353pNy4D19 yeo5/54Z5AbSeRUMYJSFFbxwJzfewyVq2nV7EUJEj7lk0NmksB+S6w1a+a8cWydJ /QIDAQAB -----END PUBLIC KEY----- `) func Recive() []byte { netListen, _ := net.Listen("tcp", "127.0.0.1:1234") defer netListen.Close() //監聽端口,並接收數據 for { conn, _ := netListen.Accept() //設置接收數據的內存緩存 data := make([]byte, 2048) for { n, _ := conn.Read(data) //返回接收的數據 return data[:n] } } } func main() { //fmt.Println(Recive()) //得到接收到的數據 data := Recive() //拆分數據 plaintxt := data[:11] fmt.Println("接收的名文爲", string(plaintxt)) //得到接收到的數據中的數字簽名的結果 sig := data[11:] //經過公鑰作驗證 block, _ := pem.Decode(publicKey) pubInterface, _ := x509.ParsePKIXPublicKey(block.Bytes) pub := pubInterface.(*rsa.PublicKey) //驗證發送方是否爲zhaoyingkui h := md5.New() h.Write([]byte(plaintxt)) hashed := h.Sum(nil) e := rsa.VerifyPSS(pub, crypto.MD5, hashed, sig, nil) if e == nil { fmt.Println("接受數據成功,數據確實是",string(plaintxt)) } }
client.gotcp
package main import ( "crypto/md5" "encoding/pem" "crypto/x509" "crypto/rsa" "crypto" "crypto/rand" "net" "fmt" ) //發送消息,須要對數據進行簽名 //私鑰作簽名 var privateKey = []byte(` -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAyOnQ8Dbm1/UIkmSfeMKdK1LRJGX7T18vjZ7P4w3f/Jft/LKC wkxyC2H7x03An+EdHP7dreRhNytzbQaseIgHEYjFapaCEz+JpMNm+qY4ZpApzvPv qm/tut4T1J0HG33iiBqnyMJRZg8LjUXV2tEwfnHm5yCX36kOkN/YCW7ZbeO6aqw7 gMyvJDiLGIYgCy2Daqe1MH1RP91djrt6tWcfqVmUR+HxvJFkvUZZHqFUUZyJefNc Y7JQDLSz5F22VB7ZLd9sSX38My353pNy4D19yeo5/54Z5AbSeRUMYJSFFbxwJzfe wyVq2nV7EUJEj7lk0NmksB+S6w1a+a8cWydJ/QIDAQABAoIBAAQo+z+OE3eTRksp tDee5/w2qcf0KKD7GpP3HtzXs7SaPL5Hv/df99iOfdUhogRtd9na2SI5oV2wE6LF SZrxThwp1dSgKy9U2HfF6AL2oCJXh9YWLPc9fBGreYOkgLosAB3LV4ALrf3L//Q7 5vKx9CwaFarhfOOPr5KGYAXJ+syQqi3CjQrPGTLsoyYPB5oc5CA45eHIctoS90M3 cCRb5pu8vlbmeMUh9G9GMdjD3zuefndOBnwcpErLf2xPuM/Qav9LI7bP25UaZe1u zuTm93AjAtjS9zTvyqbVx/xq7C+LA4EaEeBzxNuUPHAGEhuf4kQGOPl48XKM3aNk lc/UoUECgYEA5vTg6lJKkyHvA5JJvOLSRqrGd220TvO0EPmdp3PUGSFWdldC1ev1 M42f8tbzBBeQJlIMBTeGi5Sa8QRVVZXWYmjKkcpDreZJCKz4dVPyeg93MRUhDA7J 8+2GSypKO+MpTty3WY7y0K0Lyk7381to7QTfqXzMc1d/Q/W2rqdrITECgYEA3rL3 4EzaxisRG9yaxu1ndGFcaTX9JUm+RTDPd5wecfE2mrSqfWwcXjsJ/BOqim1pwPQe 1/7e6PwyPqqd9It+E5f3zLwN5fvHISSjawU+sCLgpPY4YQvybf2cLsfyQrIQw1Ig 4Mo+DTBp4EAGYLszn/8yk7A6PIkev/+W22s1oo0CgYEArYriGpC9QrOj4t4glFMn yDv4p7MCYrUS4BKA2VvaywtW6dOGADKubA+GWbYUo0WFZpYOPDlN20JN7r7f1FC1 6Axv8n62vkwlIuS+SYNL11YZrQMAcwwFykn3uDFN2JRH7N9C0oPshssQ6fLOs8lD HZ6k5blF84GSuqE+pRxeDnECgYAagUJvN7ZyD34hysfBFVBS0aOmAf73CSfUJFMM 8U/OT98n2ojQFKXrsSsnDVAm2Y7UoDlri7IMGLgCLVxPVqrSuiuL+nXNAYJZt3qb qiwj2oLSH1vmcP2RibWk+7chqP/Fv2iaWHe6KiDvx676pE0opb7nRPopakh2oXz1 8I+ZoQKBgDR/aXBDXcDzHC4dM3dYzkSf0bn8LXyANkEjHovSH/QSs4m+d2BkGlSy yB3kgNSnEa9vNoffQcRvRlQbS58zTF8Z4iGjnoCHS6Q2yJBFm9L+EaRJlF6tOERk ngLn8mAtV/IGigWBpZCVeEIHH1nG1DLatF2VDCQifQXZ5oRcZZr6 -----END RSA PRIVATE KEY----- `) func SignData(msg string) []byte { //準備簽名的數據 plaintxt:=[]byte(msg) h:=md5.New() h.Write(plaintxt) hashed:=h.Sum(nil) fmt.Println(hashed) //將字節數組轉換成私鑰類型 block,_:=pem.Decode(privateKey) priv,_:=x509.ParsePKCS1PrivateKey(block.Bytes) //簽名 opts:=&rsa.PSSOptions{rsa.PSSSaltLengthAuto,crypto.MD5} sig,_:=rsa.SignPSS(rand.Reader,priv,crypto.MD5,hashed,opts) //返回簽名結果 return sig } //經過TCP將數據和簽名結果發送給接收端 func Send(data []byte) { conn,_:=net.ResolveTCPAddr("tcp4","127.0.0.1:1234") n,_:=net.DialTCP("tcp",nil,conn) //將數據經過tcp協議發送給接收方 n.Write(data) fmt.Println("發送結束") } func main() { //得到簽名的結果 var dt = "hello world" sg:=SignData(dt) //dt是準發送出去的數據 var data = make([]byte,len(dt)+len(sg)) copy(data[0:11],[]byte(dt)) copy(data[11:],sg) //data數組其實有兩部分組成,發出去的數據+簽名結果 Send(data) }
一種利用橢圓曲線密碼來實現的數字簽名算法。函數