@@ -12,8 +12,14 @@ import (
1212 "crypto/sha512"
1313 "crypto/subtle"
1414 "fmt"
15+
16+ // JWX v2 - for backward compatibility (used by existing NewJWSSigner/NewJWSVerifier)
1517 "github.com/lestrrat-go/jwx/v2/jwa"
1618 "github.com/lestrrat-go/jwx/v2/jws"
19+
20+ // JWX v3 - for new V3 functions (used by NewJWSSignerV3/NewJWSVerifierV3)
21+ jwav3 "github.com/lestrrat-go/jwx/v3/jwa"
22+ jwsv3 "github.com/lestrrat-go/jwx/v3/jws"
1723)
1824
1925// Signer includes a cryptographic key (typically a private key) and configuration of what needs to be signed.
@@ -125,16 +131,21 @@ func NewEd25519SignerFromSeed(seed []byte, config *SignConfig, fields Fields) (*
125131 return NewEd25519Signer (key , config , fields )
126132}
127133
128- // NewJWSSigner creates a generic signer for JWS algorithms, using the go-jwx package. The particular key type for each algorithm
134+ // NewJWSSigner creates a generic signer for JWS algorithms, using the go-jwx v2 package. The particular key type for each algorithm
129135// is documented in that package.
130136// Config may be nil for a default configuration.
137+ //
138+ // Note: This function uses jwx v2. For jwx v3 support, use NewJWSSignerV3 instead.
131139func NewJWSSigner (alg jwa.SignatureAlgorithm , key interface {}, config * SignConfig , fields Fields ) (* Signer , error ) {
132140 if key == nil {
133141 return nil , fmt .Errorf ("key must not be nil" )
134142 }
135143 if alg == jwa .NoSignature {
136144 return nil , fmt .Errorf ("the NONE signing algorithm is expressly disallowed" )
137145 }
146+ if config == nil {
147+ config = NewSignConfig ()
148+ }
138149 jwsSigner , err := jws .NewSigner (alg )
139150 if err != nil {
140151 return nil , err
@@ -148,16 +159,52 @@ func NewJWSSigner(alg jwa.SignatureAlgorithm, key interface{}, config *SignConfi
148159 }, nil
149160}
150161
162+ // NewJWSSignerV3 creates a generic signer for JWS algorithms, using the go-jwx v3 package. The particular key type for each algorithm
163+ // is documented in that package.
164+ // Config may be nil for a default configuration.
165+ //
166+ // This function uses jwx v3 and is the recommended choice for new code using jwx v3.
167+ // It uses the recommended SignerFor() API which returns Signer2 interface.
168+ func NewJWSSignerV3 (alg jwav3.SignatureAlgorithm , key interface {}, config * SignConfig , fields Fields ) (* Signer , error ) {
169+ if key == nil {
170+ return nil , fmt .Errorf ("key must not be nil" )
171+ }
172+ if alg == jwav3 .NoSignature () {
173+ return nil , fmt .Errorf ("the NONE signing algorithm is expressly disallowed" )
174+ }
175+ if config == nil {
176+ config = NewSignConfig ()
177+ }
178+ jwsSigner , err := jwsv3 .SignerFor (alg )
179+ if err != nil {
180+ return nil , err
181+ }
182+ return & Signer {
183+ key : key ,
184+ alg : "" ,
185+ config : config ,
186+ fields : fields ,
187+ foreignSigner : jwsSigner ,
188+ }, nil
189+ }
190+
151191func (s Signer ) sign (buff []byte ) ([]byte , error ) {
152192 if s .foreignSigner != nil {
153- switch signer := s .foreignSigner .(type ) {
154- case jws.Signer :
155- {
156- return signer .Sign (buff , s .key )
157- }
158- default :
159- return nil , fmt .Errorf ("expected jws.Signer, got %T" , s .foreignSigner )
193+ // Try v2 signer first (jws.Signer interface: Sign(payload, key))
194+ if signerV2 , ok := s .foreignSigner .(jws.Signer ); ok {
195+ return signerV2 .Sign (buff , s .key )
196+ }
197+
198+ // Try v3 Signer2 interface (new recommended API: Sign(key, payload))
199+ // Note: parameter order is SWAPPED compared to v2!
200+ type Signer2 interface {
201+ Sign (key interface {}, payload []byte ) ([]byte , error )
202+ }
203+ if signerV3 , ok := s .foreignSigner .(Signer2 ); ok {
204+ return signerV3 .Sign (s .key , buff ) // Note: key first, payload second
160205 }
206+
207+ return nil , fmt .Errorf ("expected jws.Signer or Signer2 interface, got %T" , s .foreignSigner )
161208 }
162209 switch s .alg {
163210 case "hmac-sha256" :
@@ -300,9 +347,11 @@ func NewEd25519Verifier(key ed25519.PublicKey, config *VerifyConfig, fields Fiel
300347 }, nil
301348}
302349
303- // NewJWSVerifier creates a generic verifier for JWS algorithms, using the go-jwx package. The particular key type for each algorithm
350+ // NewJWSVerifier creates a generic verifier for JWS algorithms, using the go-jwx v2 package. The particular key type for each algorithm
304351// is documented in that package. Set config to nil for a default configuration.
305352// Fields is the list of required headers and fields, which may be empty (but this is typically insecure).
353+ //
354+ // Note: This function uses jwx v2. For jwx v3 support, use NewJWSVerifierV3 instead.
306355func NewJWSVerifier (alg jwa.SignatureAlgorithm , key interface {}, config * VerifyConfig , fields Fields ) (* Verifier , error ) {
307356 if key == nil {
308357 return nil , fmt .Errorf ("key must not be nil" )
@@ -326,18 +375,60 @@ func NewJWSVerifier(alg jwa.SignatureAlgorithm, key interface{}, config *VerifyC
326375 }, nil
327376}
328377
378+ // NewJWSVerifierV3 creates a generic verifier for JWS algorithms, using the go-jwx v3 package. The particular key type for each algorithm
379+ // is documented in that package. Set config to nil for a default configuration.
380+ // Fields is the list of required headers and fields, which may be empty (but this is typically insecure).
381+ //
382+ // This function uses jwx v3 and is the recommended choice for new code using jwx v3.
383+ // It uses the recommended VerifierFor() API which returns Verifier2 interface.
384+ func NewJWSVerifierV3 (alg jwav3.SignatureAlgorithm , key interface {}, config * VerifyConfig , fields Fields ) (* Verifier , error ) {
385+ if key == nil {
386+ return nil , fmt .Errorf ("key must not be nil" )
387+ }
388+ if config == nil {
389+ config = NewVerifyConfig ()
390+ }
391+ if alg == jwav3 .NoSignature () {
392+ return nil , fmt .Errorf ("the NONE signing algorithm is expressly disallowed" )
393+ }
394+ verifier , err := jwsv3 .VerifierFor (alg )
395+ if err != nil {
396+ return nil , err
397+ }
398+ return & Verifier {
399+ key : key ,
400+ alg : "" ,
401+ config : config ,
402+ fields : fields ,
403+ foreignVerifier : verifier ,
404+ }, nil
405+ }
406+
329407func (v Verifier ) verify (buff []byte , sig []byte ) (bool , error ) {
330408 if v .foreignVerifier != nil {
331- switch verifier := v . foreignVerifier .( type ) {
332- case jws.Verifier :
333- err := verifier .Verify (buff , sig , v .key )
409+ // Try v2 verifier first (jws.Verifier interface: Verify(payload, sig, key))
410+ if verifierV2 , ok := v . foreignVerifier .( jws.Verifier ); ok {
411+ err := verifierV2 .Verify (buff , sig , v .key )
334412 if err != nil {
335413 return false , err
336414 }
337415 return true , nil
338- default :
339- return false , fmt .Errorf ("expected jws.Verifier, got %T" , v .foreignVerifier )
340416 }
417+
418+ // Try v3 Verifier2 interface (new recommended API: Verify(key, payload, sig))
419+ // Note: parameter order is DIFFERENT compared to v2!
420+ type Verifier2 interface {
421+ Verify (key interface {}, payload , signature []byte ) error
422+ }
423+ if verifierV3 , ok := v .foreignVerifier .(Verifier2 ); ok {
424+ err := verifierV3 .Verify (v .key , buff , sig ) // Note: key first, then payload, then signature
425+ if err != nil {
426+ return false , err
427+ }
428+ return true , nil
429+ }
430+
431+ return false , fmt .Errorf ("expected jws.Verifier or Verifier2 interface, got %T" , v .foreignVerifier )
341432 }
342433
343434 switch v .alg {
0 commit comments