Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
2.7 KiB
126 lines
2.7 KiB
// +build go1.4 |
|
|
|
package jwt |
|
|
|
import ( |
|
"crypto" |
|
"crypto/rand" |
|
"crypto/rsa" |
|
) |
|
|
|
// Implements the RSAPSS family of signing methods signing methods |
|
type SigningMethodRSAPSS struct { |
|
*SigningMethodRSA |
|
Options *rsa.PSSOptions |
|
} |
|
|
|
// Specific instances for RS/PS and company |
|
var ( |
|
SigningMethodPS256 *SigningMethodRSAPSS |
|
SigningMethodPS384 *SigningMethodRSAPSS |
|
SigningMethodPS512 *SigningMethodRSAPSS |
|
) |
|
|
|
func init() { |
|
// PS256 |
|
SigningMethodPS256 = &SigningMethodRSAPSS{ |
|
&SigningMethodRSA{ |
|
Name: "PS256", |
|
Hash: crypto.SHA256, |
|
}, |
|
&rsa.PSSOptions{ |
|
SaltLength: rsa.PSSSaltLengthAuto, |
|
Hash: crypto.SHA256, |
|
}, |
|
} |
|
RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { |
|
return SigningMethodPS256 |
|
}) |
|
|
|
// PS384 |
|
SigningMethodPS384 = &SigningMethodRSAPSS{ |
|
&SigningMethodRSA{ |
|
Name: "PS384", |
|
Hash: crypto.SHA384, |
|
}, |
|
&rsa.PSSOptions{ |
|
SaltLength: rsa.PSSSaltLengthAuto, |
|
Hash: crypto.SHA384, |
|
}, |
|
} |
|
RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { |
|
return SigningMethodPS384 |
|
}) |
|
|
|
// PS512 |
|
SigningMethodPS512 = &SigningMethodRSAPSS{ |
|
&SigningMethodRSA{ |
|
Name: "PS512", |
|
Hash: crypto.SHA512, |
|
}, |
|
&rsa.PSSOptions{ |
|
SaltLength: rsa.PSSSaltLengthAuto, |
|
Hash: crypto.SHA512, |
|
}, |
|
} |
|
RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { |
|
return SigningMethodPS512 |
|
}) |
|
} |
|
|
|
// Implements the Verify method from SigningMethod |
|
// For this verify method, key must be an rsa.PublicKey struct |
|
func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { |
|
var err error |
|
|
|
// Decode the signature |
|
var sig []byte |
|
if sig, err = DecodeSegment(signature); err != nil { |
|
return err |
|
} |
|
|
|
var rsaKey *rsa.PublicKey |
|
switch k := key.(type) { |
|
case *rsa.PublicKey: |
|
rsaKey = k |
|
default: |
|
return ErrInvalidKey |
|
} |
|
|
|
// Create hasher |
|
if !m.Hash.Available() { |
|
return ErrHashUnavailable |
|
} |
|
hasher := m.Hash.New() |
|
hasher.Write([]byte(signingString)) |
|
|
|
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) |
|
} |
|
|
|
// Implements the Sign method from SigningMethod |
|
// For this signing method, key must be an rsa.PrivateKey struct |
|
func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { |
|
var rsaKey *rsa.PrivateKey |
|
|
|
switch k := key.(type) { |
|
case *rsa.PrivateKey: |
|
rsaKey = k |
|
default: |
|
return "", ErrInvalidKeyType |
|
} |
|
|
|
// Create the hasher |
|
if !m.Hash.Available() { |
|
return "", ErrHashUnavailable |
|
} |
|
|
|
hasher := m.Hash.New() |
|
hasher.Write([]byte(signingString)) |
|
|
|
// Sign the string and return the encoded bytes |
|
if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { |
|
return EncodeSegment(sigBytes), nil |
|
} else { |
|
return "", err |
|
} |
|
}
|
|
|