rsa_pss.go 3.4 KB

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