签名验签
1. 生成公私钥对
以下算法只支持生成RSA和ECDSA的公私钥对:
1 import ( 2 "crypto/ecdsa" 3 "crypto/elliptic" 4 "crypto/rand" 5 "crypto/rsa" 6 "crypto/x509" 7 "errors" 8 "fmt" 9 ) 10 11 // the size of ecdsa algorithm 12 const ( 13 curveP256 = 256 14 curveP384 = 384 15 curveP521 = 521 16 ) 17 18 type AlgoType uint8 19 20 const ( 21 RSA AlgoType = iota + 1 // rsa 22 ECC // ecdsa 23 ) 24 25 // GenerateKeyPairs generates a key pairs as specified in the request. Currently, 26 // only ECDSA and RSA are supported. 27 // 28 // GenerateKeyPairs returns DER encoding private key and public key. 29 func GenerateKeyPairs(algo AlgoType, size int) ([]byte, []byte, error) { 30 switch algo { 31 case RSA: 32 if size < 2048 { 33 return nil, nil, errors.New("RSA key is too weak") 34 } 35 if size > 8192 { 36 return nil, nil, errors.New("RSA key size too large") 37 } 38 priv, err := rsa.GenerateKey(rand.Reader, size) 39 if err != nil { 40 return nil, nil, fmt.Errorf("generate rsa key: %v", err.Error()) 41 } 42 pub := priv.Public() 43 pubBytes := x509.MarshalPKCS1PublicKey(pub.(*rsa.PublicKey)) 44 privBytes := x509.MarshalPKCS1PrivateKey(priv) 45 return privBytes, pubBytes, nil 46 case ECC: 47 var curve elliptic.Curve 48 switch size { 49 case curveP256: 50 curve = elliptic.P256() 51 case curveP384: 52 curve = elliptic.P384() 53 case curveP521: 54 curve = elliptic.P521() 55 default: 56 return nil, nil, errors.New("invalid ecdsa curve") 57 } 58 priv, err := ecdsa.GenerateKey(curve, rand.Reader) 59 if err != nil { 60 return nil, nil, fmt.Errorf("generate ecdsa key: %v", err.Error()) 61 } 62 pubBytes, err := x509.MarshalPKIXPublicKey(priv.Public()) 63 if err != nil { 64 return nil, nil, fmt.Errorf("marshal ecdsa public key: %v", err.Error()) 65 } 66 privBytes, err := x509.MarshalECPrivateKey(priv) 67 if err != nil { 68 return nil, nil, fmt.Errorf("marshal ecdsa private key: %v", err.Error()) 69 } 70 return privBytes, pubBytes, nil 71 default: 72 return nil, nil, errors.New("invalid algorithm") 73 } 74 }
2. 签名
签名的步骤如下:
① 基于待签名的数据生成摘要;
② 使用私钥对摘要生成签名。
代码如下:
// Sign signs a message using a specific private key. Private key passed must // be DER encoding. Note that using sha256 hash function to create digest. // // Sign returns a signature. func Sign(privKey, msg []byte) ([]byte, error) { priv, err := ParsePrivateKeyDER(privKey) if err != nil { return nil, fmt.Errorf("parse private key: %v", err.Error()) } // create digest h := sha256.New() h.Write(msg) digest := h.Sum(nil) // sign sign, err := priv.Sign(rand.Reader, digest, crypto.SHA256) if err != nil { return nil, fmt.Errorf("sign: %v", err.Error()) } return sign, nil }
由上面代码可以看出,我们使用的是sha256算法计算摘要,也可以使用其它散列算法。
由于前面生成的私钥是ASN.1 DER编码的,所以需要将其解析成crypto.Signer才能调用签名的接口,解析的代码如下:
1 // ParsePrivateKeyDER parses a PKCS #1, PKCS #8, ECDSA, or Ed25519 DER-encoded 2 // private key. The key must not be in PEM format. 3 func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) { 4 generalKey, err := x509.ParsePKCS8PrivateKey(keyDER) 5 if err != nil { 6 generalKey, err = x509.ParsePKCS1PrivateKey(keyDER) 7 if err != nil { 8 generalKey, err = x509.ParseECPrivateKey(keyDER) 9 if err != nil { 10 return nil, errors.New("parse private key field.") 11 } 12 } 13 } 14 15 switch generalKey.(type) { 16 case *rsa.PrivateKey: 17 return generalKey.(*rsa.PrivateKey), nil 18 case *ecdsa.PrivateKey: 19 return generalKey.(*ecdsa.PrivateKey), nil 20 } 21 22 // should never reach here 23 return nil, errors.New("parse private key field.") 24 }
3. 验签
验签的过程是将源数据再次使用上述的散列算法计算摘要,然后使用公钥将签名解签,最后将解签的结果与摘要进行对比,相同则说明验签通过,代码如下:
// VerifySignature verifies signature. Currently, only ECDSA and RSA are supported. // Note that signature(including R and S) must be marshaled using ASN.1 standard // when using ecdsa algorithm. func VerifySignature(pubKey, sign, msg []byte) error { //Create digest hash := sha256.New() hash.Write(msg) digest := hash.Sum(nil) pub, err := x509.ParsePKIXPublicKey(pubKey) if err != nil { pub, err = x509.ParsePKCS1PublicKey(pubKey) if err != nil { return fmt.Errorf("public key of unknown type: %v", err.Error()) } } switch pub.(type) { case *rsa.PublicKey: publickey := pub.(*rsa.PublicKey) err = rsa.VerifyPKCS1v15(publickey, crypto.SHA256, digest, sign) if err != nil { return fmt.Errorf("verify signature: %v", err.Error()) } case *ecdsa.PublicKey: publickey := pub.(*ecdsa.PublicKey) parsedSign := struct { R *big.Int S *big.Int }{} rest, err := asn1.Unmarshal(sign, &parsedSign) if err != nil { return fmt.Errorf("parse ecc signature using ASN.1 standard: %v", err.Error()) } if len(rest) > 0 { return errors.New("extra data in marshaled sign data.") } isValid := ecdsa.Verify(publickey, digest, parsedSign.R, parsedSign.S) if !isValid { return errors.New("verify signature failed.") } } return nil }

浙公网安备 33010602011771号