From 0ba05480e4eb38fcb0685fd85533d3dbef898116 Mon Sep 17 00:00:00 2001 From: Ichinose Shogo Date: Mon, 7 Nov 2022 13:17:36 +0900 Subject: [PATCH] implement marshal json --- go.mod | 3 +- go.sum | 2 + jws/fuzz_test.go | 151 +++++++++++++++++ jws/jws.go | 27 +++ jws/jws_test.go | 159 +++++++++++++++++- ...6643ef9239cb74af81e5d7a08fc5f1e3bc599ebc4e | 0 ...8551dc95b446c75b3c3f903d888e81714127e53ad9 | 0 ...61ed3ca85cdf6e83c3f1ee2caf5cc4ec784ece8173 | 0 ...22772847ba21dd86bc1e9692793505205cdd04bc03 | 0 ...9ab145521028a4d3ca6b221b24c083bbf46d865109 | 0 ...622352602bb967d84e8cbb13b40ebdd4ddabea7e98 | 0 ...115695c3d96fe587eb0d4cf4bafcebf807cc54e4ad | 0 12 files changed, 340 insertions(+), 2 deletions(-) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/03e56becdff763a4b3cceb6643ef9239cb74af81e5d7a08fc5f1e3bc599ebc4e (100%) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/04ae3b7d597ad0746745cf8551dc95b446c75b3c3f903d888e81714127e53ad9 (100%) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/15bb34ecdfb84f2aa52c3e61ed3ca85cdf6e83c3f1ee2caf5cc4ec784ece8173 (100%) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/5b7c500ef50e24e31e204022772847ba21dd86bc1e9692793505205cdd04bc03 (100%) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/9f36fb0a8eaa39cdd0b3bb9ab145521028a4d3ca6b221b24c083bbf46d865109 (100%) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/a758fc09962c730050f778622352602bb967d84e8cbb13b40ebdd4ddabea7e98 (100%) rename jws/testdata/fuzz/{FuzzJWS => FuzzJWSCompact}/e346c856959f11ef0653d2115695c3d96fe587eb0d4cf4bafcebf807cc54e4ad (100%) diff --git a/go.mod b/go.mod index caaee2f..0f714b4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,8 @@ go 1.19 require ( github.com/shogo82148/memoize v0.0.2 + github.com/shogo82148/pointer v1.2.0 golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be ) -require github.com/shogo82148/pointer v1.2.0 +require golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect diff --git a/go.sum b/go.sum index 506b7f7..45d9c98 100644 --- a/go.sum +++ b/go.sum @@ -4,3 +4,5 @@ github.com/shogo82148/pointer v1.2.0 h1:MEPjAx9hK17sdEVhaqHROphdy+RxTH70vaBypZzZ github.com/shogo82148/pointer v1.2.0/go.mod h1:agZ5JFpavFPXznbWonIvbG78NDfvDTFppe+7o53up5w= golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A= golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/jws/fuzz_test.go b/jws/fuzz_test.go index 463b41a..c08cd0b 100644 --- a/jws/fuzz_test.go +++ b/jws/fuzz_test.go @@ -14,6 +14,157 @@ import ( ) func FuzzJWS(f *testing.F) { + f.Add( + `{`+ + `"payload":`+ + `"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF`+ + `tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",`+ + `"signatures":[`+ + `{"protected":"eyJhbGciOiJSUzI1NiJ9",`+ + `"header":`+ + `{"kid":"2010-12-29"},`+ + `"signature":`+ + `"cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ`+ + `mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb`+ + `KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl`+ + `b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES`+ + `c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX`+ + `LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"},`+ + `{"protected":"eyJhbGciOiJFUzI1NiJ9",`+ + `"header":`+ + `{"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},`+ + `"signature":`+ + `"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS`+ + `lSApmWQxfKTUJqPP3-Kg6NU1Q"}]`+ + `}`, + `{"kty":"RSA",`+ + `"n":"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx`+ + `HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs`+ + `D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH`+ + `SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV`+ + `MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8`+ + `NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ",`+ + `"e":"AQAB",`+ + `"d":"Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I`+ + `jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0`+ + `BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn`+ + `439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT`+ + `CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh`+ + `BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ",`+ + `"p":"4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi`+ + `YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG`+ + `BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc",`+ + `"q":"uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa`+ + `ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA`+ + `-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc",`+ + `"dp":"BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q`+ + `CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb`+ + `34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0",`+ + `"dq":"h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa`+ + `7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky`+ + `NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU",`+ + `"qi":"IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o`+ + `y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU`+ + `W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U"`+ + `}`, + ) + + f.Add( + `{`+ + `"payload":`+ + `"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF`+ + `tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",`+ + `"signatures":[`+ + `{"protected":"eyJhbGciOiJSUzI1NiJ9",`+ + `"header":`+ + `{"kid":"2010-12-29"},`+ + `"signature":`+ + `"cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ`+ + `mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb`+ + `KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl`+ + `b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES`+ + `c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX`+ + `LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"},`+ + `{"protected":"eyJhbGciOiJFUzI1NiJ9",`+ + `"header":`+ + `{"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},`+ + `"signature":`+ + `"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS`+ + `lSApmWQxfKTUJqPP3-Kg6NU1Q"}]`+ + `}`, + `{"kty":"EC",`+ + `"crv":"P-256",`+ + `"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",`+ + `"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",`+ + `"d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI"`+ + `}`, + ) + + f.Add(`{`+ + `"payload":`+ + `"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF`+ + `tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",`+ + `"protected":"eyJhbGciOiJFUzI1NiJ9",`+ + `"header":`+ + `{"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},`+ + `"signature":`+ + `"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS`+ + `lSApmWQxfKTUJqPP3-Kg6NU1Q"`+ + `}`, + `{"kty":"EC",`+ + `"crv":"P-256",`+ + `"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",`+ + `"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",`+ + `"d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI"`+ + `}`, + ) + f.Fuzz(func(t *testing.T, raw, rawKey string) { + var msg1 Message + if err := msg1.UnmarshalJSON([]byte(raw)); err != nil { + return + } + + key, err := jwk.ParseKey([]byte(rawKey)) + if err != nil { + return + } + + var header1 *Header + protected1, payload1, err := msg1.Verify(FindKeyFunc(func(protected, header *Header) (sig.SigningKey, error) { + header1 = header + return protected.Algorithm().New().NewSigningKey(key), nil + })) + if err != nil { + return + } + + msg2 := NewMessage(payload1) + if err := msg2.Sign(protected1, header1, protected1.Algorithm().New().NewSigningKey(key)); err != nil { + t.Fatal(err) + } + + data, err := msg2.MarshalJSON() + if err != nil { + t.Fatal(err) + } + + var msg3 Message + if err := msg3.UnmarshalJSON(data); err != nil { + t.Fatal(err) + } + _, payload3, err := msg1.Verify(FindKeyFunc(func(protected, header *Header) (sig.SigningKey, error) { + return protected.Algorithm().New().NewSigningKey(key), nil + })) + if err != nil { + return + } + if string(payload1) != string(payload3) { + t.Errorf("want %s, got %s", string(payload1), string(payload3)) + } + }) +} + +func FuzzJWSCompact(f *testing.F) { f.Add( "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9"+ "."+ diff --git a/jws/jws.go b/jws/jws.go index 707be72..76ae6c0 100644 --- a/jws/jws.go +++ b/jws/jws.go @@ -405,6 +405,33 @@ func (msg *Message) UnmarshalJSON(data []byte) error { return nil } +func (msg *Message) MarshalJSON() ([]byte, error) { + raw := map[string]any{ + "payload": string(msg.payload), + } + if len(msg.Signatures) == 1 { + // Flattened JWS JSON Serialization + sig := msg.Signatures[0] + raw["protected"] = string(sig.raw) + raw["signature"] = string(sig.b64signature) + } else { + // Complete JWS JSON Serialization Representation + signatures := make([]any, 0, len(msg.Signatures)) + for _, sig := range msg.Signatures { + raw := map[string]any{ + "protected": string(sig.raw), + "signature": string(sig.b64signature), + } + if sig.header != nil { + raw["header"] = sig.header + } + signatures = append(signatures, raw) + } + raw["signatures"] = signatures + } + return json.Marshal(raw) +} + func decodeHeader(raw map[string]any) (*Header, error) { d := jsonutils.NewDecoder("jws", raw) h := &Header{ diff --git a/jws/jws_test.go b/jws/jws_test.go index bc6a688..8a2ceac 100644 --- a/jws/jws_test.go +++ b/jws/jws_test.go @@ -2,6 +2,7 @@ package jws import ( "bytes" + "encoding/json" "errors" "testing" @@ -290,7 +291,7 @@ func TestVerify(t *testing.T) { }) } -func TestParseJSON(t *testing.T) { +func TestUnmarshalJSON(t *testing.T) { t.Run("RFC 7515 Appendix A.6. Example JWS Using General JWS JSON Serialization", func(t *testing.T) { raw := `{` + `"payload":` + @@ -472,6 +473,162 @@ func TestParseJSON(t *testing.T) { }) } +func TestMarshalJSON(t *testing.T) { + t.Run("RFC 7515 Appendix A.6. Example JWS Using General JWS JSON Serialization", func(t *testing.T) { + msg := NewMessage([]byte(`{"iss":"joe",` + "\r\n" + + ` "exp":1300819380,` + "\r\n" + + ` "http://example.com/is_root":true}`)) + + protected1 := NewHeader() + protected1.SetAlgorithm(jwa.RS256) + header1 := NewHeader() + header1.SetKeyID("2010-12-29") + rawKey1 := `{"kty":"RSA",` + + `"n":"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx` + + `HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs` + + `D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH` + + `SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV` + + `MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8` + + `NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ",` + + `"e":"AQAB",` + + `"d":"Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I` + + `jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0` + + `BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn` + + `439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT` + + `CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh` + + `BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ",` + + `"p":"4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi` + + `YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG` + + `BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc",` + + `"q":"uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa` + + `ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA` + + `-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc",` + + `"dp":"BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q` + + `CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb` + + `34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0",` + + `"dq":"h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa` + + `7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky` + + `NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU",` + + `"qi":"IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o` + + `y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU` + + `W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U"` + + `}` + key1, err := jwk.ParseKey([]byte(rawKey1)) + if err != nil { + t.Fatal(err) + } + if err := msg.Sign(protected1, header1, jwa.RS256.New().NewSigningKey(key1)); err != nil { + t.Fatal(err) + } + + protected2 := NewHeader() + protected2.SetAlgorithm(jwa.ES256) + header2 := NewHeader() + header2.SetKeyID("e9bc097a-ce51-4036-9562-d2ade882db0d") + rawKey2 := `{"kty":"EC",` + + `"crv":"P-256",` + + `"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",` + + `"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",` + + `"d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI"` + + `}` + key2, err := jwk.ParseKey([]byte(rawKey2)) + if err != nil { + t.Fatal(err) + } + if err := msg.Sign(protected2, header2, jwa.ES256.New().NewSigningKey(key2)); err != nil { + t.Fatal(err) + } + + data, err := msg.MarshalJSON() + if err != nil { + t.Fatal(err) + } + + var tmp any + if err := json.Unmarshal(data, &tmp); err != nil { + t.Fatal(err) + } + }) + + t.Run("RFC 7515 Appendix A.7. Example JWS Using Flattened JWS JSON Serialization", func(t *testing.T) { + raw := `{` + + `"payload":` + + `"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF` + + `tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",` + + `"protected":"eyJhbGciOiJFUzI1NiJ9",` + + `"header":` + + `{"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},` + + `"signature":` + + `"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS` + + `lSApmWQxfKTUJqPP3-Kg6NU1Q"` + + `}` + var msg Message + if err := msg.UnmarshalJSON([]byte(raw)); err != nil { + t.Fatal(err) + } + _, payload, err := msg.Verify(FindKeyFunc(func(protected, header *Header) (sig.SigningKey, error) { + if header.KeyID() != "e9bc097a-ce51-4036-9562-d2ade882db0d" { + return nil, errors.New("unknown key id") + } + rawKey := `{"kty":"EC",` + + `"crv":"P-256",` + + `"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",` + + `"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",` + + `"d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI"` + + `}` + key, err := jwk.ParseKey([]byte(rawKey)) + if err != nil { + return nil, err + } + return protected.Algorithm().New().NewSigningKey(key), nil + })) + if err != nil { + t.Fatal(err) + } + want := []byte(`{"iss":"joe",` + "\r\n" + + ` "exp":1300819380,` + "\r\n" + + ` "http://example.com/is_root":true}`) + if !bytes.Equal(payload, want) { + t.Errorf("unexpected payload: want %q, got %q", string(want), string(payload)) + } + }) + + // test for b64 header parameter. + t.Run("RFC 7797 Section 4.2. Example with Header Parameters", func(t *testing.T) { + raw := `{` + + `"protected":` + + `"eyJhbGciOiJIUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19",` + + `"payload":` + + `"$.02",` + + `"signature":` + + `"A5dxf2s96_n5FLueVuW1Z_vh161FwXZC4YLPff6dmDY"` + + `}` + var msg Message + if err := msg.UnmarshalJSON([]byte(raw)); err != nil { + t.Fatal(err) + } + _, payload, err := msg.Verify(FindKeyFunc(func(protected, header *Header) (sig.SigningKey, error) { + rawKey := `{` + + `"kty":"oct",` + + `"k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75` + + `aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"` + + `}` + key, err := jwk.ParseKey([]byte(rawKey)) + if err != nil { + return nil, err + } + return protected.Algorithm().New().NewSigningKey(key), nil + })) + if err != nil { + t.Fatal(err) + } + want := []byte(`$.02`) + if !bytes.Equal(payload, want) { + t.Errorf("unexpected payload: want %q, got %q", string(want), string(payload)) + } + }) +} + func TestSign(t *testing.T) { t.Run("RFC7515 Appendix A.1 Example JWS Using HMAC SHA-256", func(t *testing.T) { rawKey := `{"kty":"oct",` + diff --git a/jws/testdata/fuzz/FuzzJWS/03e56becdff763a4b3cceb6643ef9239cb74af81e5d7a08fc5f1e3bc599ebc4e b/jws/testdata/fuzz/FuzzJWSCompact/03e56becdff763a4b3cceb6643ef9239cb74af81e5d7a08fc5f1e3bc599ebc4e similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/03e56becdff763a4b3cceb6643ef9239cb74af81e5d7a08fc5f1e3bc599ebc4e rename to jws/testdata/fuzz/FuzzJWSCompact/03e56becdff763a4b3cceb6643ef9239cb74af81e5d7a08fc5f1e3bc599ebc4e diff --git a/jws/testdata/fuzz/FuzzJWS/04ae3b7d597ad0746745cf8551dc95b446c75b3c3f903d888e81714127e53ad9 b/jws/testdata/fuzz/FuzzJWSCompact/04ae3b7d597ad0746745cf8551dc95b446c75b3c3f903d888e81714127e53ad9 similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/04ae3b7d597ad0746745cf8551dc95b446c75b3c3f903d888e81714127e53ad9 rename to jws/testdata/fuzz/FuzzJWSCompact/04ae3b7d597ad0746745cf8551dc95b446c75b3c3f903d888e81714127e53ad9 diff --git a/jws/testdata/fuzz/FuzzJWS/15bb34ecdfb84f2aa52c3e61ed3ca85cdf6e83c3f1ee2caf5cc4ec784ece8173 b/jws/testdata/fuzz/FuzzJWSCompact/15bb34ecdfb84f2aa52c3e61ed3ca85cdf6e83c3f1ee2caf5cc4ec784ece8173 similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/15bb34ecdfb84f2aa52c3e61ed3ca85cdf6e83c3f1ee2caf5cc4ec784ece8173 rename to jws/testdata/fuzz/FuzzJWSCompact/15bb34ecdfb84f2aa52c3e61ed3ca85cdf6e83c3f1ee2caf5cc4ec784ece8173 diff --git a/jws/testdata/fuzz/FuzzJWS/5b7c500ef50e24e31e204022772847ba21dd86bc1e9692793505205cdd04bc03 b/jws/testdata/fuzz/FuzzJWSCompact/5b7c500ef50e24e31e204022772847ba21dd86bc1e9692793505205cdd04bc03 similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/5b7c500ef50e24e31e204022772847ba21dd86bc1e9692793505205cdd04bc03 rename to jws/testdata/fuzz/FuzzJWSCompact/5b7c500ef50e24e31e204022772847ba21dd86bc1e9692793505205cdd04bc03 diff --git a/jws/testdata/fuzz/FuzzJWS/9f36fb0a8eaa39cdd0b3bb9ab145521028a4d3ca6b221b24c083bbf46d865109 b/jws/testdata/fuzz/FuzzJWSCompact/9f36fb0a8eaa39cdd0b3bb9ab145521028a4d3ca6b221b24c083bbf46d865109 similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/9f36fb0a8eaa39cdd0b3bb9ab145521028a4d3ca6b221b24c083bbf46d865109 rename to jws/testdata/fuzz/FuzzJWSCompact/9f36fb0a8eaa39cdd0b3bb9ab145521028a4d3ca6b221b24c083bbf46d865109 diff --git a/jws/testdata/fuzz/FuzzJWS/a758fc09962c730050f778622352602bb967d84e8cbb13b40ebdd4ddabea7e98 b/jws/testdata/fuzz/FuzzJWSCompact/a758fc09962c730050f778622352602bb967d84e8cbb13b40ebdd4ddabea7e98 similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/a758fc09962c730050f778622352602bb967d84e8cbb13b40ebdd4ddabea7e98 rename to jws/testdata/fuzz/FuzzJWSCompact/a758fc09962c730050f778622352602bb967d84e8cbb13b40ebdd4ddabea7e98 diff --git a/jws/testdata/fuzz/FuzzJWS/e346c856959f11ef0653d2115695c3d96fe587eb0d4cf4bafcebf807cc54e4ad b/jws/testdata/fuzz/FuzzJWSCompact/e346c856959f11ef0653d2115695c3d96fe587eb0d4cf4bafcebf807cc54e4ad similarity index 100% rename from jws/testdata/fuzz/FuzzJWS/e346c856959f11ef0653d2115695c3d96fe587eb0d4cf4bafcebf807cc54e4ad rename to jws/testdata/fuzz/FuzzJWSCompact/e346c856959f11ef0653d2115695c3d96fe587eb0d4cf4bafcebf807cc54e4ad