golang实现摘要签名和验证

CodingCode · · 2163 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang实现摘要签名和验证的过程:

两个步骤:

  1. 利用私钥对一个摘要进行签名。
$ ./test -command sign -key ./privatekey.pem -text "12345"
MEUCIE7DsGmTHJ3VGZec2UF9hRX7jq9Yd7F2kS7kEL132js8AiEA/ZlyIpo86Rn3waR8m2c4BtQPu8cNjYAnroibK+ujslY=
  1. 利用公钥验证签名是否有效。
$ ./test -command verify -cert ./publickey.pem -text "12345" -sign "MEQCIFuvcVHlztAN7YVehgCDYzVSo1Q10iTKeJE5ydxzfih5AiAC2ETt/8XuE1VHaGkLsiJkRSueh65Leq2VKkmFKxB/sQ=="
Successed to verify Signature and nonce

下面是代码原文:

package main

import (
    "fmt"
    "flag"
    "io/ioutil"
    "math/big"
    "crypto/ecdsa"
    "crypto/rand"
    "crypto/sha256"
    "crypto/x509"
    "encoding/asn1"
    "encoding/base64"
    "encoding/pem"
)

type ECDSASignature struct {
    R, S *big.Int
}

var (
    command     string
    certfile    string
    keyfile     string
    text        string
    sign        string
)

func main() {
    flag.StringVar(&command,    "command",  "",   "Command: sign/verify")
    flag.StringVar(&keyfile,    "key",      "",   "Private key file")
    flag.StringVar(&certfile,   "cert",     "",   "Public key file")
    flag.StringVar(&text,       "text",     "",   "Text content to be signed")
    flag.StringVar(&sign,       "sign",     "",   "Signed content to be verifed")
    flag.Parse()

    switch command {
    case "sign":
        if keyfile == "" || text == "" {
            fmt.Printf("ERROR: either key file or text is empty\n")
            return
        }
        Sign(keyfile, text)
    case "verify":
        if certfile == "" || text == "" || sign == "" {
            fmt.Printf("ERROR: either key file or text or sign is empty\n")
            return
        }
        Verify(certfile, text, sign)
    default:
        fmt.Printf("ERROR: unknown command\n")
        return
    }

}

func Sign(keyFile, text string) {
    keyBuff, err := ioutil.ReadFile(keyFile)
    if err != nil {
        fmt.Printf("ERROR: failed to read keystore file: %s, error: %v\n", keyFile, err)
        return
    }

    block, _ := pem.Decode(keyBuff)
    if block == nil {
        fmt.Printf("ERROR: block of decoded private key is nil\n")
        return
    }

    privKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
    if err != nil {
        fmt.Printf("ERROR: failed get ECDSA private key, %v\n", err)
        return
    }
    ecPrivKey := privKey.(*ecdsa.PrivateKey)


    hash := sha256.Sum256([]byte(text))
    r, s, err := ecdsa.Sign(rand.Reader, ecPrivKey, hash[:])
    if err != nil {
        fmt.Printf("ERROR: failed to get signature, %v\n", err)
        return
    }

    // asn1 output DER format
    signature, err := asn1.Marshal(ECDSASignature{
        R: r,
        S: s,
    })
    if err != nil {
        fmt.Printf("ERROR: asn1.Marshal ECDSA signature: %v\n", err)
        return
    }

    fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(signature))
}

func Verify(certFile, text string, sign string) {
    certBuff, err := ioutil.ReadFile(certFile)
    if err != nil {
        fmt.Printf("ERROR: failed to read keystore file: %s, error: %s\n", certFile, err)
        return
    }

    block, _ := pem.Decode(certBuff)
    if block == nil {
        fmt.Printf("ERROR: block of decoded private key is nil\n")
        return
    }

    cert, err := x509.ParseCertificate(block.Bytes)
    if err != nil {
        fmt.Printf("ERROR: failed get ECDSA private key, error: %v\n", err)
        return
    }

    arr := []byte(text)
    h := sha256.New()
    h.Write(arr)
    hashed := h.Sum(nil)

    signatureDec, _ := base64.StdEncoding.DecodeString(sign)
    sig := new(ECDSASignature)
    _, err = asn1.Unmarshal(signatureDec, sig)
    if err != nil {
        fmt.Printf("ERROR: failed unmashalling signature, error: %v", err)
        return
    }

    pub, _ := cert.PublicKey.(*ecdsa.PublicKey)
    if !ecdsa.Verify(pub, hashed[:], sig.R, sig.S) {
        fmt.Printf("ERROR: Failed to verify Signature: %v\n", err)
        return
    }
    fmt.Printf("Successed to verify Signature and nonce\n")
    return
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:CodingCode

查看原文:golang实现摘要签名和验证

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2163 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传