gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

rsa_pss.go (3439B)


      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 }