Skip to content

Commit 9d5fb50

Browse files
committed
feat: add digest verification
1 parent 19f9b8f commit 9d5fb50

2 files changed

Lines changed: 153 additions & 0 deletions

File tree

digest.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ package httpsig
3434
import (
3535
"crypto/sha256"
3636
"crypto/sha512"
37+
"crypto/subtle"
3738
"errors"
3839
"net/http"
3940

@@ -97,6 +98,41 @@ func (d *digestor) Digest(body []byte) (http.Header, error) {
9798
return hdr, nil
9899
}
99100

101+
func (d *digestor) Verify(body []byte, header http.Header) error {
102+
dict, err := httpsfv.UnmarshalDictionary(header.Values(ContentDigestHeader))
103+
if err != nil {
104+
return err
105+
}
106+
107+
for _, algorithm := range d.config.Algorithms {
108+
item, ok := dict.Get(string(algorithm))
109+
if !ok {
110+
continue
111+
}
112+
113+
digest, err := calculateDigest(body, algorithm)
114+
if err != nil {
115+
return err
116+
}
117+
118+
valueItem, ok := item.(httpsfv.Item)
119+
if !ok {
120+
return errors.New("invalid digest header")
121+
}
122+
123+
value, ok := valueItem.Value.([]byte)
124+
if !ok {
125+
return errors.New("invalid digest header")
126+
}
127+
128+
if subtle.ConstantTimeCompare([]byte(digest), []byte(value)) != 1 {
129+
return errors.New("digest mismatch")
130+
}
131+
}
132+
133+
return nil
134+
}
135+
100136
func calculateDigest(body []byte, algorithm DigestAlgorithm) ([]byte, error) {
101137
switch algorithm {
102138
case DigestAlgorithmSha256:

digest_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,120 @@ func TestDigest_SHA256(t *testing.T) {
6262

6363
assert.Equal(t, `sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:`, hdr.Get(ContentDigestHeader))
6464
}
65+
66+
func TestVerify_SHA256(t *testing.T) {
67+
body := []byte("{\"hello\": \"world\"}\n")
68+
69+
d := NewDigestor(
70+
WithDigestAlgorithms(DigestAlgorithmSha256),
71+
)
72+
73+
hdr, err := d.Digest(body)
74+
assert.NoError(t, err)
75+
76+
err = d.Verify(body, hdr)
77+
assert.NoError(t, err)
78+
}
79+
80+
func TestVerify_SHA512(t *testing.T) {
81+
body := []byte("{\"hello\": \"world\"}\n")
82+
83+
d := NewDigestor(
84+
WithDigestAlgorithms(DigestAlgorithmSha512),
85+
)
86+
87+
hdr, err := d.Digest(body)
88+
assert.NoError(t, err)
89+
90+
err = d.Verify(body, hdr)
91+
assert.NoError(t, err)
92+
}
93+
94+
func TestDigest_SHA256_Verify_SHA256_SHA512(t *testing.T) {
95+
body := []byte("{\"hello\": \"world\"}\n")
96+
97+
d := NewDigestor(
98+
WithDigestAlgorithms(DigestAlgorithmSha256),
99+
)
100+
101+
hdr, err := d.Digest(body)
102+
assert.NoError(t, err)
103+
104+
err = d.Verify(body, hdr)
105+
assert.NoError(t, err)
106+
107+
d = NewDigestor(
108+
WithDigestAlgorithms(DigestAlgorithmSha256),
109+
WithDigestAlgorithms(DigestAlgorithmSha512),
110+
)
111+
112+
err = d.Verify(body, hdr)
113+
assert.NoError(t, err)
114+
}
115+
116+
func TestDigest_SHA256_SHA512_Verify_SHA256_SHA512(t *testing.T) {
117+
body := []byte("{\"hello\": \"world\"}\n")
118+
119+
d := NewDigestor(
120+
WithDigestAlgorithms(DigestAlgorithmSha256),
121+
WithDigestAlgorithms(DigestAlgorithmSha512),
122+
)
123+
124+
hdr, err := d.Digest(body)
125+
assert.NoError(t, err)
126+
127+
err = d.Verify(body, hdr)
128+
assert.NoError(t, err)
129+
130+
d = NewDigestor(
131+
WithDigestAlgorithms(DigestAlgorithmSha256),
132+
WithDigestAlgorithms(DigestAlgorithmSha512),
133+
)
134+
135+
err = d.Verify(body, hdr)
136+
assert.NoError(t, err)
137+
}
138+
139+
func TestDigest_SHA256_SHA512_Verify_SHA256(t *testing.T) {
140+
body := []byte("{\"hello\": \"world\"}\n")
141+
142+
d := NewDigestor(
143+
WithDigestAlgorithms(DigestAlgorithmSha256),
144+
WithDigestAlgorithms(DigestAlgorithmSha512),
145+
)
146+
147+
hdr, err := d.Digest(body)
148+
assert.NoError(t, err)
149+
150+
err = d.Verify(body, hdr)
151+
assert.NoError(t, err)
152+
153+
d = NewDigestor(
154+
WithDigestAlgorithms(DigestAlgorithmSha256),
155+
)
156+
157+
err = d.Verify(body, hdr)
158+
assert.NoError(t, err)
159+
}
160+
161+
func TestDigest_SHA256_SHA512_Verify_SHA512(t *testing.T) {
162+
body := []byte("{\"hello\": \"world\"}\n")
163+
164+
d := NewDigestor(
165+
WithDigestAlgorithms(DigestAlgorithmSha256),
166+
WithDigestAlgorithms(DigestAlgorithmSha512),
167+
)
168+
169+
hdr, err := d.Digest(body)
170+
assert.NoError(t, err)
171+
172+
err = d.Verify(body, hdr)
173+
assert.NoError(t, err)
174+
175+
d = NewDigestor(
176+
WithDigestAlgorithms(DigestAlgorithmSha512),
177+
)
178+
179+
err = d.Verify(body, hdr)
180+
assert.NoError(t, err)
181+
}

0 commit comments

Comments
 (0)