Files
motr-enclave/internal/crypto/mpc/spec/jwt.go

117 lines
3.0 KiB
Go

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,
}
})
}