package spec import ( "crypto/sha256" "encoding/base64" "fmt" "github.com/golang-jwt/jwt/v5" "github.com/sonr-io/crypto/mpc" ) // MPCSigningMethod implements the SigningMethod interface for MPC-based signing type MPCSigningMethod struct { Name string enclave mpc.Enclave } // NewJWTSigningMethod creates a new MPC signing method with the given enclave func NewJWTSigningMethod(name string, enclave mpc.Enclave) *MPCSigningMethod { return &MPCSigningMethod{ Name: name, enclave: enclave, } } // WithEnclave sets the enclave for an existing signing method func (m *MPCSigningMethod) WithEnclave(enclave mpc.Enclave) *MPCSigningMethod { return &MPCSigningMethod{ Name: m.Name, enclave: enclave, } } // NewMPCSigningMethod is an alias for NewJWTSigningMethod for compatibility func NewMPCSigningMethod(name string, enclave mpc.Enclave) *MPCSigningMethod { return NewJWTSigningMethod(name, enclave) } // Alg returns the signing method's name func (m *MPCSigningMethod) Alg() string { return m.Name } // Verify verifies the signature using the MPC public key func (m *MPCSigningMethod) Verify(signingString string, signature []byte, key any) error { // Check if enclave is available if m.enclave == nil { return fmt.Errorf("MPC enclave not available for signature verification") } // Decode the signature sig, err := base64.RawURLEncoding.DecodeString(string(signature)) if err != nil { return fmt.Errorf("failed to decode signature: %w", err) } // Hash the signing string using SHA-256 hasher := sha256.New() hasher.Write([]byte(signingString)) digest := hasher.Sum(nil) // Use MPC enclave to verify signature valid, err := m.enclave.Verify(digest, sig) if err != nil { return fmt.Errorf("failed to verify signature: %w", err) } if !valid { return fmt.Errorf("signature verification failed") } return nil } // Sign signs the data using MPC func (m *MPCSigningMethod) Sign(signingString string, key any) ([]byte, error) { // Check if enclave is available if m.enclave == nil { return nil, fmt.Errorf("MPC enclave not available for signing") } // Hash the signing string using SHA-256 hasher := sha256.New() hasher.Write([]byte(signingString)) digest := hasher.Sum(nil) // Use MPC enclave to sign the digest sig, err := m.enclave.Sign(digest) if err != nil { return nil, fmt.Errorf("failed to sign with MPC: %w", err) } // Encode the signature as base64url encoded := base64.RawURLEncoding.EncodeToString(sig) return []byte(encoded), nil } func init() { // Register the MPC signing method factory jwt.RegisterSigningMethod("MPC256", func() jwt.SigningMethod { // This factory creates a new instance without enclave // The enclave will be provided when creating tokens return &MPCSigningMethod{ Name: "MPC256", } }) } // RegisterMPCMethod registers an MPC signing method for the given algorithm name func RegisterMPCMethod(alg string) { jwt.RegisterSigningMethod(alg, func() jwt.SigningMethod { return &MPCSigningMethod{ Name: alg, } }) }