數字簽名(Digital Signature),通俗來講是基於非對稱加密算法,用秘鑰對內容進行散列值簽名,在對內容與簽名一起發送。
數字簽名的生成個驗證
簽名
⑴ 對數據進行散列值運算。
⑵ 簽名:使用簽名者的私鑰對數據的散列值進行加密。
⑶ 數字簽名數據:簽名與原始數據。
驗證
⑴ 接收數據:原始數據&數字簽名。
⑵ 使用公鑰進行解密得到散列值。
⑶ 將原始數據的散列值與解密后的散列值進行對比。
Go語言中使用RSA進行數字簽名
⑴ pem解碼:使用pem對私鑰進行解碼, 得到pem.Block結構體
⑵ 獲得私鑰:使用GO x509接口pem.Block
據解析成私鑰結構體
⑶ 計算hash值:對明文進行散列值計算
⑷ 使用秘鑰對散列值簽名
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
)
var (
private = `-----BEGIN 私鑰-----
MIICXQIBAAKBgQDc73afIxqYOHg80puDIMYrqUAiTi8EiTVDEiO9YE3+VxRvN0sa
pe3zx1UdhgIn3iCPUzyI2vwNADId3LjuIjkdCcdB2fHrBTbcy6u0545HnY42F9aQ
7cAr168bHcqhQoKcna9i9nukO+w7So1J9C6Wr8J4e4923q7+T7z7bZeXywIDAQAB
AoGBAItX5KLdywoyo3MJCdgcNaCX8MEyOmlL+HHC4ROxx78gQN0cLJw0Bu33zHEA
ch+e8z4yKz3Nj6bLdtBqw6A9qXLBCfWfD/p9YKDZNFP/6+u9teUirOgiBSq7kXWy
mtBm0I3pz33EomCuSJzLj/Mj/fkKs+425jPFcZboJdZpCyBhAkEA8mtGUGYuAZwV
RKBDkf1bz5EyPBGV+9CyXa6pd6md61APY0j+qhb1w9ADfHKkAzfoilhpucznRhaz
kAheqMPAMwJBAOlQEx2Ytc8TxfFqhF8RPTODe2N0jBBvsvJ85k7vNiQ+hnmaAray
XS6pCbZdvmGHYKlz3MVGeis/UJKDdSzE0gkCQQCoZijkNPcEmz6S+5m00oFywXRa
EgVUdndRaMHEpIlVK7pkyBJQab60Fc42JxUUP0RExoI7VcHbCG4YQhgvuDvNAkBQ
CUolcwebe/sBcDrsqetGyqn/WjHaSZcnnDUdiu4VzOUwveaEafeRVCeiydHPfzNn
rflkK2MphtTLDhGaRAKRAkASKlhV8aTBzTty/V3XMQfFVIAdHCyEIGMdjDDSzPly
shZCn66IyIze8j5Q4ZLcRz6GPglHdrkBnyt4QFuGurpl
-----END 私鑰-----`
public = `-----BEGIN 公鑰-----
MIGJAoGBANzvdp8jGpg4eDzSm4MgxiupQCJOLwSJNUMSI71gTf5XFG83Sxql7fPH
VR2GAifeII9TPIja/A0AMh3cuO4iOR0Jx0HZ8esFNtzLq7TnjkedjjYX1pDtwCvX
rxsdyqFCgpydr2L2e6Q77DtKjUn0Lpavwnh7j3berv5PvPttl5fLAgMBAAE=
-----END 公鑰-----`
)
func digitalSign(privateKey, plainText string) (signText []byte, err error) {
var (
pemBlock, _ = pem.Decode([]byte(privateKey))
privateStream *rsa.PrivateKey
plainHash = sha256.Sum256([]byte(plainText))
)
if privateStream, err = x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err != nil {
return
}
if signText, err = rsa.SignPKCS1v15(rand.Reader, privateStream, crypto.SHA256, plainHash[:]); err != nil {
return
}
return
}
func digitalVerify(publicKeyByte, plainText string, signText []byte) (ok bool, err error) {
var (
pemBlock, _ = pem.Decode([]byte(publicKeyByte))
publicStream *rsa.PublicKey
plainHash = sha256.Sum256([]byte(plainText))
)
if publicStream, err = x509.ParsePKCS1PublicKey(pemBlock.Bytes); err != nil {
return
}
if err = rsa.VerifyPKCS1v15(publicStream, crypto.SHA256, plainHash[:], signText); err != nil {
return
}
return true, nil
}
func main() {
text, err := digitalSign(private, "張三李四王五趙柳")
ok, err := digitalVerify(public, "張三李四王五趙柳", text)
fmt.Println(ok)
fmt.Println(err)
}
總結
在Go語言API中公鑰私鑰的注釋頭尾也需要加上