【go密碼學】-數字簽名

介紹

數字簽名就是隻有消息的發送者才能產生的別人沒法僞造的一段數字串,這段數字串是對信息真實性的有效證實。算法

  • 發送者:生成簽名
  • 接受者:驗證簽名

非對稱密碼機制

非對稱加密中,公鑰用於加密,私鑰用於解密。數字簽名中相反,私鑰生成簽名,公鑰驗證簽名編程

數字簽名方法

直接對消息簽名

clipboard.png

對消息的散列值簽名

先用單向散列函數求出消息的散列值,而後再將散列值進行加密。數組

clipboard.png

數字簽名算法

RSA

案例一緩存

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)
}

DSA

ECDSA

一種利用橢圓曲線密碼來實現的數字簽名算法。函數

相關文章
相關標籤/搜索