...

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

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

     1  package jwt_test
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"os"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/golang-jwt/jwt/v4"
    10  )
    11  
    12  var ecdsaTestData = []struct {
    13  	name        string
    14  	keys        map[string]string
    15  	tokenString string
    16  	alg         string
    17  	claims      map[string]interface{}
    18  	valid       bool
    19  }{
    20  	{
    21  		"Basic ES256",
    22  		map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"},
    23  		"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJmb28iOiJiYXIifQ.feG39E-bn8HXAKhzDZq7yEAPWYDhZlwTn3sePJnU9VrGMmwdXAIEyoOnrjreYlVM_Z4N13eK9-TmMTWyfKJtHQ",
    24  		"ES256",
    25  		map[string]interface{}{"foo": "bar"},
    26  		true,
    27  	},
    28  	{
    29  		"Basic ES384",
    30  		map[string]string{"private": "test/ec384-private.pem", "public": "test/ec384-public.pem"},
    31  		"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJmb28iOiJiYXIifQ.ngAfKMbJUh0WWubSIYe5GMsA-aHNKwFbJk_wq3lq23aPp8H2anb1rRILIzVR0gUf4a8WzDtrzmiikuPWyCS6CN4-PwdgTk-5nehC7JXqlaBZU05p3toM3nWCwm_LXcld",
    32  		"ES384",
    33  		map[string]interface{}{"foo": "bar"},
    34  		true,
    35  	},
    36  	{
    37  		"Basic ES512",
    38  		map[string]string{"private": "test/ec512-private.pem", "public": "test/ec512-public.pem"},
    39  		"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJmb28iOiJiYXIifQ.AAU0TvGQOcdg2OvrwY73NHKgfk26UDekh9Prz-L_iWuTBIBqOFCWwwLsRiHB1JOddfKAls5do1W0jR_F30JpVd-6AJeTjGKA4C1A1H6gIKwRY0o_tFDIydZCl_lMBMeG5VNFAjO86-WCSKwc3hqaGkq1MugPRq_qrF9AVbuEB4JPLyL5",
    40  		"ES512",
    41  		map[string]interface{}{"foo": "bar"},
    42  		true,
    43  	},
    44  	{
    45  		"basic ES256 invalid: foo => bar",
    46  		map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"},
    47  		"eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MEQCIHoSJnmGlPaVQDqacx_2XlXEhhqtWceVopjomc2PJLtdAiAUTeGPoNYxZw0z8mgOnnIcjoxRuNDVZvybRZF3wR1l8W",
    48  		"ES256",
    49  		map[string]interface{}{"foo": "bar"},
    50  		false,
    51  	},
    52  }
    53  
    54  func TestECDSAVerify(t *testing.T) {
    55  	for _, data := range ecdsaTestData {
    56  		var err error
    57  
    58  		key, _ := os.ReadFile(data.keys["public"])
    59  
    60  		var ecdsaKey *ecdsa.PublicKey
    61  		if ecdsaKey, err = jwt.ParseECPublicKeyFromPEM(key); err != nil {
    62  			t.Errorf("Unable to parse ECDSA public key: %v", err)
    63  		}
    64  
    65  		parts := strings.Split(data.tokenString, ".")
    66  
    67  		method := jwt.GetSigningMethod(data.alg)
    68  		err = method.Verify(strings.Join(parts[0:2], "."), parts[2], ecdsaKey)
    69  		if data.valid && err != nil {
    70  			t.Errorf("[%v] Error while verifying key: %v", data.name, err)
    71  		}
    72  		if !data.valid && err == nil {
    73  			t.Errorf("[%v] Invalid key passed validation", data.name)
    74  		}
    75  	}
    76  }
    77  
    78  func TestECDSASign(t *testing.T) {
    79  	for _, data := range ecdsaTestData {
    80  		var err error
    81  		key, _ := os.ReadFile(data.keys["private"])
    82  
    83  		var ecdsaKey *ecdsa.PrivateKey
    84  		if ecdsaKey, err = jwt.ParseECPrivateKeyFromPEM(key); err != nil {
    85  			t.Errorf("Unable to parse ECDSA private key: %v", err)
    86  		}
    87  
    88  		if data.valid {
    89  			parts := strings.Split(data.tokenString, ".")
    90  			toSign := strings.Join(parts[0:2], ".")
    91  			method := jwt.GetSigningMethod(data.alg)
    92  			sig, err := method.Sign(toSign, ecdsaKey)
    93  
    94  			if err != nil {
    95  				t.Errorf("[%v] Error signing token: %v", data.name, err)
    96  			}
    97  			if sig == parts[2] {
    98  				t.Errorf("[%v] Identical signatures\nbefore:\n%v\nafter:\n%v", data.name, parts[2], sig)
    99  			}
   100  
   101  			err = method.Verify(toSign, sig, ecdsaKey.Public())
   102  			if err != nil {
   103  				t.Errorf("[%v] Sign produced an invalid signature: %v", data.name, err)
   104  			}
   105  		}
   106  	}
   107  }
   108  
   109  func BenchmarkECDSAParsing(b *testing.B) {
   110  	for _, data := range ecdsaTestData {
   111  		key, _ := os.ReadFile(data.keys["private"])
   112  
   113  		b.Run(data.name, func(b *testing.B) {
   114  			b.ReportAllocs()
   115  			b.ResetTimer()
   116  			b.RunParallel(func(pb *testing.PB) {
   117  				for pb.Next() {
   118  					if _, err := jwt.ParseECPrivateKeyFromPEM(key); err != nil {
   119  						b.Fatalf("Unable to parse ECDSA private key: %v", err)
   120  					}
   121  				}
   122  			})
   123  		})
   124  	}
   125  }
   126  
   127  func BenchmarkECDSASigning(b *testing.B) {
   128  	for _, data := range ecdsaTestData {
   129  		key, _ := os.ReadFile(data.keys["private"])
   130  
   131  		ecdsaKey, err := jwt.ParseECPrivateKeyFromPEM(key)
   132  		if err != nil {
   133  			b.Fatalf("Unable to parse ECDSA private key: %v", err)
   134  		}
   135  
   136  		method := jwt.GetSigningMethod(data.alg)
   137  
   138  		b.Run(data.name, func(b *testing.B) {
   139  			benchmarkSigning(b, method, ecdsaKey)
   140  		})
   141  
   142  		// Directly call method.Sign without the decoration of *Token.
   143  		b.Run(data.name+"/sign-only", func(b *testing.B) {
   144  			if !data.valid {
   145  				b.Skipf("Skipping because data is not valid")
   146  			}
   147  
   148  			parts := strings.Split(data.tokenString, ".")
   149  			toSign := strings.Join(parts[0:2], ".")
   150  
   151  			b.ReportAllocs()
   152  			b.ResetTimer()
   153  			for i := 0; i < b.N; i++ {
   154  				sig, err := method.Sign(toSign, ecdsaKey)
   155  				if err != nil {
   156  					b.Fatalf("[%v] Error signing token: %v", data.name, err)
   157  				}
   158  				if sig == parts[2] {
   159  					b.Fatalf("[%v] Identical signatures\nbefore:\n%v\nafter:\n%v", data.name, parts[2], sig)
   160  				}
   161  			}
   162  		})
   163  	}
   164  }
   165  

View as plain text