@@ -17,6 +17,12 @@ type esjwtEncoderWithPrivateKeyFile struct {
1717 method jwt.SigningMethod
1818}
1919
20+ type esjwtEncoderWithCachedPrivateKey struct {
21+ encoder encoder
22+ privateKey crypto.PrivateKey
23+ method jwt.SigningMethod
24+ }
25+
2026type esjwtDecoderWithPrivateKeyFile struct {
2127 decoder decoder
2228 privateKeyFile string
@@ -29,6 +35,12 @@ type esjwtDecoderWithPublicKeyFile struct {
2935 method jwt.SigningMethod
3036}
3137
38+ type esjwtDecoderWithCachedPublicKey struct {
39+ decoder decoder
40+ publicKey crypto.PublicKey
41+ method jwt.SigningMethod
42+ }
43+
3244// NewES256Encoder creates a new ECDSA-SHA256 JWT encoder with a private key file.
3345func NewES256Encoder (privateKeyFile string ) Encoder {
3446 return & esjwtEncoderWithPrivateKeyFile {
@@ -109,6 +121,61 @@ func NewES256DecoderWithPublicKeyFileAndValidation(publicKeyFile string, validat
109121 }
110122}
111123
124+ // NewES256EncoderWithCache creates a new ECDSA-SHA256 JWT encoder with cached private key.
125+ // The private key is loaded once at creation time, improving performance for repeated operations.
126+ func NewES256EncoderWithCache (privateKeyFile string ) (Encoder , error ) {
127+ privateKey , _ , err := readECDSAPrivateKey (privateKeyFile )
128+ if err != nil {
129+ return nil , err
130+ }
131+ return & esjwtEncoderWithCachedPrivateKey {
132+ method : jwt .SigningMethodES256 ,
133+ privateKey : privateKey ,
134+ }, nil
135+ }
136+
137+ // NewES256DecoderWithPrivateKeyFileAndCache creates a new ECDSA-SHA256 JWT decoder with cached public key from private key file.
138+ // The key is loaded once at creation time, improving performance for repeated operations.
139+ func NewES256DecoderWithPrivateKeyFileAndCache (privateKeyFile string ) (Decoder , error ) {
140+ return NewES256DecoderWithPrivateKeyFileAndCacheAndValidation (privateKeyFile , ValidationOptions {})
141+ }
142+
143+ // NewES256DecoderWithPrivateKeyFileAndCacheAndValidation creates a new ECDSA-SHA256 JWT decoder with cached public key and validation options.
144+ func NewES256DecoderWithPrivateKeyFileAndCacheAndValidation (privateKeyFile string , validationOpts ValidationOptions ) (Decoder , error ) {
145+ _ , publicKey , err := readECDSAPrivateKey (privateKeyFile )
146+ if err != nil {
147+ return nil , err
148+ }
149+ return & esjwtDecoderWithCachedPublicKey {
150+ method : jwt .SigningMethodES256 ,
151+ publicKey : publicKey ,
152+ decoder : decoder {validationOpts : validationOpts },
153+ }, nil
154+ }
155+
156+ // NewES256DecoderWithPublicKeyFileAndCache creates a new ECDSA-SHA256 JWT decoder with cached public key from public key file.
157+ // The key is loaded once at creation time, improving performance for repeated operations.
158+ func NewES256DecoderWithPublicKeyFileAndCache (publicKeyFile string ) (Decoder , error ) {
159+ return NewES256DecoderWithPublicKeyFileAndCacheAndValidation (publicKeyFile , ValidationOptions {})
160+ }
161+
162+ // NewES256DecoderWithPublicKeyFileAndCacheAndValidation creates a new ECDSA-SHA256 JWT decoder with cached public key and validation options.
163+ func NewES256DecoderWithPublicKeyFileAndCacheAndValidation (publicKeyFile string , validationOpts ValidationOptions ) (Decoder , error ) {
164+ publicKeyBytes , err := os .ReadFile (publicKeyFile ) // #nosec G304 -- user-provided file path
165+ if err != nil {
166+ return nil , fmt .Errorf ("error reading public key file: %w" , err )
167+ }
168+ publicKey , err := jwt .ParseECPublicKeyFromPEM (publicKeyBytes )
169+ if err != nil {
170+ return nil , fmt .Errorf ("error parsing EC public key: %w" , err )
171+ }
172+ return & esjwtDecoderWithCachedPublicKey {
173+ method : jwt .SigningMethodES256 ,
174+ publicKey : publicKey ,
175+ decoder : decoder {validationOpts : validationOpts },
176+ }, nil
177+ }
178+
112179// NewES384DecoderWithPublicKeyFile creates a new ECDSA-SHA384 JWT decoder with a public key file.
113180func NewES384DecoderWithPublicKeyFile (publicKeyFile string ) Decoder {
114181 return NewES384DecoderWithPublicKeyFileAndValidation (publicKeyFile , ValidationOptions {})
@@ -123,6 +190,61 @@ func NewES384DecoderWithPublicKeyFileAndValidation(publicKeyFile string, validat
123190 }
124191}
125192
193+ // NewES384EncoderWithCache creates a new ECDSA-SHA384 JWT encoder with cached private key.
194+ // The private key is loaded once at creation time, improving performance for repeated operations.
195+ func NewES384EncoderWithCache (privateKeyFile string ) (Encoder , error ) {
196+ privateKey , _ , err := readECDSAPrivateKey (privateKeyFile )
197+ if err != nil {
198+ return nil , err
199+ }
200+ return & esjwtEncoderWithCachedPrivateKey {
201+ method : jwt .SigningMethodES384 ,
202+ privateKey : privateKey ,
203+ }, nil
204+ }
205+
206+ // NewES384DecoderWithPrivateKeyFileAndCache creates a new ECDSA-SHA384 JWT decoder with cached public key from private key file.
207+ // The key is loaded once at creation time, improving performance for repeated operations.
208+ func NewES384DecoderWithPrivateKeyFileAndCache (privateKeyFile string ) (Decoder , error ) {
209+ return NewES384DecoderWithPrivateKeyFileAndCacheAndValidation (privateKeyFile , ValidationOptions {})
210+ }
211+
212+ // NewES384DecoderWithPrivateKeyFileAndCacheAndValidation creates a new ECDSA-SHA384 JWT decoder with cached public key and validation options.
213+ func NewES384DecoderWithPrivateKeyFileAndCacheAndValidation (privateKeyFile string , validationOpts ValidationOptions ) (Decoder , error ) {
214+ _ , publicKey , err := readECDSAPrivateKey (privateKeyFile )
215+ if err != nil {
216+ return nil , err
217+ }
218+ return & esjwtDecoderWithCachedPublicKey {
219+ method : jwt .SigningMethodES384 ,
220+ publicKey : publicKey ,
221+ decoder : decoder {validationOpts : validationOpts },
222+ }, nil
223+ }
224+
225+ // NewES384DecoderWithPublicKeyFileAndCache creates a new ECDSA-SHA384 JWT decoder with cached public key from public key file.
226+ // The key is loaded once at creation time, improving performance for repeated operations.
227+ func NewES384DecoderWithPublicKeyFileAndCache (publicKeyFile string ) (Decoder , error ) {
228+ return NewES384DecoderWithPublicKeyFileAndCacheAndValidation (publicKeyFile , ValidationOptions {})
229+ }
230+
231+ // NewES384DecoderWithPublicKeyFileAndCacheAndValidation creates a new ECDSA-SHA384 JWT decoder with cached public key and validation options.
232+ func NewES384DecoderWithPublicKeyFileAndCacheAndValidation (publicKeyFile string , validationOpts ValidationOptions ) (Decoder , error ) {
233+ publicKeyBytes , err := os .ReadFile (publicKeyFile ) // #nosec G304 -- user-provided file path
234+ if err != nil {
235+ return nil , fmt .Errorf ("error reading public key file: %w" , err )
236+ }
237+ publicKey , err := jwt .ParseECPublicKeyFromPEM (publicKeyBytes )
238+ if err != nil {
239+ return nil , fmt .Errorf ("error parsing EC public key: %w" , err )
240+ }
241+ return & esjwtDecoderWithCachedPublicKey {
242+ method : jwt .SigningMethodES384 ,
243+ publicKey : publicKey ,
244+ decoder : decoder {validationOpts : validationOpts },
245+ }, nil
246+ }
247+
126248// NewES512DecoderWithPublicKeyFile creates a new ECDSA-SHA512 JWT decoder with a public key file.
127249func NewES512DecoderWithPublicKeyFile (publicKeyFile string ) Decoder {
128250 return NewES512DecoderWithPublicKeyFileAndValidation (publicKeyFile , ValidationOptions {})
@@ -137,6 +259,61 @@ func NewES512DecoderWithPublicKeyFileAndValidation(publicKeyFile string, validat
137259 }
138260}
139261
262+ // NewES512EncoderWithCache creates a new ECDSA-SHA512 JWT encoder with cached private key.
263+ // The private key is loaded once at creation time, improving performance for repeated operations.
264+ func NewES512EncoderWithCache (privateKeyFile string ) (Encoder , error ) {
265+ privateKey , _ , err := readECDSAPrivateKey (privateKeyFile )
266+ if err != nil {
267+ return nil , err
268+ }
269+ return & esjwtEncoderWithCachedPrivateKey {
270+ method : jwt .SigningMethodES512 ,
271+ privateKey : privateKey ,
272+ }, nil
273+ }
274+
275+ // NewES512DecoderWithPrivateKeyFileAndCache creates a new ECDSA-SHA512 JWT decoder with cached public key from private key file.
276+ // The key is loaded once at creation time, improving performance for repeated operations.
277+ func NewES512DecoderWithPrivateKeyFileAndCache (privateKeyFile string ) (Decoder , error ) {
278+ return NewES512DecoderWithPrivateKeyFileAndCacheAndValidation (privateKeyFile , ValidationOptions {})
279+ }
280+
281+ // NewES512DecoderWithPrivateKeyFileAndCacheAndValidation creates a new ECDSA-SHA512 JWT decoder with cached public key and validation options.
282+ func NewES512DecoderWithPrivateKeyFileAndCacheAndValidation (privateKeyFile string , validationOpts ValidationOptions ) (Decoder , error ) {
283+ _ , publicKey , err := readECDSAPrivateKey (privateKeyFile )
284+ if err != nil {
285+ return nil , err
286+ }
287+ return & esjwtDecoderWithCachedPublicKey {
288+ method : jwt .SigningMethodES512 ,
289+ publicKey : publicKey ,
290+ decoder : decoder {validationOpts : validationOpts },
291+ }, nil
292+ }
293+
294+ // NewES512DecoderWithPublicKeyFileAndCache creates a new ECDSA-SHA512 JWT decoder with cached public key from public key file.
295+ // The key is loaded once at creation time, improving performance for repeated operations.
296+ func NewES512DecoderWithPublicKeyFileAndCache (publicKeyFile string ) (Decoder , error ) {
297+ return NewES512DecoderWithPublicKeyFileAndCacheAndValidation (publicKeyFile , ValidationOptions {})
298+ }
299+
300+ // NewES512DecoderWithPublicKeyFileAndCacheAndValidation creates a new ECDSA-SHA512 JWT decoder with cached public key and validation options.
301+ func NewES512DecoderWithPublicKeyFileAndCacheAndValidation (publicKeyFile string , validationOpts ValidationOptions ) (Decoder , error ) {
302+ publicKeyBytes , err := os .ReadFile (publicKeyFile ) // #nosec G304 -- user-provided file path
303+ if err != nil {
304+ return nil , fmt .Errorf ("error reading public key file: %w" , err )
305+ }
306+ publicKey , err := jwt .ParseECPublicKeyFromPEM (publicKeyBytes )
307+ if err != nil {
308+ return nil , fmt .Errorf ("error parsing EC public key: %w" , err )
309+ }
310+ return & esjwtDecoderWithCachedPublicKey {
311+ method : jwt .SigningMethodES512 ,
312+ publicKey : publicKey ,
313+ decoder : decoder {validationOpts : validationOpts },
314+ }, nil
315+ }
316+
140317func readECDSAPrivateKey (privateKeyFile string ) (crypto.PrivateKey , crypto.PublicKey , error ) {
141318 contentKeyFile , err := os .ReadFile (privateKeyFile ) // #nosec G304 -- user-provided file path
142319 if err != nil {
@@ -184,3 +361,11 @@ func (j *esjwtDecoderWithPublicKeyFile) Decode(token string) (string, error) {
184361 }
185362 return j .decoder .DecodeJWT (key , token )
186363}
364+
365+ func (j * esjwtEncoderWithCachedPrivateKey ) Encode (payload string ) (string , error ) {
366+ return j .encoder .EncodeJWT (j .privateKey , j .method , payload )
367+ }
368+
369+ func (j * esjwtDecoderWithCachedPublicKey ) Decode (token string ) (string , error ) {
370+ return j .decoder .DecodeJWT (j .publicKey , token )
371+ }
0 commit comments