...

Source file src/github.com/golang-jwt/jwt/v4/rsa_pss_test.go

Documentation: github.com/golang-jwt/jwt/v4

     1  //go:build go1.4
     2  // +build go1.4
     3  
     4  package jwt_test
     5  
     6  import (
     7  	"crypto/rsa"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/golang-jwt/jwt/v4"
    14  	"github.com/golang-jwt/jwt/v4/test"
    15  )
    16  
    17  var rsaPSSTestData = []struct {
    18  	name        string
    19  	tokenString string
    20  	alg         string
    21  	claims      map[string]interface{}
    22  	valid       bool
    23  }{
    24  	{
    25  		"Basic PS256",
    26  		"eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9w",
    27  		"PS256",
    28  		map[string]interface{}{"foo": "bar"},
    29  		true,
    30  	},
    31  	{
    32  		"Basic PS384",
    33  		"eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.w7-qqgj97gK4fJsq_DCqdYQiylJjzWONvD0qWWWhqEOFk2P1eDULPnqHRnjgTXoO4HAw4YIWCsZPet7nR3Xxq4ZhMqvKW8b7KlfRTb9cH8zqFvzMmybQ4jv2hKc3bXYqVow3AoR7hN_CWXI3Dv6Kd2X5xhtxRHI6IL39oTVDUQ74LACe-9t4c3QRPuj6Pq1H4FAT2E2kW_0KOc6EQhCLWEhm2Z2__OZskDC8AiPpP8Kv4k2vB7l0IKQu8Pr4RcNBlqJdq8dA5D3hk5TLxP8V5nG1Ib80MOMMqoS3FQvSLyolFX-R_jZ3-zfq6Ebsqr0yEb0AH2CfsECF7935Pa0FKQ",
    34  		"PS384",
    35  		map[string]interface{}{"foo": "bar"},
    36  		true,
    37  	},
    38  	{
    39  		"Basic PS512",
    40  		"eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.GX1HWGzFaJevuSLavqqFYaW8_TpvcjQ8KfC5fXiSDzSiT9UD9nB_ikSmDNyDILNdtjZLSvVKfXxZJqCfefxAtiozEDDdJthZ-F0uO4SPFHlGiXszvKeodh7BuTWRI2wL9-ZO4mFa8nq3GMeQAfo9cx11i7nfN8n2YNQ9SHGovG7_T_AvaMZB_jT6jkDHpwGR9mz7x1sycckEo6teLdHRnH_ZdlHlxqknmyTu8Odr5Xh0sJFOL8BepWbbvIIn-P161rRHHiDWFv6nhlHwZnVzjx7HQrWSGb6-s2cdLie9QL_8XaMcUpjLkfOMKkDOfHo6AvpL7Jbwi83Z2ZTHjJWB-A",
    41  		"PS512",
    42  		map[string]interface{}{"foo": "bar"},
    43  		true,
    44  	},
    45  	{
    46  		"basic PS256 invalid: foo => bar",
    47  		"eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9W",
    48  		"PS256",
    49  		map[string]interface{}{"foo": "bar"},
    50  		false,
    51  	},
    52  }
    53  
    54  func TestRSAPSSVerify(t *testing.T) {
    55  	var err error
    56  
    57  	key, _ := os.ReadFile("test/sample_key.pub")
    58  	var rsaPSSKey *rsa.PublicKey
    59  	if rsaPSSKey, err = jwt.ParseRSAPublicKeyFromPEM(key); err != nil {
    60  		t.Errorf("Unable to parse RSA public key: %v", err)
    61  	}
    62  
    63  	for _, data := range rsaPSSTestData {
    64  		parts := strings.Split(data.tokenString, ".")
    65  
    66  		method := jwt.GetSigningMethod(data.alg)
    67  		err := method.Verify(strings.Join(parts[0:2], "."), parts[2], rsaPSSKey)
    68  		if data.valid && err != nil {
    69  			t.Errorf("[%v] Error while verifying key: %v", data.name, err)
    70  		}
    71  		if !data.valid && err == nil {
    72  			t.Errorf("[%v] Invalid key passed validation", data.name)
    73  		}
    74  	}
    75  }
    76  
    77  func TestRSAPSSSign(t *testing.T) {
    78  	var err error
    79  
    80  	key, _ := os.ReadFile("test/sample_key")
    81  	var rsaPSSKey *rsa.PrivateKey
    82  	if rsaPSSKey, err = jwt.ParseRSAPrivateKeyFromPEM(key); err != nil {
    83  		t.Errorf("Unable to parse RSA private key: %v", err)
    84  	}
    85  
    86  	for _, data := range rsaPSSTestData {
    87  		if data.valid {
    88  			parts := strings.Split(data.tokenString, ".")
    89  			method := jwt.GetSigningMethod(data.alg)
    90  			sig, err := method.Sign(strings.Join(parts[0:2], "."), rsaPSSKey)
    91  			if err != nil {
    92  				t.Errorf("[%v] Error signing token: %v", data.name, err)
    93  			}
    94  			if sig == parts[2] {
    95  				t.Errorf("[%v] Signatures shouldn't match\nnew:\n%v\noriginal:\n%v", data.name, sig, parts[2])
    96  			}
    97  		}
    98  	}
    99  }
   100  
   101  func TestRSAPSSSaltLengthCompatibility(t *testing.T) {
   102  	// Fails token verify, if salt length is auto.
   103  	ps256SaltLengthEqualsHash := &jwt.SigningMethodRSAPSS{
   104  		SigningMethodRSA: jwt.SigningMethodPS256.SigningMethodRSA,
   105  		Options: &rsa.PSSOptions{
   106  			SaltLength: rsa.PSSSaltLengthEqualsHash,
   107  		},
   108  	}
   109  
   110  	// Behaves as before https://github.com/dgrijalva/jwt-go/issues/285 fix.
   111  	ps256SaltLengthAuto := &jwt.SigningMethodRSAPSS{
   112  		SigningMethodRSA: jwt.SigningMethodPS256.SigningMethodRSA,
   113  		Options: &rsa.PSSOptions{
   114  			SaltLength: rsa.PSSSaltLengthAuto,
   115  		},
   116  	}
   117  	if !verify(jwt.SigningMethodPS256, makeToken(ps256SaltLengthEqualsHash)) {
   118  		t.Error("SigningMethodPS256 should accept salt length that is defined in RFC")
   119  	}
   120  	if !verify(ps256SaltLengthEqualsHash, makeToken(jwt.SigningMethodPS256)) {
   121  		t.Error("Sign by SigningMethodPS256 should have salt length that is defined in RFC")
   122  	}
   123  	if !verify(jwt.SigningMethodPS256, makeToken(ps256SaltLengthAuto)) {
   124  		t.Error("SigningMethodPS256 should accept auto salt length to be compatible with previous versions")
   125  	}
   126  	if !verify(ps256SaltLengthAuto, makeToken(jwt.SigningMethodPS256)) {
   127  		t.Error("Sign by SigningMethodPS256 should be accepted by previous versions")
   128  	}
   129  	if verify(ps256SaltLengthEqualsHash, makeToken(ps256SaltLengthAuto)) {
   130  		t.Error("Auto salt length should be not accepted, when RFC salt length is required")
   131  	}
   132  }
   133  
   134  func makeToken(method jwt.SigningMethod) string {
   135  	token := jwt.NewWithClaims(method, jwt.RegisteredClaims{
   136  		Issuer:   "example",
   137  		IssuedAt: jwt.NewNumericDate(time.Now()),
   138  	})
   139  	privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key")
   140  	signed, err := token.SignedString(privateKey)
   141  	if err != nil {
   142  		panic(err)
   143  	}
   144  	return signed
   145  }
   146  
   147  func verify(signingMethod jwt.SigningMethod, token string) bool {
   148  	segments := strings.Split(token, ".")
   149  	err := signingMethod.Verify(strings.Join(segments[:2], "."), segments[2], test.LoadRSAPublicKeyFromDisk("test/sample_key.pub"))
   150  	return err == nil
   151  }
   152  

View as plain text