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.

rsa_pss.go 3.4KB

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