package sign import ( "crypto/ed25519" "crypto/rand" "encoding/base64" "errors" "fmt" ) var ( ErrInvalidSignature = errors.New("invalid signature") ErrInvalidPublicKey = errors.New("invalid public key") ErrInvalidPrivateKey = errors.New("invalid private key") ) // KeyPair Ed25519 密钥对 type KeyPair struct { PublicKey ed25519.PublicKey PrivateKey ed25519.PrivateKey } // GenerateKeyPair 生成新的密钥对 func GenerateKeyPair() (*KeyPair, error) { pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, fmt.Errorf("generate key: %w", err) } return &KeyPair{PublicKey: pub, PrivateKey: priv}, nil } // Sign 使用私钥签名数据 func Sign(privateKey ed25519.PrivateKey, data []byte) []byte { return ed25519.Sign(privateKey, data) } // Verify 使用公钥验证签名 func Verify(publicKey ed25519.PublicKey, data, signature []byte) bool { return ed25519.Verify(publicKey, data, signature) } // SignBase64 签名并返回 Base64 编码 func SignBase64(privateKey ed25519.PrivateKey, data []byte) string { sig := Sign(privateKey, data) return base64.StdEncoding.EncodeToString(sig) } // VerifyBase64 验证 Base64 编码的签名 func VerifyBase64(publicKey ed25519.PublicKey, data []byte, sigB64 string) error { sig, err := base64.StdEncoding.DecodeString(sigB64) if err != nil { return fmt.Errorf("decode signature: %w", err) } if !Verify(publicKey, data, sig) { return ErrInvalidSignature } return nil } // EncodePublicKey 编码公钥为 Base64 func EncodePublicKey(pub ed25519.PublicKey) string { return base64.StdEncoding.EncodeToString(pub) } // DecodePublicKey 从 Base64 解码公钥 func DecodePublicKey(s string) (ed25519.PublicKey, error) { data, err := base64.StdEncoding.DecodeString(s) if err != nil { return nil, err } if len(data) != ed25519.PublicKeySize { return nil, ErrInvalidPublicKey } return ed25519.PublicKey(data), nil } // EncodePrivateKey 编码私钥为 Base64 func EncodePrivateKey(priv ed25519.PrivateKey) string { return base64.StdEncoding.EncodeToString(priv) } // DecodePrivateKey 从 Base64 解码私钥 func DecodePrivateKey(s string) (ed25519.PrivateKey, error) { data, err := base64.StdEncoding.DecodeString(s) if err != nil { return nil, err } if len(data) != ed25519.PrivateKeySize { return nil, ErrInvalidPrivateKey } return ed25519.PrivateKey(data), nil }