package jwt

import (
	
	
	
)

// SigningMethodRSA implements the RSA family of signing methods.
// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation
type SigningMethodRSA struct {
	Name string
	Hash crypto.Hash
}

// Specific instances for RS256 and company
var (
	SigningMethodRS256 *SigningMethodRSA
	SigningMethodRS384 *SigningMethodRSA
	SigningMethodRS512 *SigningMethodRSA
)

func init() {
	// RS256
	SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256}
	RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod {
		return SigningMethodRS256
	})

	// RS384
	SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384}
	RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod {
		return SigningMethodRS384
	})

	// RS512
	SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512}
	RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod {
		return SigningMethodRS512
	})
}

func ( *SigningMethodRSA) () string {
	return .Name
}

// Verify implements token verification for the SigningMethod
// For this signing method, must be an *rsa.PublicKey structure.
func ( *SigningMethodRSA) (,  string,  interface{}) error {
	var  error

	// Decode the signature
	var  []byte
	if ,  = DecodeSegment();  != nil {
		return 
	}

	var  *rsa.PublicKey
	var  bool

	if ,  = .(*rsa.PublicKey); ! {
		return ErrInvalidKeyType
	}

	// Create hasher
	if !.Hash.Available() {
		return ErrHashUnavailable
	}
	 := .Hash.New()
	.Write([]byte())

	// Verify the signature
	return rsa.VerifyPKCS1v15(, .Hash, .Sum(nil), )
}

// Sign implements token signing for the SigningMethod
// For this signing method, must be an *rsa.PrivateKey structure.
func ( *SigningMethodRSA) ( string,  interface{}) (string, error) {
	var  *rsa.PrivateKey
	var  bool

	// Validate type of key
	if ,  = .(*rsa.PrivateKey); ! {
		return "", ErrInvalidKey
	}

	// Create the hasher
	if !.Hash.Available() {
		return "", ErrHashUnavailable
	}

	 := .Hash.New()
	.Write([]byte())

	// Sign the string and return the encoded bytes
	if ,  := rsa.SignPKCS1v15(rand.Reader, , .Hash, .Sum(nil));  == nil {
		return EncodeSegment(), nil
	} else {
		return "", 
	}
}