...

Source file src/github.com/golang-jwt/jwt/rsa_pss.go

Documentation: github.com/golang-jwt/jwt

     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  	// VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS.
    16  	// Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow
    17  	// https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously.
    18  	// See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details.
    19  	VerifyOptions *rsa.PSSOptions
    20  }
    21  
    22  // Specific instances for RS/PS and company.
    23  var (
    24  	SigningMethodPS256 *SigningMethodRSAPSS
    25  	SigningMethodPS384 *SigningMethodRSAPSS
    26  	SigningMethodPS512 *SigningMethodRSAPSS
    27  )
    28  
    29  func init() {
    30  	// PS256
    31  	SigningMethodPS256 = &SigningMethodRSAPSS{
    32  		SigningMethodRSA: &SigningMethodRSA{
    33  			Name: "PS256",
    34  			Hash: crypto.SHA256,
    35  		},
    36  		Options: &rsa.PSSOptions{
    37  			SaltLength: rsa.PSSSaltLengthEqualsHash,
    38  		},
    39  		VerifyOptions: &rsa.PSSOptions{
    40  			SaltLength: rsa.PSSSaltLengthAuto,
    41  		},
    42  	}
    43  	RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod {
    44  		return SigningMethodPS256
    45  	})
    46  
    47  	// PS384
    48  	SigningMethodPS384 = &SigningMethodRSAPSS{
    49  		SigningMethodRSA: &SigningMethodRSA{
    50  			Name: "PS384",
    51  			Hash: crypto.SHA384,
    52  		},
    53  		Options: &rsa.PSSOptions{
    54  			SaltLength: rsa.PSSSaltLengthEqualsHash,
    55  		},
    56  		VerifyOptions: &rsa.PSSOptions{
    57  			SaltLength: rsa.PSSSaltLengthAuto,
    58  		},
    59  	}
    60  	RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod {
    61  		return SigningMethodPS384
    62  	})
    63  
    64  	// PS512
    65  	SigningMethodPS512 = &SigningMethodRSAPSS{
    66  		SigningMethodRSA: &SigningMethodRSA{
    67  			Name: "PS512",
    68  			Hash: crypto.SHA512,
    69  		},
    70  		Options: &rsa.PSSOptions{
    71  			SaltLength: rsa.PSSSaltLengthEqualsHash,
    72  		},
    73  		VerifyOptions: &rsa.PSSOptions{
    74  			SaltLength: rsa.PSSSaltLengthAuto,
    75  		},
    76  	}
    77  	RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod {
    78  		return SigningMethodPS512
    79  	})
    80  }
    81  
    82  // Implements the Verify method from SigningMethod
    83  // For this verify method, key must be an rsa.PublicKey struct
    84  func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
    85  	var err error
    86  
    87  	// Decode the signature
    88  	var sig []byte
    89  	if sig, err = DecodeSegment(signature); err != nil {
    90  		return err
    91  	}
    92  
    93  	var rsaKey *rsa.PublicKey
    94  	switch k := key.(type) {
    95  	case *rsa.PublicKey:
    96  		rsaKey = k
    97  	default:
    98  		return ErrInvalidKey
    99  	}
   100  
   101  	// Create hasher
   102  	if !m.Hash.Available() {
   103  		return ErrHashUnavailable
   104  	}
   105  	hasher := m.Hash.New()
   106  	hasher.Write([]byte(signingString))
   107  
   108  	opts := m.Options
   109  	if m.VerifyOptions != nil {
   110  		opts = m.VerifyOptions
   111  	}
   112  
   113  	return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts)
   114  }
   115  
   116  // Implements the Sign method from SigningMethod
   117  // For this signing method, key must be an rsa.PrivateKey struct
   118  func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
   119  	var rsaKey *rsa.PrivateKey
   120  
   121  	switch k := key.(type) {
   122  	case *rsa.PrivateKey:
   123  		rsaKey = k
   124  	default:
   125  		return "", ErrInvalidKeyType
   126  	}
   127  
   128  	// Create the hasher
   129  	if !m.Hash.Available() {
   130  		return "", ErrHashUnavailable
   131  	}
   132  
   133  	hasher := m.Hash.New()
   134  	hasher.Write([]byte(signingString))
   135  
   136  	// Sign the string and return the encoded bytes
   137  	if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil {
   138  		return EncodeSegment(sigBytes), nil
   139  	} else {
   140  		return "", err
   141  	}
   142  }
   143  

View as plain text