package authn import ( "crypto/ed25519" "encoding/base64" "errors" ) var ( // ErrInvalidClientPublicKey reports that cached client public key material // is not a base64-encoded raw Ed25519 public key. ErrInvalidClientPublicKey = errors.New("client_public_key is not a valid base64-encoded Ed25519 public key") // ErrInvalidRequestSignature reports that a request signature is not a raw // Ed25519 signature for the canonical request signing input. ErrInvalidRequestSignature = errors.New("invalid request signature") ) // VerifyRequestSignature validates the base64-encoded raw Ed25519 public key // from session cache, builds the canonical v1 signing input from fields, and // verifies that signature authenticates the request. func VerifyRequestSignature(clientPublicKey string, signature []byte, fields RequestSigningFields) error { publicKey, err := decodeClientPublicKey(clientPublicKey) if err != nil { return err } if len(signature) != ed25519.SignatureSize { return ErrInvalidRequestSignature } if !ed25519.Verify(publicKey, BuildRequestSigningInput(fields), signature) { return ErrInvalidRequestSignature } return nil } func decodeClientPublicKey(value string) (ed25519.PublicKey, error) { decoded, err := base64.StdEncoding.Strict().DecodeString(value) if err != nil { return nil, ErrInvalidClientPublicKey } if len(decoded) != ed25519.PublicKeySize { return nil, ErrInvalidClientPublicKey } return ed25519.PublicKey(decoded), nil }