签名
java
func (a *Account) Sign(message []byte) ([]byte, error) {
hash := crypto.Keccak256Hash(message)
signature, err := crypto.Sign(hash.Bytes(), a.privateKeyECDSA)
if err != nil {
log.Fatal(err)
}
signMsg := []byte(hexutil.Encode(signature))
return signMsg, err
}
验签
java
func (a *Account) VerifySign(signatureHex, message string) (bool, error) {
// 签名 Hex 转 Bytes
signature, err := hexutil.Decode(signatureHex)
if err != nil {
return false, errors.New("签名后的数据解析异常")
}
// msg 转 hash
newHash := crypto.Keccak256Hash([]byte(message))
// 由于前端工具差异, 可能需要重新 Hash
//var newHash []byte
if signature[64] > 30 {
signature[64] -= 31
//newHash = signHash(hash.Bytes())
} else {
signature[64] -= 27
//newHash = hash.Bytes()
}
sigPublicKeyECDSA, err := crypto.SigToPub(newHash.Bytes(), signature)
if err != nil {
return false, errors.New("签名解出公钥椭圆曲线异常")
}
// 一个重要的问题是我们必须首先删除signture的最后一个字节,因为它是ECDSA恢复ID,不能包含它。
sigPublicKeyBytes := crypto.FromECDSAPub(sigPublicKeyECDSA)
signatureNoRecoverID := signature[:len(signature)-1]
recoveredAddr := crypto.PubkeyToAddress(*sigPublicKeyECDSA)
if string(a.PublicKey()) != recoveredAddr.Hex() {
return false, errors.New("签名解出公钥异常")
}
// 该函数接收原始数据的签名,哈希值和字节格式的公钥。 它返回一个布尔值,如果公钥与签名的签名者匹配,则为true。
verified := crypto.VerifySignature(sigPublicKeyBytes, newHash.Bytes(), signatureNoRecoverID)
if !verified {
return false, errors.New("验签失败")
}
return verified, nil
}