github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/appengine/login/googlesignin/jwt-go/rsa_pss.go (about)

     1  // +build go1.4
     2  
     3  package jwt
     4  
     5  import (
     6  	"crypto"
     7  	"crypto/rand"
     8  	"crypto/rsa"
     9  )
    10  
    11  // Implements the RSAPSS family of signing methods signing methods
    12  type SigningMethodRSAPSS struct {
    13  	*SigningMethodRSA
    14  	Options *rsa.PSSOptions
    15  }
    16  
    17  // Specific instances for RS/PS and company
    18  var (
    19  	SigningMethodPS256 *SigningMethodRSAPSS
    20  	SigningMethodPS384 *SigningMethodRSAPSS
    21  	SigningMethodPS512 *SigningMethodRSAPSS
    22  )
    23  
    24  func init() {
    25  	// PS256
    26  	SigningMethodPS256 = &SigningMethodRSAPSS{
    27  		&SigningMethodRSA{
    28  			Name: "PS256",
    29  			Hash: crypto.SHA256,
    30  		},
    31  		&rsa.PSSOptions{
    32  			SaltLength: rsa.PSSSaltLengthAuto,
    33  			Hash:       crypto.SHA256,
    34  		},
    35  	}
    36  	RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod {
    37  		return SigningMethodPS256
    38  	})
    39  
    40  	// PS384
    41  	SigningMethodPS384 = &SigningMethodRSAPSS{
    42  		&SigningMethodRSA{
    43  			Name: "PS384",
    44  			Hash: crypto.SHA384,
    45  		},
    46  		&rsa.PSSOptions{
    47  			SaltLength: rsa.PSSSaltLengthAuto,
    48  			Hash:       crypto.SHA384,
    49  		},
    50  	}
    51  	RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod {
    52  		return SigningMethodPS384
    53  	})
    54  
    55  	// PS512
    56  	SigningMethodPS512 = &SigningMethodRSAPSS{
    57  		&SigningMethodRSA{
    58  			Name: "PS512",
    59  			Hash: crypto.SHA512,
    60  		},
    61  		&rsa.PSSOptions{
    62  			SaltLength: rsa.PSSSaltLengthAuto,
    63  			Hash:       crypto.SHA512,
    64  		},
    65  	}
    66  	RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod {
    67  		return SigningMethodPS512
    68  	})
    69  }
    70  
    71  // Implements the Verify method from SigningMethod
    72  // For this verify method, key must be an rsa.PrivateKey struct
    73  func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
    74  	var err error
    75  
    76  	// Decode the signature
    77  	var sig []byte
    78  	if sig, err = DecodeSegment(signature); err != nil {
    79  		return err
    80  	}
    81  
    82  	var rsaKey *rsa.PublicKey
    83  	switch k := key.(type) {
    84  	case *rsa.PublicKey:
    85  		rsaKey = k
    86  	default:
    87  		return ErrInvalidKey
    88  	}
    89  
    90  	// Create hasher
    91  	if !m.Hash.Available() {
    92  		return ErrHashUnavailable
    93  	}
    94  	hasher := m.Hash.New()
    95  	hasher.Write([]byte(signingString))
    96  
    97  	return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options)
    98  }
    99  
   100  // Implements the Sign method from SigningMethod
   101  // For this signing method, key must be an rsa.PublicKey struct
   102  func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
   103  	var rsaKey *rsa.PrivateKey
   104  
   105  	switch k := key.(type) {
   106  	case *rsa.PrivateKey:
   107  		rsaKey = k
   108  	default:
   109  		return "", ErrInvalidKey
   110  	}
   111  
   112  	// Create the hasher
   113  	if !m.Hash.Available() {
   114  		return "", ErrHashUnavailable
   115  	}
   116  
   117  	hasher := m.Hash.New()
   118  	hasher.Write([]byte(signingString))
   119  
   120  	// Sign the string and return the encoded bytes
   121  	if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil {
   122  		return EncodeSegment(sigBytes), nil
   123  	} else {
   124  		return "", err
   125  	}
   126  }