Skip to content

Commit 6d0ef86

Browse files
committed
Various updates including better key rotation, and key versioning
1 parent d7f223d commit 6d0ef86

20 files changed

+226
-294
lines changed

Makefile

Lines changed: 52 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,57 @@
1-
# The import path is where your repository can be found.
2-
# To import subpackages, always prepend the full import path.
3-
# If you change this, run `make clean`. Read more: https://git.io/vM7zV
4-
IMPORT_PATH := github.com/privacypass/challenge-bypass-server
5-
6-
# V := 1 # When V is set, print commands and build progress.
7-
8-
# Space separated patterns of packages to skip in list, test, format.
9-
IGNORED_PACKAGES := /vendor/
10-
11-
.PHONY: all
12-
all: build
13-
14-
.PHONY: build btd
15-
build: btd
16-
17-
btd: .GOPATH/.ok
18-
$Q go install $(if $V,-v) $(VERSION_FLAGS) $(IMPORT_PATH)/server
19-
$Q mv bin/server bin/btd
20-
21-
### Code not in the repository root? Another binary? Add to the path like this.
22-
# .PHONY: otherbin
23-
# otherbin: .GOPATH/.ok
24-
# $Q go install $(if $V,-v) $(VERSION_FLAGS) $(IMPORT_PATH)/cmd/otherbin
25-
26-
##### ^^^^^^ EDIT ABOVE ^^^^^^ #####
27-
28-
##### =====> Utility targets <===== #####
29-
30-
.PHONY: clean test list cover format
31-
32-
clean:
33-
$Q rm -rf bin .GOPATH
34-
35-
test: .GOPATH/.ok
36-
$Q go test $(if $V,-v) -i -race $(allpackages) # install -race libs to speed up next run
37-
ifndef CI
38-
$Q go vet $(allpackages)
39-
$Q GODEBUG=cgocheck=2 go test -race $(allpackages)
40-
else
41-
$Q ( go vet $(allpackages); echo $$? ) | \
42-
tee .GOPATH/test/vet.txt | sed '$$ d'; exit $$(tail -1 .GOPATH/test/vet.txt)
43-
$Q ( GODEBUG=cgocheck=2 go test -v -race $(allpackages); echo $$? ) | \
44-
tee .GOPATH/test/output.txt | sed '$$ d'; exit $$(tail -1 .GOPATH/test/output.txt)
45-
endif
46-
47-
list: .GOPATH/.ok
48-
@echo $(allpackages)
49-
50-
cover: bin/gocovmerge .GOPATH/.ok
51-
@echo "NOTE: make cover does not exit 1 on failure, don't use it to check for tests success!"
52-
$Q rm -f .GOPATH/cover/*.out .GOPATH/cover/all.merged
53-
$(if $V,@echo "-- go test -coverpkg=./... -coverprofile=.GOPATH/cover/... ./...")
54-
@for MOD in $(allpackages); do \
55-
go test -coverpkg=`echo $(allpackages)|tr " " ","` \
56-
-coverprofile=.GOPATH/cover/unit-`echo $$MOD|tr "/" "_"`.out \
57-
$$MOD 2>&1 | grep -v "no packages being tested depend on"; \
1+
.PHONY: help print build test cover clean distclean package
2+
3+
BOLD = \033[1m
4+
UNDERLINE = \033[4m
5+
BLUE = \033[36m
6+
RESET = \033[0m
7+
8+
VERSION := $(shell git describe --tags --always --dirty="-dev")
9+
DATE := $(shell date -u '+%Y-%m-%d-%H%M UTC')
10+
ARCHS ?= amd64 arm64
11+
12+
Q ?= @
13+
14+
## Show usage information for this Makefile
15+
help:
16+
@printf "$(BOLD)chl-byp-srv$(RESET)\n\n"
17+
@printf "$(UNDERLINE)Available Tasks$(RESET)\n\n"
18+
@awk -F \
19+
':|##' '/^##/ {c=$$2; getline; printf "$(BLUE)%10s$(RESET) %s\n", $$1, c}' \
20+
$(MAKEFILE_LIST)
21+
@printf "\n"
22+
23+
## print command
24+
print-command:
25+
$Q@printf "GOARCH=$(ARCH) CGO_ENABLED=1 go build -ldflags='-X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"' -o bin/chl-byp-srv ./server"
26+
27+
## Build executable
28+
build:
29+
$Q# ARCH is set from `package`.
30+
$Q# Alternatively, run `make ARCH=<amd64|arm64> build` to override here.
31+
$QGOARCH=$(ARCH) CGO_ENABLED=1 go build \
32+
-ldflags='-X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"' \
33+
-o bin/chl-byp-srv \
34+
./server
35+
36+
## Run tests
37+
test: build
38+
PATH="${PATH}:${PWD}/bin" && GOCACHE=off && go test -v -race ./...
39+
40+
## Generate cover report
41+
cover:
42+
$Qmkdir -p .cover
43+
$Qrm -f .cover/*.out .cover/all.merged .cover/all.html
44+
$Qfor pkg in $$(go list ./...); do \
45+
go test -coverprofile=.cover/`echo $$pkg|tr "/" "_"`.out $$pkg; \
5846
done
59-
$Q ./bin/gocovmerge .GOPATH/cover/*.out > .GOPATH/cover/all.merged
47+
$Qecho 'mode: set' > .cover/all.merged
48+
$Qgrep -h -v "mode: set" .cover/*.out >> .cover/all.merged
6049
ifndef CI
61-
$Q go tool cover -html .GOPATH/cover/all.merged
50+
$Qgo tool cover -html .cover/all.merged
6251
else
63-
$Q go tool cover -html .GOPATH/cover/all.merged -o .GOPATH/cover/all.html
52+
$Qgo tool cover -html .cover/all.merged -o .cover/all.html
6453
endif
65-
@echo ""
66-
@echo "=====> Total test coverage: <====="
67-
@echo ""
68-
$Q go tool cover -func .GOPATH/cover/all.merged
69-
70-
format: bin/goimports .GOPATH/.ok
71-
$Q find .GOPATH/src/$(IMPORT_PATH)/ -iname \*.go | grep -v \
72-
-e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)) | xargs ./bin/goimports -w
73-
74-
##### =====> Internals <===== #####
75-
76-
.PHONY: setup
77-
setup: clean .GOPATH/.ok
78-
@if ! grep "/.GOPATH" .gitignore > /dev/null 2>&1; then \
79-
echo "/.GOPATH" >> .gitignore; \
80-
echo "/bin" >> .gitignore; \
81-
fi
82-
go get -u github.com/FiloSottile/gvt
83-
- ./bin/gvt fetch golang.org/x/tools/cmd/goimports
84-
- ./bin/gvt fetch github.com/wadey/gocovmerge
85-
86-
VERSION := $(shell git describe --tags --always --dirty="-dev")
87-
DATE := $(shell date -u '+%Y-%m-%d-%H%M UTC')
88-
VERSION_FLAGS := -ldflags='-X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"'
8954

90-
# cd into the GOPATH to workaround ./... not following symlinks
91-
_allpackages = $(shell ( cd $(CURDIR)/.GOPATH/src/$(IMPORT_PATH) && \
92-
GOPATH=$(CURDIR)/.GOPATH go list ./... 2>&1 1>&3 | \
93-
grep -v -e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)) 1>&2 ) 3>&1 | \
94-
grep -v -e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)))
95-
96-
# memoize allpackages, so that it's executed only once and only if used
97-
allpackages = $(if $(__allpackages),,$(eval __allpackages := $$(_allpackages)))$(__allpackages)
98-
99-
export GOPATH := $(CURDIR)/.GOPATH
100-
unexport GOBIN
101-
102-
Q := $(if $V,,@)
103-
104-
.GOPATH/.ok:
105-
$Q mkdir -p "$(dir .GOPATH/src/$(IMPORT_PATH))"
106-
$Q ln -s ../../../.. ".GOPATH/src/$(IMPORT_PATH)"
107-
$Q mkdir -p .GOPATH/test .GOPATH/cover
108-
$Q mkdir -p bin
109-
$Q ln -s ../bin .GOPATH/bin
110-
$Q touch $@
111-
112-
.PHONY: bin/gocovmerge bin/goimports
113-
bin/gocovmerge: .GOPATH/.ok
114-
@test -d ./vendor/github.com/wadey/gocovmerge || \
115-
{ echo "Vendored gocovmerge not found, try running 'make setup'..."; exit 1; }
116-
$Q go install $(IMPORT_PATH)/vendor/github.com/wadey/gocovmerge
117-
bin/goimports: .GOPATH/.ok
118-
@test -d ./vendor/golang.org/x/tools/cmd/goimports || \
119-
{ echo "Vendored goimports not found, try running 'make setup'..."; exit 1; }
120-
$Q go install $(IMPORT_PATH)/vendor/golang.org/x/tools/cmd/goimports
121-
122-
# Based on https://github.com/cloudflare/hellogopher - v1.1 - MIT License
123-
#
124-
# Copyright (c) 2017 Cloudflare
125-
#
126-
# Permission is hereby granted, free of charge, to any person obtaining a copy
127-
# of this software and associated documentation files (the "Software"), to deal
128-
# in the Software without restriction, including without limitation the rights
129-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
130-
# copies of the Software, and to permit persons to whom the Software is
131-
# furnished to do so, subject to the following conditions:
132-
#
133-
# The above copyright notice and this permission notice shall be included in all
134-
# copies or substantial portions of the Software.
135-
#
136-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
137-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
139-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
140-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
141-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
142-
# SOFTWARE.
55+
## Clean build files
56+
clean:
57+
$Qrm -rf bin

crypto/batch.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import (
2020
b64 "encoding/base64"
2121
"encoding/json"
2222
"errors"
23-
"golang.org/x/crypto/sha3"
2423
"math/big"
2524
"strings"
25+
26+
"golang.org/x/crypto/sha3"
2627
)
2728

2829
var (
@@ -63,7 +64,11 @@ func NewBatchProof(hash crypto.Hash, g, h *Point, m []*Point, z []*Point, x *big
6364
}
6465

6566
func ComputeComposites(hash crypto.Hash, curve elliptic.Curve, G, Y *Point, P, Q []*Point) (*Point, *Point, [][]byte, error) {
66-
// seed = H(G, Y, [P], [Qs])
67+
if len(P) != len(Q) {
68+
return nil, nil, nil, ErrUnequalPointCounts
69+
}
70+
71+
// seed = H(G, Y, [P], [Q])
6772
H := hash.New()
6873
H.Write(G.Marshal())
6974
H.Write(Y.Marshal())

crypto/batch_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,6 @@ func TestMarshalBatchProof(t *testing.T) {
133133
}
134134
dleq.G = bp.P.G
135135
dleq.H = bp.P.H
136-
Mx, My, Zx, Zy := new(big.Int), new(big.Int), new(big.Int), new(big.Int)
137-
for i := 0; i < len(bp.M); i++ {
138-
cMx, cMy := curve.ScalarMult(bp.M[i].X, bp.M[i].Y, bp.C[i])
139-
cZx, cZy := curve.ScalarMult(bp.Z[i].X, bp.Z[i].Y, bp.C[i])
140-
Mx, My = curve.Add(cMx, cMy, Mx, My)
141-
Zx, Zy = curve.Add(cZx, cZy, Zx, Zy)
142-
}
143136
dleq.M, dleq.Z = recomputeComposites(curve, bp.M, bp.Z, bp.C)
144137
bpUnmarshal := &BatchProof{M: bp.M, Z: bp.Z, C: bp.C, P: dleq}
145138
if !bpUnmarshal.Verify() {

crypto/curve.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -152,22 +152,6 @@ func BatchMarshalPoints(points []*Point) ([][]byte, error) {
152152
return data, nil
153153
}
154154

155-
// We combine the marshaled points with the DLEQ proof
156-
// This function splits the points and the DLEQ proof for further unmarshaling
157-
func GetMarshaledPointsAndDleq(data [][]byte) ([][]byte, []byte) {
158-
marshaledPoints := make([][]byte, len(data)-1)
159-
var batchProof []byte
160-
for i, v := range data {
161-
if i < len(data)-1 {
162-
marshaledPoints[i] = v
163-
} else {
164-
batchProof = data[i]
165-
}
166-
}
167-
168-
return marshaledPoints, batchProof
169-
}
170-
171155
func NewPoint(curve elliptic.Curve, x, y *big.Int) (*Point, error) {
172156
if curve == nil {
173157
return nil, ErrUnspecifiedCurve
@@ -232,7 +216,9 @@ func HashToCurve(curve elliptic.Curve, hash crypto.Hash, data []byte) (*Point, e
232216
var ctr = make([]byte, 4)
233217
var h = hash.New()
234218
h.Write([]byte(separator))
235-
for i := 0; i < 10; i++ {
219+
// Obviously this is bad practise, but increasing this number rules out probabilistic failures.
220+
// We should implement the SWU method for encoding bytes to curves in the future.
221+
for i := 0; i < 20; i++ {
236222
binary.LittleEndian.PutUint32(ctr, uint32(i))
237223
h.Write(data)
238224
h.Write(ctr)

crypto/dleq.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ type Proof struct {
4040
}
4141

4242
type Base64Proof struct {
43-
R string
44-
C string
43+
R string
44+
C string
4545
}
4646

4747
func (p *Proof) IsComplete() bool {

crypto/dleq_test.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import (
1212
)
1313

1414
func setup(curve elliptic.Curve) ([]byte, *Point, *Point, error) {
15+
// All public keys are going to be generators, so GenerateKey is a handy
16+
// test function. However, TESTING ONLY. Maintaining the discrete log
17+
// relationship breaks the token scheme. Ideally the generator points
18+
// would come from a group PRF or something like Elligator.
1519
x, _, _, err := elliptic.GenerateKey(curve, rand.Reader)
1620
if err != nil {
1721
return nil, nil, nil, err
@@ -31,10 +35,6 @@ func setup(curve elliptic.Curve) ([]byte, *Point, *Point, error) {
3135
}
3236

3337
func TestValidProof(t *testing.T) {
34-
// All public keys are going to be generators, so GenerateKey is a handy
35-
// test function. However, TESTING ONLY. Maintaining the discrete log
36-
// relationship breaks the token scheme. Ideally the generator points
37-
// would come from a group PRF or something like Elligator.
3838
curve := elliptic.P256()
3939
x, G, M, err := setup(curve)
4040
if err != nil {
@@ -84,10 +84,6 @@ func TestValidProof(t *testing.T) {
8484
}
8585

8686
func TestInvalidProof(t *testing.T) {
87-
// All public keys are going to be generators, so GenerateKey is a handy
88-
// test function. However, TESTING ONLY. Maintaining the discrete log
89-
// relationship breaks the token scheme. Ideally the generator points
90-
// would come from a group PRF or something like Elligator.
9187
curve := elliptic.P256()
9288
x, G, M, err := setup(curve)
9389
if err != nil {

0 commit comments

Comments
 (0)