...

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

Documentation: github.com/golang-jwt/jwt

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

View as plain text