Skip to content
This repository was archived by the owner on Jul 12, 2023. It is now read-only.

Commit c43e7c0

Browse files
authored
Add random padding to responses (#490)
* Add random padding to responses * Make it 1-2kb
1 parent 1c49680 commit c43e7c0

File tree

1 file changed

+41
-14
lines changed

1 file changed

+41
-14
lines changed

pkg/api/api.go

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616
// well as between mobile devices and the server.
1717
package api
1818

19-
import "fmt"
19+
import (
20+
"crypto/rand"
21+
"encoding/base64"
22+
"fmt"
23+
"math/big"
24+
)
2025

2126
const (
2227
// TestTypeConfirmed is the string that represents a confirmed covid-19 test.
@@ -98,13 +103,35 @@ func (e *ErrorReturn) WithCode(code string) *ErrorReturn {
98103
// It's arbitrary bytes that should be ignored or discarded. It primarily exists
99104
// to prevent a network observer from building a model based on request or
100105
// response sizes.
101-
type Padding struct {
102-
Padding string `json:"padding,omitempty"`
106+
type Padding []byte
107+
108+
// MarshalJSON is a custom JSON marshaler for padding. It generates and returns
109+
// 1-2kb (random) of base64-encoded bytes.
110+
func (p Padding) MarshalJSON() ([]byte, error) {
111+
bi, err := rand.Int(rand.Reader, big.NewInt(1024))
112+
if err != nil {
113+
return nil, fmt.Errorf("padding: failed to generate random number: %w", err)
114+
}
115+
116+
// rand.Int is [0, max), so add 1kb to set the range from 1-2kb.
117+
i := int(bi.Int64() + 1024)
118+
119+
b := make([]byte, i)
120+
n, err := rand.Read(b)
121+
if err != nil {
122+
return nil, fmt.Errorf("padding: failed to read bytes: %w", err)
123+
}
124+
if n < i {
125+
return nil, fmt.Errorf("padding: wrote less bytes than expected")
126+
}
127+
128+
s := fmt.Sprintf("%q", base64.StdEncoding.EncodeToString(b))
129+
return []byte(s), nil
103130
}
104131

105132
// CSRFResponse is the return type when requesting an AJAX CSRF token.
106133
type CSRFResponse struct {
107-
Padding
134+
Padding Padding `json:"padding"`
108135

109136
CSRFToken string `json:"csrftoken"`
110137
Error string `json:"error"`
@@ -115,7 +142,7 @@ type CSRFResponse struct {
115142
// code. This is called by the Web frontend.
116143
// API is served at /api/issue
117144
type IssueCodeRequest struct {
118-
Padding
145+
Padding Padding `json:"padding"`
119146

120147
SymptomDate string `json:"symptomDate"` // ISO 8601 formatted date, YYYY-MM-DD
121148
TestDate string `json:"testDate"`
@@ -128,7 +155,7 @@ type IssueCodeRequest struct {
128155

129156
// IssueCodeResponse defines the response type for IssueCodeRequest.
130157
type IssueCodeResponse struct {
131-
Padding
158+
Padding Padding `json:"padding"`
132159

133160
// UUID is a handle which allows the issuer to track status of the issued verification code.
134161
UUID string `json:"uuid"`
@@ -157,15 +184,15 @@ type IssueCodeResponse struct {
157184
// previously issued OTP code. This is called by the Web frontend.
158185
// API is served at /api/checkcodestatus
159186
type CheckCodeStatusRequest struct {
160-
Padding
187+
Padding Padding `json:"padding"`
161188

162189
// UUID is a handle which allows the issuer to track status of the issued verification code.
163190
UUID string `json:"uuid"`
164191
}
165192

166193
// CheckCodeStatusResponse defines the response type for CheckCodeStatusRequest.
167194
type CheckCodeStatusResponse struct {
168-
Padding
195+
Padding Padding `json:"padding"`
169196

170197
// Claimed is true if a user has used the OTP code to get a token via the VerifyCode api.
171198
Claimed bool `json:"claimed"`
@@ -186,15 +213,15 @@ type CheckCodeStatusResponse struct {
186213
// This is called by the Web frontend.
187214
// API is served at /api/expirecode
188215
type ExpireCodeRequest struct {
189-
Padding
216+
Padding Padding `json:"padding"`
190217

191218
// UUID is a handle which allows the issuer to track status of the issued verification code.
192219
UUID string `json:"uuid"`
193220
}
194221

195222
// ExpireCodeResponse defines the response type for ExpireCodeRequest.
196223
type ExpireCodeResponse struct {
197-
Padding
224+
Padding Padding `json:"padding"`
198225

199226
// ExpiresAtTimestamp represents Unix, seconds since the epoch. Still UTC.
200227
// After this time the code will no longer be accepted and is eligible for deletion.
@@ -226,7 +253,7 @@ type ExpireCodeResponse struct {
226253
//
227254
// Requires API key in a HTTP header, X-API-Key: APIKEY
228255
type VerifyCodeRequest struct {
229-
Padding
256+
Padding Padding `json:"padding"`
230257

231258
VerificationCode string `json:"code"`
232259
AcceptTestTypes []string `json:"accept"`
@@ -236,7 +263,7 @@ type VerifyCodeRequest struct {
236263
// (type and [optional] date) as well as the verification token. The verification token
237264
// may be sent back on a valid VerificationCertificateRequest later.
238265
type VerifyCodeResponse struct {
239-
Padding
266+
Padding Padding `json:"padding"`
240267

241268
TestType string `json:"testtype,omitempty"`
242269
SymptomDate string `json:"symptomDate,omitempty"` // ISO 8601 formatted date, YYYY-MM-DD
@@ -252,7 +279,7 @@ type VerifyCodeResponse struct {
252279
//
253280
// Requires API key in a HTTP header, X-API-Key: APIKEY
254281
type VerificationCertificateRequest struct {
255-
Padding
282+
Padding Padding `json:"padding"`
256283

257284
VerificationToken string `json:"token"`
258285
ExposureKeyHMAC string `json:"ekeyhmac"`
@@ -262,7 +289,7 @@ type VerificationCertificateRequest struct {
262289
// a signed certificate that can be presented to the configured exposure
263290
// notifications server to publish keys along w/ the certified diagnosis.
264291
type VerificationCertificateResponse struct {
265-
Padding
292+
Padding Padding `json:"padding"`
266293

267294
Certificate string `json:"certificate,omitempty"`
268295
Error string `json:"error,omitempty"`

0 commit comments

Comments
 (0)