@@ -2,8 +2,11 @@ package httpsign
22
33import (
44 "encoding/base64"
5- "github.com/stretchr/testify/assert"
5+ "net/http"
6+ "net/url"
67 "testing"
8+
9+ "github.com/stretchr/testify/assert"
710)
811
912var httpreq1pssNoSig = `POST /foo?param=Value&Pet=dog HTTP/1.1
@@ -55,6 +58,50 @@ func FuzzVerifyRequest(f *testing.F) {
5558 })
5659}
5760
61+ // Same as FuzzVerifyRequest but using Message
62+ func FuzzMessageVerifyRequest (f * testing.F ) {
63+ type inputs struct {
64+ req , sigInput , sig string
65+ }
66+ testcases := []inputs {
67+ {httpreq1pssNoSig ,
68+ "sig-b21=();created=1618884473;keyid=\" test-key-rsa-pss\" ;nonce=\" b3k2pp5k7z-50gnwp.yemd\" " ,
69+ "sig-b21=:d2pmTvmbncD3xQm8E9ZV2828BjQWGgiwAaw5bAkgibUopemLJcWDy/lkbbHAve4cRAtx31Iq786U7it++wgGxbtRxf8Udx7zFZsckzXaJMkA7ChG52eSkFxykJeNqsrWH5S+oxNFlD4dzVuwe8DhTSja8xxbR/Z2cOGdCbzR72rgFWhzx2VjBqJzsPLMIQKhO4DGezXehhWwE56YCE+O6c0mKZsfxVrogUvA4HELjVKWmAvtl6UnCh8jYzuVG5WSb/QEVPnP5TmcAnLH1g+s++v6d4s8m0gCw1fV5/SITLq9mhho8K3+7EPYTU8IU1bLhdxO5Nyt8C8ssinQ98Xw9Q==:" ,
70+ },
71+ {httpreq1pssNoSig ,
72+ "sig-b21=(date);created=1618884473;keyid=\" test-key-rsa-pss\" ;nonce=\" xxxb3k5k7z-50gnwp.yemd\" " ,
73+ "sig-b21=:d2pmTvmbncD3xQm8E9ZV2828BjQWGgiwAaw5bAkgibUopemLJcWDy/lkbbHAve4cRAtx31Iq786U7it++wgGxbtRxf8Udx7zFZsckzXaJMkA7ChG52eSkFxykJeNqsrWH5S+oxNFlD4dzVuwe8DhTSja8xxbR/Z2cOGdCbzR72rgFWhzx2VjBqJzsPLMIQKhO4DGezXehhWwE56YCE+O6c0mKZsfxVrogUvA4HELjVKWmAvtl6UnCh8jYzuVG5WSb/QEVPnP5TmcAnLH1g+s++v6d4s8m0gCw1fV5/SITLq9mhho8K3+7EPYTU8IU1bLhdxO5Nyt8C8ssinQ98Xw9Q==:" ,
74+ },
75+ {httpreq1pssNoSig ,
76+ "sig-b21=(some-field;tr);created=1618884473;keyid=\" test-key-rsa-pss\" ;nonce=\" xxxb3k5k7z-50gnwp.yemd\" " ,
77+ "sig-b21=:d2pmTvmbncD3xQm8E9ZV2828BjQWGgiwAaw5bAkgibUopemLJcWDy/lkbbHAve4cRAtx31Iq786U7it++wgGxbtRxf8Udx7zFZsckzXaJMkA7ChG52eSkFxykJeNqsrWH5S+oxNFlD4dzVuwe8DhTSja8xxbR/Z2cOGdCbzR72rgFWhzx2VjBqJzsPLMIQKhO4DGezXehhWwE56YCE+O6c0mKZsfxVrogUvA4HELjVKWmAvtl6UnCh8jYzuVG5WSb/QEVPnP5TmcAnLH1g+s++v6d4s8m0gCw1fV5/SITLq9mhho8K3+7EPYTU8IU1bLhdxO5Nyt8C8ssinQ98Xw9Q==:" ,
78+ },
79+ {httpreq1pssNoSig ,
80+ "sig-b22=(some-field;tr;bs);created=1618884473;keyid=\" test-key-rsa-pss\" ;nonce=\" xxxb3k5k7z-50gnwp.yemd\" " ,
81+ "sig-b22=:d2pmTvmbncD3xQm8E9ZV2828BjQWGgiwAaw5bAkgibUopemLJcWDy/lkbbHAve4cRAtx31Iq786U7it++wgGxbtRxf8Udx7zFZsckzXaJMkA7ChG52eSkFxykJeNqsrWH5S+oxNFlD4dzVuwe8DhTSja8xxbR/Z2cOGdCbzR72rgFWhzx2VjBqJzsPLMIQKhO4DGezXehhWwE56YCE+O6c0mKZsfxVrogUvA4HELjVKWmAvtl6UnCh8jYzuVG5WSb/QEVPnP5TmcAnLH1g+s++v6d4s8m0gCw1fV5/SITLq9mhho8K3+7EPYTU8IU1bLhdxO5Nyt8C8ssinQ98Xw9Q==:" ,
82+ },
83+ }
84+ for _ , tc := range testcases {
85+ f .Add (tc .req , tc .sigInput , tc .sig ) // Use f.Add to provide a seed corpus
86+ }
87+ f .Fuzz (func (t * testing.T , reqString , sigInput , sig string ) {
88+ req := readRequest (reqString )
89+ if req != nil {
90+ req .Header .Set ("Signature-Input" , sigInput )
91+ req .Header .Set ("Signature" , sig )
92+ }
93+
94+ sigName := "sig-b21"
95+ verifier := makeRSAVerifier (f , "key1" , * NewFields ())
96+ msg , err := NewMessage (NewMessageConfig ().WithRequest (req ))
97+ if err != nil {
98+ t .Errorf ("Failed to create Message" )
99+ }
100+ _ , _ = msg .Verify (sigName , verifier )
101+ // only report panics
102+ })
103+ }
104+
58105func FuzzSignAndVerifyHMAC (f * testing.F ) {
59106 type inputs struct {
60107 req string
@@ -83,3 +130,130 @@ func FuzzSignAndVerifyHMAC(f *testing.F) {
83130 }
84131 })
85132}
133+
134+ // Same as FuzzSignAndVerifyHMAC but using Message
135+ func FuzzMessageSignAndVerifyHMAC (f * testing.F ) {
136+ type inputs struct {
137+ req string
138+ }
139+ testcases := []inputs {
140+ {httpreq1 },
141+ }
142+ for _ , tc := range testcases {
143+ f .Add (tc .req )
144+ }
145+ f .Fuzz (func (t * testing.T , reqString string ) {
146+ config := NewSignConfig ().SignAlg (false ).setFakeCreated (1618884475 )
147+ fields := Headers ("@authority" , "date" , "content-type" )
148+ signatureName := "sig1"
149+ key , _ := base64 .StdEncoding .DecodeString ("uzvJfB4u3N0Jy4T7NZ75MDVcr8zSTInedJtkgcu46YW4XByzNJjxBdtjUkdJPBtbmHhIDi6pcl8jsasjlTMtDQ==" )
150+ signer , _ := NewHMACSHA256Signer (key , config .SetKeyID ("test-shared-secret" ), fields )
151+ req := readRequest (reqString )
152+ sigInput , sig , err := SignRequest (signatureName , * signer , req )
153+ if err == nil {
154+ req .Header .Add ("Signature" , sig )
155+ req .Header .Add ("Signature-Input" , sigInput )
156+ verifier , err := NewHMACSHA256Verifier (key , NewVerifyConfig ().SetVerifyCreated (false ).SetKeyID ("test-shared-secret" ), fields )
157+ assert .NoError (t , err , "could not generate Verifier" )
158+ msg , err := NewMessage (NewMessageConfig ().WithRequest (req ))
159+ if err != nil {
160+ t .Errorf ("Failed to create Message" )
161+ }
162+ _ , err = msg .Verify (signatureName , * verifier )
163+ assert .NoError (t , err , "verification error" )
164+ }
165+ })
166+ }
167+
168+ func FuzzMessageVerify (f * testing.F ) {
169+ f .Add ("GET" , "https://example.com/path" , "example.com" , "https" , 0 , "" , "" , "" , "" , true , false )
170+ f .Add ("POST" , "https://api.example.com" , "api.example.com" , "https" , 0 , "" , "" , "" , "" , false , true )
171+ f .Add ("" , "" , "" , "" , 200 , "GET" , "https://example.com" , "example.com" , "https" , true , false )
172+ f .Add ("PUT" , "" , "" , "http" , 0 , "" , "" , "" , "" , false , false )
173+ f .Add ("" , "" , "" , "" , 404 , "" , "" , "" , "" , false , false )
174+ f .Add ("0" , "%" , "0" , "0" , 0 , "" , "" , "" , "" , true , false )
175+
176+ f .Fuzz (func (t * testing.T , method , urlStr , authority , scheme string , statusCode int ,
177+ assocMethod , assocURLStr , assocAuthority , assocScheme string ,
178+ hasHeaders , hasTrailers bool ) {
179+
180+ config := NewMessageConfig ()
181+
182+ if method != "" {
183+ config = config .WithMethod (method )
184+ }
185+ if urlStr != "" {
186+ u , err := url .Parse (urlStr )
187+ if err == nil {
188+ config = config .WithURL (u )
189+ }
190+ }
191+ if authority != "" {
192+ config = config .WithAuthority (authority )
193+ }
194+ if scheme != "" {
195+ config = config .WithScheme (scheme )
196+ }
197+
198+ if statusCode > 0 {
199+ config = config .WithStatusCode (statusCode )
200+ }
201+
202+ if hasHeaders {
203+ headers := http.Header {
204+ "Content-Type" : []string {"application/json" },
205+ "X-Test" : []string {"fuzz" },
206+ }
207+ config = config .WithHeaders (headers )
208+ }
209+ if hasTrailers {
210+ trailers := http.Header {
211+ "X-Trailer" : []string {"test" },
212+ }
213+ config = config .WithTrailers (trailers )
214+ }
215+
216+ if statusCode > 0 && assocMethod != "" {
217+ var assocURL * url.URL
218+ if assocURLStr != "" {
219+ assocURL , _ = url .Parse (assocURLStr )
220+ }
221+ assocHeaders := http.Header {"X-Assoc" : []string {"test" }}
222+ config = config .WithAssociatedRequest (assocMethod , assocURL , assocHeaders , assocAuthority , assocScheme )
223+ }
224+
225+ msg , err := NewMessage (config )
226+
227+ if err == nil {
228+ if msg .headers == nil && msg .method != "" {
229+ t .Errorf ("Request message created without headers" )
230+ }
231+ if msg .headers == nil && msg .statusCode != nil {
232+ t .Errorf ("Response message created without headers" )
233+ }
234+
235+ key , _ := base64 .StdEncoding .DecodeString ("uzvJfB4u3N0Jy4T7NZ75MDVcr8zSTInedJtkgcu46YW4XByzNJjxBdtjUkdJPBtbmHhIDi6pcl8jsasjlTMtDQ==" )
236+ verifier , _ := NewHMACSHA256Verifier (key , NewVerifyConfig ().SetVerifyCreated (false ), Fields {})
237+
238+ if msg .headers != nil {
239+ msg .headers .Set ("Signature-Input" , `sig1=("@method");created=1618884473;keyid="test-key"` )
240+ msg .headers .Set ("Signature" , `sig1=:test:` )
241+ }
242+
243+ _ , _ = msg .Verify ("sig1" , * verifier )
244+ }
245+
246+ if err != nil {
247+ hasRequest := method != ""
248+ hasResponse := statusCode > 0
249+
250+ if ! hasRequest && ! hasResponse {
251+ assert .Contains (t , err .Error (), "must have either method" )
252+ } else if hasRequest && hasResponse {
253+ assert .Contains (t , err .Error (), "cannot have both request and response" )
254+ } else if (hasRequest || hasResponse ) && ! hasHeaders {
255+ assert .Contains (t , err .Error (), "must have headers" )
256+ }
257+ }
258+ })
259+ }
0 commit comments