func (h *EssentialHeader) Construct(m map[string]interface{}) error { r := emap.Hmap(m) if alg, err := r.GetString("alg"); err == nil { h.Algorithm = jwa.SignatureAlgorithm(alg) } if h.Algorithm == "" { h.Algorithm = jwa.NoSignature } h.ContentType, _ = r.GetString("cty") h.KeyID, _ = r.GetString("kid") h.Type, _ = r.GetString("typ") h.X509CertThumbprint, _ = r.GetString("x5t") h.X509CertThumbprintS256, _ = r.GetString("x5t#256") if v, err := r.GetStringSlice("crit"); err != nil { h.Critical = v } if v, err := r.GetStringSlice("x5c"); err != nil { h.X509CertChain = v } if v, err := r.GetString("jku"); err == nil { u, err := url.Parse(v) if err == nil { h.JwkSetURL = u } } if v, err := r.GetString("x5u"); err == nil { u, err := url.Parse(v) if err == nil { h.X509Url = u } } return nil }
// VerifyWithJWK verifies the JWS message using JWK keys func VerifyWithJWK(buf []byte, keyset *jwk.Set) ([]byte, error) { m, err := Parse(buf) if err != nil { return nil, err } for _, key := range keyset.Keys { if u := key.Use(); u != "" && u != "enc" { continue } keyval, err := key.Materialize() if err != nil { return nil, err } alg := jwa.SignatureAlgorithm(key.Alg()) var verifier Verifier switch key.Kty() { case jwa.RSA: pubkey, ok := keyval.(*rsa.PublicKey) if !ok { return nil, errors.New("invalid key: *rsa.PublicKey is required") } verifier, err = NewRsaVerify(alg, pubkey) if err != nil { return nil, err } case jwa.EC: pubkey, ok := keyval.(*ecdsa.PublicKey) if !ok { return nil, errors.New("invalid key: *ecdsa.PublicKey is required") } verifier, err = NewEcdsaVerify(alg, pubkey) if err != nil { return nil, err } case jwa.OctetSeq: sharedkey, ok := keyval.([]byte) if !ok { return nil, errors.New("invalid key: []byte is required") } verifier, err = NewHmacVerify(alg, sharedkey) if err != nil { return nil, err } default: continue } if err := verifier.Verify(m); err != nil { continue } return m.Payload.Bytes(), nil } return nil, errors.New("failed to verify") }
func verifyMessageWithJWK(m *Message, key jwk.Key) error { keyval, err := key.Materialize() if err != nil { return err } alg := jwa.SignatureAlgorithm(key.Alg()) var verifier Verifier switch key.Kty() { case jwa.RSA: pubkey, ok := keyval.(*rsa.PublicKey) if !ok { return errors.New("invalid key: *rsa.PublicKey is required") } verifier, err = NewRsaVerify(alg, pubkey) if err != nil { return err } case jwa.EC: pubkey, ok := keyval.(*ecdsa.PublicKey) if !ok { return errors.New("invalid key: *ecdsa.PublicKey is required") } verifier, err = NewEcdsaVerify(alg, pubkey) if err != nil { return err } case jwa.OctetSeq: sharedkey, ok := keyval.([]byte) if !ok { return errors.New("invalid key: []byte is required") } verifier, err = NewHmacVerify(alg, sharedkey) if err != nil { return err } default: // don't know what this is... return errors.New("unknown signature algorithm") } if err := verifier.Verify(m); err != nil { // we return a stock "failed to verify" error so callers // can differentiate between other errors and Verify() failing // note: this masks potential errors within Verify(), but ... hmmm return errVerifyFailed } return nil }
// Construct walks through the map (most likely parsed from a JSON buffer) // and populates the necessary fields on this header func (h *EssentialHeader) Construct(m map[string]interface{}) error { r := emap.Hmap(m) if alg, err := r.GetString("alg"); err == nil { h.Algorithm = jwa.SignatureAlgorithm(alg) } if h.Algorithm == "" { h.Algorithm = jwa.NoSignature } h.ContentType, _ = r.GetString("cty") h.KeyID, _ = r.GetString("kid") h.Type, _ = r.GetString("typ") h.X509CertThumbprint, _ = r.GetString("x5t") h.X509CertThumbprintS256, _ = r.GetString("x5t#256") if v, err := r.GetStringSlice("crit"); err != nil { h.Critical = v } if v, err := r.GetStringSlice("x5c"); err != nil { h.X509CertChain = v } if v, err := r.GetByteSlice("jwk"); err == nil { if jwks, err := jwk.Parse(v); err == nil { if len(jwks.Keys) != 1 { // The spec says "a JWK", so I believe this should represent // one JWK. check for that, and if not, return an error because // the JWS is probably invalid (XXX: send in a PR if there are // cases where this must work in the wild) return errors.New("expected a single JWK in this field") } h.Jwk = jwks.Keys[0] } } if v, err := r.GetString("jku"); err == nil { u, err := url.Parse(v) if err == nil { h.JwkSetURL = u } } if v, err := r.GetString("x5u"); err == nil { u, err := url.Parse(v) if err == nil { h.X509Url = u } } return nil }
func (h *Header) Set(key string, value interface{}) error { switch key { case "alg": var v jwa.SignatureAlgorithm s, ok := value.(string) if ok { v = jwa.SignatureAlgorithm(s) } else { v, ok = value.(jwa.SignatureAlgorithm) if !ok { return ErrInvalidHeaderValue } } h.Algorithm = v case "cty": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } h.ContentType = v case "kid": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } h.KeyID = v case "typ": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } h.Type = v case "x5t": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } h.X509CertThumbprint = v case "x5t#256": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } h.X509CertThumbprintS256 = v case "x5c": v, ok := value.([]string) if !ok { return ErrInvalidHeaderValue } h.X509CertChain = v case "crit": v, ok := value.([]string) if !ok { return ErrInvalidHeaderValue } h.Critical = v case "jku": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } u, err := url.Parse(v) if err != nil { return ErrInvalidHeaderValue } h.JwkSetURL = u case "x5u": v, ok := value.(string) if !ok { return ErrInvalidHeaderValue } u, err := url.Parse(v) if err != nil { return ErrInvalidHeaderValue } h.X509Url = u default: h.PrivateParams[key] = value } return nil }
func TestRsaSign_SignWithBadAlgorithm(t *testing.T) { _, err := NewRsaSign(jwa.SignatureAlgorithm("FooBar"), nil) if !assert.Equal(t, ErrUnsupportedAlgorithm, err, "Creating signer with unknown algorithm should return error") { return } }