From 23e63807085b13a9b221c3374d05099559583011 Mon Sep 17 00:00:00 2001 From: jwijenbergh Date: Wed, 9 Feb 2022 18:10:09 +0100 Subject: Add signature verification to list retrieval - Move test data to src - Verify signatures by calling the Verify method - Add a customizable parameter to force prehashed signatures Signed-off-by: jwijenbergh --- go.mod | 2 +- src/server.go | 56 ++++++-- src/test_data/empty | 0 src/test_data/generate.sh | 58 ++++++++ src/test_data/generate_forged.py | 37 +++++ src/test_data/organization_list.json | 1 + src/test_data/organization_list.json.minisig | 4 + .../organization_list.json.tc_servlist.minisig | 4 + src/test_data/other_list.json | 1 + src/test_data/other_list.json.minisig | 4 + src/test_data/public.key | 2 + src/test_data/random.txt | 1 + src/test_data/secret.key | 2 + src/test_data/server_list.json | 3 + src/test_data/server_list.json.blake2b | Bin 0 -> 64 bytes .../server_list.json.forged_keyid.minisig | 4 + src/test_data/server_list.json.forged_pure.minisig | 4 + src/test_data/server_list.json.large_time.minisig | 4 + src/test_data/server_list.json.minisig | 4 + src/test_data/server_list.json.pure.minisig | 4 + .../server_list.json.tc_earliertime.minisig | 4 + .../server_list.json.tc_emptyfile.minisig | 4 + .../server_list.json.tc_emptytime.minisig | 4 + .../server_list.json.tc_latertime.minisig | 4 + src/test_data/server_list.json.tc_nofile.minisig | 4 + src/test_data/server_list.json.tc_nohashed.minisig | 4 + src/test_data/server_list.json.tc_notime.minisig | 4 + src/test_data/server_list.json.tc_orglist.minisig | 4 + .../server_list.json.tc_otherfile.minisig | 4 + src/test_data/server_list.json.tc_random.minisig | 4 + src/test_data/server_list.json.wrong_key.minisig | 4 + src/test_data/wrong_public.key | 2 + src/test_data/wrong_secret.key | 2 + src/verify.go | 14 +- src/verify_test.go | 158 +++++++++++++++++++++ test_data/empty | 0 test_data/generate.sh | 58 -------- test_data/generate_forged.py | 37 ----- test_data/organization_list.json | 1 - test_data/organization_list.json.minisig | 4 - .../organization_list.json.tc_servlist.minisig | 4 - test_data/other_list.json | 1 - test_data/other_list.json.minisig | 4 - test_data/public.key | 2 - test_data/random.txt | 1 - test_data/secret.key | 2 - test_data/server_list.json | 3 - test_data/server_list.json.blake2b | Bin 64 -> 0 bytes test_data/server_list.json.forged_keyid.minisig | 4 - test_data/server_list.json.forged_pure.minisig | 4 - test_data/server_list.json.large_time.minisig | 4 - test_data/server_list.json.minisig | 4 - test_data/server_list.json.pure.minisig | 4 - test_data/server_list.json.tc_earliertime.minisig | 4 - test_data/server_list.json.tc_emptyfile.minisig | 4 - test_data/server_list.json.tc_emptytime.minisig | 4 - test_data/server_list.json.tc_latertime.minisig | 4 - test_data/server_list.json.tc_nofile.minisig | 4 - test_data/server_list.json.tc_nohashed.minisig | 4 - test_data/server_list.json.tc_notime.minisig | 4 - test_data/server_list.json.tc_orglist.minisig | 4 - test_data/server_list.json.tc_otherfile.minisig | 4 - test_data/server_list.json.tc_random.minisig | 4 - test_data/server_list.json.wrong_key.minisig | 4 - test_data/wrong_public.key | 2 - test_data/wrong_secret.key | 2 - verify_test.go | 157 -------------------- 67 files changed, 399 insertions(+), 358 deletions(-) create mode 100644 src/test_data/empty create mode 100644 src/test_data/generate.sh create mode 100644 src/test_data/generate_forged.py create mode 100644 src/test_data/organization_list.json create mode 100644 src/test_data/organization_list.json.minisig create mode 100644 src/test_data/organization_list.json.tc_servlist.minisig create mode 100644 src/test_data/other_list.json create mode 100644 src/test_data/other_list.json.minisig create mode 100644 src/test_data/public.key create mode 100644 src/test_data/random.txt create mode 100644 src/test_data/secret.key create mode 100644 src/test_data/server_list.json create mode 100644 src/test_data/server_list.json.blake2b create mode 100644 src/test_data/server_list.json.forged_keyid.minisig create mode 100644 src/test_data/server_list.json.forged_pure.minisig create mode 100644 src/test_data/server_list.json.large_time.minisig create mode 100644 src/test_data/server_list.json.minisig create mode 100644 src/test_data/server_list.json.pure.minisig create mode 100644 src/test_data/server_list.json.tc_earliertime.minisig create mode 100644 src/test_data/server_list.json.tc_emptyfile.minisig create mode 100644 src/test_data/server_list.json.tc_emptytime.minisig create mode 100644 src/test_data/server_list.json.tc_latertime.minisig create mode 100644 src/test_data/server_list.json.tc_nofile.minisig create mode 100644 src/test_data/server_list.json.tc_nohashed.minisig create mode 100644 src/test_data/server_list.json.tc_notime.minisig create mode 100644 src/test_data/server_list.json.tc_orglist.minisig create mode 100644 src/test_data/server_list.json.tc_otherfile.minisig create mode 100644 src/test_data/server_list.json.tc_random.minisig create mode 100644 src/test_data/server_list.json.wrong_key.minisig create mode 100644 src/test_data/wrong_public.key create mode 100644 src/test_data/wrong_secret.key create mode 100644 src/verify_test.go delete mode 100644 test_data/empty delete mode 100644 test_data/generate.sh delete mode 100644 test_data/generate_forged.py delete mode 100644 test_data/organization_list.json delete mode 100644 test_data/organization_list.json.minisig delete mode 100644 test_data/organization_list.json.tc_servlist.minisig delete mode 100644 test_data/other_list.json delete mode 100644 test_data/other_list.json.minisig delete mode 100644 test_data/public.key delete mode 100644 test_data/random.txt delete mode 100644 test_data/secret.key delete mode 100644 test_data/server_list.json delete mode 100644 test_data/server_list.json.blake2b delete mode 100644 test_data/server_list.json.forged_keyid.minisig delete mode 100644 test_data/server_list.json.forged_pure.minisig delete mode 100644 test_data/server_list.json.large_time.minisig delete mode 100644 test_data/server_list.json.minisig delete mode 100644 test_data/server_list.json.pure.minisig delete mode 100644 test_data/server_list.json.tc_earliertime.minisig delete mode 100644 test_data/server_list.json.tc_emptyfile.minisig delete mode 100644 test_data/server_list.json.tc_emptytime.minisig delete mode 100644 test_data/server_list.json.tc_latertime.minisig delete mode 100644 test_data/server_list.json.tc_nofile.minisig delete mode 100644 test_data/server_list.json.tc_nohashed.minisig delete mode 100644 test_data/server_list.json.tc_notime.minisig delete mode 100644 test_data/server_list.json.tc_orglist.minisig delete mode 100644 test_data/server_list.json.tc_otherfile.minisig delete mode 100644 test_data/server_list.json.tc_random.minisig delete mode 100644 test_data/server_list.json.wrong_key.minisig delete mode 100644 test_data/wrong_public.key delete mode 100644 test_data/wrong_secret.key delete mode 100644 verify_test.go diff --git a/go.mod b/go.mod index 3363345..b21b580 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module eduvpn-common +module github.com/jwijenbergh/eduvpn-common go 1.15 diff --git a/src/server.go b/src/server.go index 7973654..314ceae 100644 --- a/src/server.go +++ b/src/server.go @@ -1,4 +1,4 @@ -package eduvpn_discovery +package eduvpn import ( "encoding/json" @@ -36,41 +36,79 @@ type servers struct { } `json:"server_list"` } -// Helper function that gets a disco json -// TODO: Verify signature -func getDiscoJson(jsonFile string, structure interface{}) bool { - url := "https://disco.eduvpn.org/v2/" + jsonFile +func getFileUrl(url string) ([]byte, bool) { // Do a Get request to the specified url resp, reqErr := http.Get(url) if reqErr != nil { fmt.Println("error making request") - return false + return nil, false } + // Close the response body at the end + defer resp.Body.Close() + // Check if http response code is ok + if resp.StatusCode != http.StatusOK { + return nil, false + } // Read the body body, readErr := ioutil.ReadAll(resp.Body) if readErr != nil { fmt.Println("error reading body of request") + return nil, false + } + return body, true +} + +// Helper function that gets a disco json +// TODO: Verify signature +func getDiscoJson(jsonFile string, structure interface{}) bool { + // Get json data + fileUrl := "https://disco.eduvpn.org/v2/" + jsonFile + fileBody, fileSuccess := getFileUrl(fileUrl) + + if !fileSuccess { + fmt.Println("error getting file") + } + + // Get signature + sigUrl := fileUrl + ".minisig" + sigBody, sigSuccess := getFileUrl(sigUrl) + + if !sigSuccess { + fmt.Println("error getting signature") + return false + } + + // Verify signature + // TODO: Handle this by keeping track of the previous sign time + // Wrappers must do this? + var previousSigTime uint64 = 0 + forcePrehash := false + verifySuccess, verifyErr := Verify(string(sigBody), fileBody, jsonFile, previousSigTime, forcePrehash) + + if !verifySuccess || verifyErr != nil { + fmt.Printf("signature is invalid with error: %s\n", verifyErr) return false } // Parse the json using the predefined struct - error := json.Unmarshal([]byte(body), &structure) + error := json.Unmarshal([]byte(fileBody), &structure) if error != nil { fmt.Println("error parsing server json") return false } + return true } // Get the organization list -func getOrganizationList() bool { +func GetOrganizationList() bool { organizations := organizations{} return getDiscoJson("organization_list.json", &organizations) } // Get the server list -func getServerList() bool { +func GetServerList() bool { servers := servers{} return getDiscoJson("server_list.json", &servers) } diff --git a/src/test_data/empty b/src/test_data/empty new file mode 100644 index 0000000..e69de29 diff --git a/src/test_data/generate.sh b/src/test_data/generate.sh new file mode 100644 index 0000000..b1b4545 --- /dev/null +++ b/src/test_data/generate.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# Generate testcases with fake keys + +# Make sure we do not delete *.minisigs etc. in the wrong directory +if [ ${PWD##*/} != "test_data" ] +then + >&2 echo "Wrong directory, should be run in test_data/" + exit 1 +fi + +rm -f *.minisig *.blake2b + +# Uncomment to regenerate keys +#rm -f *.key +#echo -en "\n\n" | minisign -Gf -p public.key -s secret.key & +#echo -en "\n\n" | minisign -Gf -p wrong_public.key -s wrong_secret.key & +#wait + +# Try to create pure signature with default Minisign (works with version < 0.10) +echo | minisign -Sm server_list.json -x server_list.json.pure.minisig -t $'timestamp:10\tfile:server_list.json' -s secret.key +# Check if it is actually a prehashed signature +if echo | minisign -VHm server_list.json -x server_list.json.pure.minisig -p public.key +then + echo "minisign version is >0.9, trying minisign-0.9" + # If it is, try to sign with some minisign-0.9 program + if ! echo | minisign-0.9 -Sm server_list.json -x server_list.json.pure.minisig -t $'timestamp:10\tfile:server_list.json' -s secret.key + then + >&2 echo -e "\n\nTo produce a non-prehashed signature we need Minisign 0.9\n\n" + fi +fi + +# Rest works with Minisign 0.9 and 0.10 (and up, probably) + +echo | minisign -SHm server_list.json -t $'timestamp:10\tfile:server_list.json\thashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_nohashed.minisig -t $'timestamp:10\tfile:server_list.json' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_latertime.minisig -t $'timestamp:20\tfile:server_list.json\t hashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_orglist.minisig -t $'timestamp:10\tfile:organization_list.json\thashed' -s secret.key & +wait +echo | minisign -SHm server_list.json -x server_list.json.tc_otherfile.minisig -t $'timestamp:10\tfile:otherfile\thashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_nofile.minisig -t $'timestamp:10\thashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_notime.minisig -t $'file:server_list.json\thashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_emptytime.minisig -t $'timestamp:\tfile:server_list.json\thashed' -s secret.key & +wait +echo | minisign -SHm server_list.json -x server_list.json.tc_emptyfile.minisig -t $'timestamp:10\tfile:\thashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_earliertime.minisig -t $'timestamp:9\tfile:server_list.json\thashed' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.tc_random.minisig -t 'random stuff' -s secret.key & +echo | minisign -SHm server_list.json -x server_list.json.large_time.minisig -t $'timestamp:4300000000\tfile:server_list.json' -s secret.key & +wait + +echo | minisign -SHm organization_list.json -t $'timestamp:10\tfile:organization_list.json\thashed' -s secret.key & +echo | minisign -SHm organization_list.json -x organization_list.json.tc_servlist.minisig -t $'timestamp:10\tfile:server_list.json\thashed' -s secret.key & + +echo | minisign -SHm other_list.json -t $'timestamp:10\tfile:other_list.json\thashed' -s secret.key & + +echo | minisign -SHm server_list.json -x server_list.json.wrong_key.minisig -t $'timestamp:10\tfile:server_list.json\thashed' -s wrong_secret.key & +wait + +./generate_forged.py diff --git a/src/test_data/generate_forged.py b/src/test_data/generate_forged.py new file mode 100644 index 0000000..843b32d --- /dev/null +++ b/src/test_data/generate_forged.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import hashlib +import base64 + +# Hash server_list.json + +with open("server_list.json", "rb") as f: + b = f.read() + +with open("server_list.json.blake2b", "wb") as f: + f.write(hashlib.blake2b(b).digest()) + +# Forge pure signature on hash, see https://github.com/jedisct1/minisign/issues/104 + +with open("server_list.json.minisig", "rb") as f: + siglines = f.readlines() + +siglines[0] = b"untrusted comment: this signature has ED changed to Ed\n" +sig = base64.b64decode(siglines[1]) +siglines[1] = base64.b64encode(b"Ed" + sig[2:]) + b"\n" + +with open("server_list.json.forged_pure.minisig", "wb") as f: + f.writelines(siglines) + # Should now work: minisign -Vm server_list.json.blake2b -x server_list.json.forged_pure.minisig -p public-key + +# Try to forge key ID + +with open("server_list.json.wrong_key.minisig", "rb") as f: + siglines = f.readlines() + +siglines[0] = b"untrusted comment: this signature was created with wrong_secret.key but has key ID changed to that of public.key\n" +sig_wrong = base64.b64decode(siglines[1]) +siglines[1] = base64.b64encode(sig_wrong[:2] + sig[2:2+8] + sig_wrong[2+8:]) + b"\n" + +with open("server_list.json.forged_keyid.minisig", "wb") as f: + f.writelines(siglines) diff --git a/src/test_data/organization_list.json b/src/test_data/organization_list.json new file mode 100644 index 0000000..8c53044 --- /dev/null +++ b/src/test_data/organization_list.json @@ -0,0 +1 @@ +{"organization_list": [{}]} \ No newline at end of file diff --git a/src/test_data/organization_list.json.minisig b/src/test_data/organization_list.json.minisig new file mode 100644 index 0000000..1fa546e --- /dev/null +++ b/src/test_data/organization_list.json.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH31cHjNvTEh+TCqDVCwUgFVZoRdgWYAaQDxH3L3UIsRi9Qb1O4vLI4V1CYPatKzXZnSodSJM/AZgl9v7l/5bfPQ0= +trusted comment: timestamp:10 file:organization_list.json hashed +21zZv1DviMpLCdv1NgzLBl6d+F1ZllSNyjAquYxhTHGcs2F64bDFpqY0I0xjCHIoXly6HKqJKIBXNgud12ijCQ== diff --git a/src/test_data/organization_list.json.tc_servlist.minisig b/src/test_data/organization_list.json.tc_servlist.minisig new file mode 100644 index 0000000..a7fe41f --- /dev/null +++ b/src/test_data/organization_list.json.tc_servlist.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH31cHjNvTEh+TCqDVCwUgFVZoRdgWYAaQDxH3L3UIsRi9Qb1O4vLI4V1CYPatKzXZnSodSJM/AZgl9v7l/5bfPQ0= +trusted comment: timestamp:10 file:server_list.json hashed +R6hjM/oMS5LAvpYM4F6E7iUpnlPxqiY0QfuOnpum31CW0sUy/Ypy2PiomSwvZXKVR7keEZS/+lZjyra9TkrLDQ== diff --git a/src/test_data/other_list.json b/src/test_data/other_list.json new file mode 100644 index 0000000..25ba1a8 --- /dev/null +++ b/src/test_data/other_list.json @@ -0,0 +1 @@ +{"other_list": [{}]} \ No newline at end of file diff --git a/src/test_data/other_list.json.minisig b/src/test_data/other_list.json.minisig new file mode 100644 index 0000000..eaa2248 --- /dev/null +++ b/src/test_data/other_list.json.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH366C1RnYeUAgEeX/S5A1Z9qmkV2+GJaVj06FWGd4aMLc+HS7iFMhG69u3TVD4YmzMH12rk7hQrnyCC6ex8ypIQA= +trusted comment: timestamp:10 file:other_list.json hashed +26+608n+bjQF9lwNdXbIK6t5bP8dzhjNQ9hACeYJLiB2tr437Aec2GkmJh0jSiRv1QV4RYBcKJeHQBUcV2grCQ== diff --git a/src/test_data/public.key b/src/test_data/public.key new file mode 100644 index 0000000..72676d3 --- /dev/null +++ b/src/test_data/public.key @@ -0,0 +1,2 @@ +untrusted comment: minisign public key DF07F868DFAB9B4C +RWRMm6vfaPgH39iT++NBiUKZim2nDWnalgkNROovPbZdSwVFgUdKU4ac diff --git a/src/test_data/random.txt b/src/test_data/random.txt new file mode 100644 index 0000000..b6fc4c6 --- /dev/null +++ b/src/test_data/random.txt @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/src/test_data/secret.key b/src/test_data/secret.key new file mode 100644 index 0000000..6e4af37 --- /dev/null +++ b/src/test_data/secret.key @@ -0,0 +1,2 @@ +untrusted comment: minisign encrypted secret key +RWRTY0IyobkTOt4ugAHNTPB6zOxHgX8spW6HQWddB5IrdCPDAgsAAAACAAAAAAAAAEAAAAAAvK1S1gsOgozZHuIdLWXq1IwxnWVr+dlySiykTbO6F85HvzPtgxZ7oLcGkT/vPdskAh0SV9H2ylHlt9oarXcWNDKs2r6EcZw/qy5FsD+5uhPfxwWV4qDF+1G456tYDYID63d50CgzdO0= diff --git a/src/test_data/server_list.json b/src/test_data/server_list.json new file mode 100644 index 0000000..67c4c8d --- /dev/null +++ b/src/test_data/server_list.json @@ -0,0 +1,3 @@ +{ +"server_list": [{}] +} \ No newline at end of file diff --git a/src/test_data/server_list.json.blake2b b/src/test_data/server_list.json.blake2b new file mode 100644 index 0000000..5d2ca5a Binary files /dev/null and b/src/test_data/server_list.json.blake2b differ diff --git a/src/test_data/server_list.json.forged_keyid.minisig b/src/test_data/server_list.json.forged_keyid.minisig new file mode 100644 index 0000000..efa349d --- /dev/null +++ b/src/test_data/server_list.json.forged_keyid.minisig @@ -0,0 +1,4 @@ +untrusted comment: this signature was created with wrong_secret.key but has key ID changed to that of public.key +RURMm6vfaPgH35aarz3NMq4gbv6JvzOnjG003bDe6USu+HT/JzuxHjQcQGE/KBPdyCF6BDDwwFu+NVmi5jotYCJHWOEqSBU70gE= +trusted comment: timestamp:10 file:server_list.json hashed +3BWYJamM3t6ImuXQufTeO81UMZNyM7TujMu7SCmR+oapsSEBpmkazGOgzlJYR53HP9K9zrEA+4lV8gFFngooBA== diff --git a/src/test_data/server_list.json.forged_pure.minisig b/src/test_data/server_list.json.forged_pure.minisig new file mode 100644 index 0000000..a362504 --- /dev/null +++ b/src/test_data/server_list.json.forged_pure.minisig @@ -0,0 +1,4 @@ +untrusted comment: this signature has ED changed to Ed +RWRMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 file:server_list.json hashed +oK41aX7rmpbO2ohF3v3+JGgSexQaVlfWvYPzaKEkDlJm8mVZtuK/h26SCRuL6PbTR92DLZU59rw8ckICUH/ADw== diff --git a/src/test_data/server_list.json.large_time.minisig b/src/test_data/server_list.json.large_time.minisig new file mode 100644 index 0000000..79a2a52 --- /dev/null +++ b/src/test_data/server_list.json.large_time.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:4300000000 file:server_list.json +L9C58LIq7bTLf4otqW4Eb+ASL0+FM7nRRjstCBuCPtuUerFIsOqNUpDp2AQJJ4pZJKE7SkgIq2tV8/IaVpzxBQ== diff --git a/src/test_data/server_list.json.minisig b/src/test_data/server_list.json.minisig new file mode 100644 index 0000000..143585b --- /dev/null +++ b/src/test_data/server_list.json.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 file:server_list.json hashed +oK41aX7rmpbO2ohF3v3+JGgSexQaVlfWvYPzaKEkDlJm8mVZtuK/h26SCRuL6PbTR92DLZU59rw8ckICUH/ADw== diff --git a/src/test_data/server_list.json.pure.minisig b/src/test_data/server_list.json.pure.minisig new file mode 100644 index 0000000..57dccfc --- /dev/null +++ b/src/test_data/server_list.json.pure.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RWRMm6vfaPgH3zQ/rcq2GMsNz1SYySz+olupm0I+nzNpOkPyUHTBwig3Pep4biOk/bH73bH+0sLNoZPcDk1f2Acn8JINc9MWMw4= +trusted comment: timestamp:10 file:server_list.json +FZ0eA96SlADsMrSOUgStQJpmUnBGpPbRvNI/oaYhKrylu6jUcXOgsRu6571mmDxYdlruSuUSlQbdmG81Qbl4AA== diff --git a/src/test_data/server_list.json.tc_earliertime.minisig b/src/test_data/server_list.json.tc_earliertime.minisig new file mode 100644 index 0000000..03da710 --- /dev/null +++ b/src/test_data/server_list.json.tc_earliertime.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:9 file:server_list.json hashed +vw3wjLDNZWoV98/GnFv38REiaeh+wUPEZgmBUvY35CEq00jDdHiJcYRV/7zBoKv+n9TAYxZ8WKUOGWNOPonTBg== diff --git a/src/test_data/server_list.json.tc_emptyfile.minisig b/src/test_data/server_list.json.tc_emptyfile.minisig new file mode 100644 index 0000000..a7aa3ed --- /dev/null +++ b/src/test_data/server_list.json.tc_emptyfile.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 file: hashed +g4drZ91TcYXNLnIGbeH5ZIFzrs2wWB9JTXjV3Jwg9ehSC2D8lCTqw3u2Rg+PvLPRvYmXTHyuJoKNWelsSh64CA== diff --git a/src/test_data/server_list.json.tc_emptytime.minisig b/src/test_data/server_list.json.tc_emptytime.minisig new file mode 100644 index 0000000..d3ef01e --- /dev/null +++ b/src/test_data/server_list.json.tc_emptytime.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp: file:server_list.json hashed +lw5rnZsPi+TkZ4lOCy7bjsUgTXxG+jaGOGdHuNL95FSD2mmP9ZzEJPrJ2jnH7iYfkF3zDm0QvEUDxhEirlHBDA== diff --git a/src/test_data/server_list.json.tc_latertime.minisig b/src/test_data/server_list.json.tc_latertime.minisig new file mode 100644 index 0000000..8237123 --- /dev/null +++ b/src/test_data/server_list.json.tc_latertime.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:20 file:server_list.json hashed +rHcsHF2mmcZvDLreeuljVauuFULWiY8luCsxyBxxobcJkCedEDW3/RX5KeT+2NjHSFuQxkmrYOBWTY9+ECuUDQ== diff --git a/src/test_data/server_list.json.tc_nofile.minisig b/src/test_data/server_list.json.tc_nofile.minisig new file mode 100644 index 0000000..3c1dcbe --- /dev/null +++ b/src/test_data/server_list.json.tc_nofile.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 hashed +NonaTZH7RDbsHXv85M7sL43YE7CTzs5qDRRoFYjajeqzHa+hdIuMGyemK85rAJ3prLGnMdWHkZhD4hsr3cZoDA== diff --git a/src/test_data/server_list.json.tc_nohashed.minisig b/src/test_data/server_list.json.tc_nohashed.minisig new file mode 100644 index 0000000..1d140c1 --- /dev/null +++ b/src/test_data/server_list.json.tc_nohashed.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 file:server_list.json +HaPGKT+Jqxjyw2Nt1GEKaPIZsAmVl/RI6p1mQ+S1LqzYicVgT5GxPs9NR6khdGGIFvo/xhVkXFceAWTRUCVQAg== diff --git a/src/test_data/server_list.json.tc_notime.minisig b/src/test_data/server_list.json.tc_notime.minisig new file mode 100644 index 0000000..39625c3 --- /dev/null +++ b/src/test_data/server_list.json.tc_notime.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: file:server_list.json hashed +dMhb+0Y0KAO2tzI4g0ukL/VdMiLVopmXa9BS1RQBY8bYwzmebdIM4DAIZrhtO1avkpdy0prZehuhA1No6cOSAw== diff --git a/src/test_data/server_list.json.tc_orglist.minisig b/src/test_data/server_list.json.tc_orglist.minisig new file mode 100644 index 0000000..7c2a3a8 --- /dev/null +++ b/src/test_data/server_list.json.tc_orglist.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 file:organization_list.json hashed +NreDM4iGEjMWs5sfaJCGZBZ7D9QLqxBKJ/fVW2lvIDr249DSUNR4ZRca8UL73e3c9eTXgHnY/ojsjDtzxDScDw== diff --git a/src/test_data/server_list.json.tc_otherfile.minisig b/src/test_data/server_list.json.tc_otherfile.minisig new file mode 100644 index 0000000..58a29b2 --- /dev/null +++ b/src/test_data/server_list.json.tc_otherfile.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: timestamp:10 file:otherfile hashed +PfDEIMlt2aNFyOnqHb45S7xm4fIg0vfUUbqXENPxry9GEZFX14c5BGtgcL/krDg8WFJHcIA5bzYcX58kgBiZCA== diff --git a/src/test_data/server_list.json.tc_random.minisig b/src/test_data/server_list.json.tc_random.minisig new file mode 100644 index 0000000..7240980 --- /dev/null +++ b/src/test_data/server_list.json.tc_random.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= +trusted comment: random stuff +szGsyESH0EizTXH6n0yuQg6sHTKXr+TJW/Er9ZNJYgQV+1hVM+fc5q1EmVsJlA3kW4Rt/d1p9F0ShLIIgW2vAA== diff --git a/src/test_data/server_list.json.wrong_key.minisig b/src/test_data/server_list.json.wrong_key.minisig new file mode 100644 index 0000000..5a83c0e --- /dev/null +++ b/src/test_data/server_list.json.wrong_key.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RUTQvDHvQuYCCJaarz3NMq4gbv6JvzOnjG003bDe6USu+HT/JzuxHjQcQGE/KBPdyCF6BDDwwFu+NVmi5jotYCJHWOEqSBU70gE= +trusted comment: timestamp:10 file:server_list.json hashed +3BWYJamM3t6ImuXQufTeO81UMZNyM7TujMu7SCmR+oapsSEBpmkazGOgzlJYR53HP9K9zrEA+4lV8gFFngooBA== diff --git a/src/test_data/wrong_public.key b/src/test_data/wrong_public.key new file mode 100644 index 0000000..aa794d4 --- /dev/null +++ b/src/test_data/wrong_public.key @@ -0,0 +1,2 @@ +untrusted comment: minisign public key 802E642EF31BCD0 +RWTQvDHvQuYCCPDLi3UCXzj3BbzFM5QxUFfrp174iaqYo8lT0VaAkhOt diff --git a/src/test_data/wrong_secret.key b/src/test_data/wrong_secret.key new file mode 100644 index 0000000..68e9092 --- /dev/null +++ b/src/test_data/wrong_secret.key @@ -0,0 +1,2 @@ +untrusted comment: minisign encrypted secret key +RWRTY0Iyrc2CTG2W1ZqEq9tb94oQWTnYUy4k8boMf13478FwlDYAAAACAAAAAAAAAEAAAAAA2gFhwOtjETu5WN1LpgtJHV1dk/7466LBJ8dgO/pZoQ3LLAYxlswJHVR/N/Q1HmmKvlxWo2jNTJcARXuHHlMTEgg1MERTldE88CqETrVbvq1JaqJlAY/HMkiqNEUR3L6+5VHbYPKXlVQ= diff --git a/src/verify.go b/src/verify.go index 336ba73..b7077b8 100644 --- a/src/verify.go +++ b/src/verify.go @@ -1,4 +1,4 @@ -package eduvpn_discovery +package eduvpn import ( "fmt" @@ -19,11 +19,13 @@ func getKeys() []string { // expectedFileName must be set to the file type to be verified, either "server_list.json" or "organization_list.json". // minSign must be set to the minimum UNIX timestamp (without milliseconds) for the file version. // This value should not be smaller than the time on the previous document verified. +// forcePrehash indicates whether or not we want to force the use of prehashed signatures +// In the future we want to remove this parameter and only allow prehashed signatures // // The return value will either be (true, nil) for a valid signature or (false, VerifyError) otherwise. // // Verify is a wrapper around verifyWithKeys where allowedPublicKeys is set to the list from https://git.sr.ht/~eduvpn/disco.eduvpn.org#public-keys. -func Verify(signatureFileContent string, signedJson []byte, expectedFileName string, minSignTime uint64) (bool, error) { +func Verify(signatureFileContent string, signedJson []byte, expectedFileName string, minSignTime uint64, forcePrehash bool) (bool, error) { keyStrs := getKeys() if extraKey != "" { keyStrs = append(keyStrs, extraKey) @@ -32,7 +34,7 @@ func Verify(signatureFileContent string, signedJson []byte, expectedFileName str panic(err) } } - valid, err := verifyWithKeys(signatureFileContent, signedJson, expectedFileName, minSignTime, keyStrs) + valid, err := verifyWithKeys(signatureFileContent, signedJson, expectedFileName, minSignTime, keyStrs, forcePrehash) if err != nil { if err.(detailedVerifyError).Code == errInvalidPublicKey { panic(err) // This should not happen unless keyStrs has an invalid key @@ -78,13 +80,13 @@ func (err VerifyError) Unwrap() error { // verifyWithKeys verifies the Minisign signature in signatureFileContent (minisig file format) over the server_list/organization_list JSON in signedJson. // // Verification is performed using a matching key in allowedPublicKeys. -// The signature is checked to be a Blake2b-prehashed Ed25519 Minisign signature with a valid trusted comment. +// The signature is checked to be a Ed25519 Minisign (optionally Ed25519 Blake2b-512 prehashed, see forcePrehash) signature with a valid trusted comment. // The file type that is verified is indicated by expectedFileName, which must be one of "server_list.json"/"organization_list.json". // The trusted comment is checked to be of the form "timestamp:\tfile:", optionally suffixed by something, e.g. "\thashed". // The signature is checked to have a timestamp with a value of at least minSignTime, which is a UNIX timestamp without milliseconds. // // The return value will either be (true, nil) on success or (false, detailedVerifyError) on failure. -func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFileName string, minSignTime uint64, allowedPublicKeys []string) (bool, error) { +func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFileName string, minSignTime uint64, allowedPublicKeys []string, forcePrehash bool) (bool, error) { switch expectedFileName { case "server_list.json", "organization_list.json": break @@ -98,7 +100,7 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile } // Check if signature is prehashed, see https://jedisct1.github.io/minisign/#signature-format - if sig.SignatureAlgorithm != [2]byte{'E', 'D'} { + if forcePrehash && sig.SignatureAlgorithm != [2]byte{'E', 'D'} { return false, detailedVerifyError{errInvalidSignatureAlgorithm, "BLAKE2b-prehashed EdDSA signature required", nil} } diff --git a/src/verify_test.go b/src/verify_test.go new file mode 100644 index 0000000..b9cc033 --- /dev/null +++ b/src/verify_test.go @@ -0,0 +1,158 @@ +package eduvpn + +import ( + "bufio" + "errors" + "fmt" + "io/ioutil" + "os" + "strconv" + "testing" +) + +func Test_verifyWithKeys(t *testing.T) { + var err error + + var pk []string + { + file, err := os.Open("test_data/public.key") + if err != nil { + panic(err) + } + defer file.Close() + + // Get last line (key string) from file + scanner := bufio.NewScanner(file) + for i := 0; i < 2; i++ { + if !scanner.Scan() { + panic(scanner.Err()) + } + } + pk = []string{scanner.Text()} + } + + tests := []struct { + result detailedVerifyErrorCode + testName string + signatureFile string + jsonFile string + expectedFileName string + minSignTime uint64 + allowedPks []string + }{ + {errInvalidSignatureAlgorithm, "pure", "server_list.json.pure.minisig", "server_list.json", "server_list.json", 10, pk}, + + {ok, "valid server_list", "server_list.json.minisig", "server_list.json", "server_list.json", 10, pk}, + {ok, "TC no hashed", "server_list.json.tc_nohashed.minisig", "server_list.json", "server_list.json", 10, pk}, + {ok, "TC later time", "server_list.json.tc_latertime.minisig", "server_list.json", "server_list.json", 10, pk}, + {errWrongFileName, "server_list TC file:organization_list", "server_list.json.tc_orglist.minisig", "server_list.json", "server_list.json", 10, pk}, + {errWrongFileName, "organization_list as server_list", "organization_list.json.minisig", "organization_list.json", "server_list.json", 10, pk}, + {errWrongFileName, "TC file:otherfile", "server_list.json.tc_otherfile.minisig", "server_list.json", "server_list.json", 10, pk}, + {errInvalidTrustedComment, "TC no file", "server_list.json.tc_nofile.minisig", "server_list.json", "server_list.json", 10, pk}, + {errInvalidTrustedComment, "TC no time", "server_list.json.tc_notime.minisig", "server_list.json", "server_list.json", 10, pk}, + {errAny, "TC empty time", "server_list.json.tc_emptytime.minisig", "server_list.json", "server_list.json", 10, pk}, + {errAny, "TC empty file", "server_list.json.tc_emptyfile.minisig", "server_list.json", "server_list.json", 10, pk}, + {errInvalidTrustedComment, "TC random", "server_list.json.tc_random.minisig", "server_list.json", "server_list.json", 10, pk}, + {ok, "large time", "server_list.json.large_time.minisig", "server_list.json", "server_list.json", 43e8, pk}, + {ok, "lower min time", "server_list.json.minisig", "server_list.json", "server_list.json", 5, pk}, + {errTooOld, "higher min time", "server_list.json.minisig", "server_list.json", "server_list.json", 11, pk}, + + {ok, "valid organization_list", "organization_list.json.minisig", "organization_list.json", "organization_list.json", 10, pk}, + {errWrongFileName, "organization_list TC file:server_list", "organization_list.json.tc_servlist.minisig", "organization_list.json", "organization_list.json", 10, pk}, + {errWrongFileName, "server_list as organization_list", "server_list.json.minisig", "server_list.json", "organization_list.json", 10, pk}, + + {errUnknownExpectedFileName, "valid other_list", "other_list.json.minisig", "other_list.json", "other_list.json", 10, pk}, + {errWrongFileName, "other_list as server_list", "other_list.json.minisig", "other_list.json", "server_list.json", 10, pk}, + + {errInvalidSignatureFormat, "invalid signature file", "random.txt", "server_list.json", "server_list.json", 10, pk}, + {errInvalidSignatureFormat, "empty signature file", "empty", "server_list.json", "server_list.json", 10, pk}, + + {errWrongKey, "wrong key", "server_list.json.wrong_key.minisig", "server_list.json", "server_list.json", 10, pk}, + + {errInvalidSignatureAlgorithm, "forged pure signature", "server_list.json.forged_pure.minisig", "server_list.json.blake2b", "server_list.json", 10, pk}, + {errInvalidSignature, "forged key ID", "server_list.json.forged_keyid.minisig", "server_list.json", "server_list.json", 10, pk}, + + {errWrongKey, "no allowed keys", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{}}, + {ok, "multiple allowed keys 1", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{ + pk[0], "RWSf0PYToIUJmDlsz21YOXvgQzHj9NSdyJUqEY5ZdfS9GepeXt3+JJRZ", + }}, + {ok, "multiple allowed keys 2", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{ + "RWSf0PYToIUJmDlsz21YOXvgQzHj9NSdyJUqEY5ZdfS9GepeXt3+JJRZ", pk[0], + }}, + {errInvalidPublicKey, "invalid allowed key", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{"AAA"}}, + } + + // Cache file contents in map, mapping file names to contents + files := map[string][]byte{} + loadFile := func(name string) { + content, loaded := files[name] + if !loaded { + content, err = ioutil.ReadFile("test_data/" + name) + if err != nil { + panic(err) + } + files[name] = content + } + } + for _, test := range tests { + loadFile(test.signatureFile) + loadFile(test.jsonFile) + } + + forcePrehash := true + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + t.Parallel() + valid, err := verifyWithKeys(string(files[tt.signatureFile]), files[tt.jsonFile], + tt.expectedFileName, tt.minSignTime, tt.allowedPks, forcePrehash) + compareResults(t, valid, err, int(tt.result), func() string { + return fmt.Sprintf("verifyWithKeys(%q, %q, %q, %v, %v, %t)", + tt.signatureFile, tt.jsonFile, tt.expectedFileName, tt.minSignTime, tt.allowedPks, forcePrehash) + }) + }) + } +} + +const ( + ok = -1 // Test should not give an error. + errAny = -2 // Test should give any error (specific error is an implementation detail). +) + +// compareResults compares returned ret, err from a verify function with expected error code expected. +// callStr is called to get the formatted parameters passed to the function. +func compareResults(t *testing.T, ret bool, err error, expected int, callStr func() string) { + getCode := func(err error) int { + switch e := err.(type) { + case detailedVerifyError: + return int(e.Code) + case VerifyError: + return int(e.Code) + } + panic(nil) + } + + if (err == nil) != (expected == ok) || err != nil && expected != errAny && getCode(err) != expected { + var errMsg string + if err != nil { + errMsg = fmt.Sprintf("%v %v (cause %v)", getCode(err), err, errors.Unwrap(err)) + } else { + errMsg = "" + } + + var wantErrCode string + switch expected { + case ok: + wantErrCode = "" + case errAny: + wantErrCode = "" + default: + wantErrCode = strconv.Itoa(expected) + } + + t.Errorf("%v\nerror = %v, wantErr %v", callStr(), errMsg, wantErrCode) + return + } + if ret != (expected == ok) { + t.Errorf("%v\n= %v, want %v", callStr(), ret, expected == ok) + } +} diff --git a/test_data/empty b/test_data/empty deleted file mode 100644 index e69de29..0000000 diff --git a/test_data/generate.sh b/test_data/generate.sh deleted file mode 100644 index b1b4545..0000000 --- a/test_data/generate.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# Generate testcases with fake keys - -# Make sure we do not delete *.minisigs etc. in the wrong directory -if [ ${PWD##*/} != "test_data" ] -then - >&2 echo "Wrong directory, should be run in test_data/" - exit 1 -fi - -rm -f *.minisig *.blake2b - -# Uncomment to regenerate keys -#rm -f *.key -#echo -en "\n\n" | minisign -Gf -p public.key -s secret.key & -#echo -en "\n\n" | minisign -Gf -p wrong_public.key -s wrong_secret.key & -#wait - -# Try to create pure signature with default Minisign (works with version < 0.10) -echo | minisign -Sm server_list.json -x server_list.json.pure.minisig -t $'timestamp:10\tfile:server_list.json' -s secret.key -# Check if it is actually a prehashed signature -if echo | minisign -VHm server_list.json -x server_list.json.pure.minisig -p public.key -then - echo "minisign version is >0.9, trying minisign-0.9" - # If it is, try to sign with some minisign-0.9 program - if ! echo | minisign-0.9 -Sm server_list.json -x server_list.json.pure.minisig -t $'timestamp:10\tfile:server_list.json' -s secret.key - then - >&2 echo -e "\n\nTo produce a non-prehashed signature we need Minisign 0.9\n\n" - fi -fi - -# Rest works with Minisign 0.9 and 0.10 (and up, probably) - -echo | minisign -SHm server_list.json -t $'timestamp:10\tfile:server_list.json\thashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_nohashed.minisig -t $'timestamp:10\tfile:server_list.json' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_latertime.minisig -t $'timestamp:20\tfile:server_list.json\t hashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_orglist.minisig -t $'timestamp:10\tfile:organization_list.json\thashed' -s secret.key & -wait -echo | minisign -SHm server_list.json -x server_list.json.tc_otherfile.minisig -t $'timestamp:10\tfile:otherfile\thashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_nofile.minisig -t $'timestamp:10\thashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_notime.minisig -t $'file:server_list.json\thashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_emptytime.minisig -t $'timestamp:\tfile:server_list.json\thashed' -s secret.key & -wait -echo | minisign -SHm server_list.json -x server_list.json.tc_emptyfile.minisig -t $'timestamp:10\tfile:\thashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_earliertime.minisig -t $'timestamp:9\tfile:server_list.json\thashed' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.tc_random.minisig -t 'random stuff' -s secret.key & -echo | minisign -SHm server_list.json -x server_list.json.large_time.minisig -t $'timestamp:4300000000\tfile:server_list.json' -s secret.key & -wait - -echo | minisign -SHm organization_list.json -t $'timestamp:10\tfile:organization_list.json\thashed' -s secret.key & -echo | minisign -SHm organization_list.json -x organization_list.json.tc_servlist.minisig -t $'timestamp:10\tfile:server_list.json\thashed' -s secret.key & - -echo | minisign -SHm other_list.json -t $'timestamp:10\tfile:other_list.json\thashed' -s secret.key & - -echo | minisign -SHm server_list.json -x server_list.json.wrong_key.minisig -t $'timestamp:10\tfile:server_list.json\thashed' -s wrong_secret.key & -wait - -./generate_forged.py diff --git a/test_data/generate_forged.py b/test_data/generate_forged.py deleted file mode 100644 index 843b32d..0000000 --- a/test_data/generate_forged.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 - -import hashlib -import base64 - -# Hash server_list.json - -with open("server_list.json", "rb") as f: - b = f.read() - -with open("server_list.json.blake2b", "wb") as f: - f.write(hashlib.blake2b(b).digest()) - -# Forge pure signature on hash, see https://github.com/jedisct1/minisign/issues/104 - -with open("server_list.json.minisig", "rb") as f: - siglines = f.readlines() - -siglines[0] = b"untrusted comment: this signature has ED changed to Ed\n" -sig = base64.b64decode(siglines[1]) -siglines[1] = base64.b64encode(b"Ed" + sig[2:]) + b"\n" - -with open("server_list.json.forged_pure.minisig", "wb") as f: - f.writelines(siglines) - # Should now work: minisign -Vm server_list.json.blake2b -x server_list.json.forged_pure.minisig -p public-key - -# Try to forge key ID - -with open("server_list.json.wrong_key.minisig", "rb") as f: - siglines = f.readlines() - -siglines[0] = b"untrusted comment: this signature was created with wrong_secret.key but has key ID changed to that of public.key\n" -sig_wrong = base64.b64decode(siglines[1]) -siglines[1] = base64.b64encode(sig_wrong[:2] + sig[2:2+8] + sig_wrong[2+8:]) + b"\n" - -with open("server_list.json.forged_keyid.minisig", "wb") as f: - f.writelines(siglines) diff --git a/test_data/organization_list.json b/test_data/organization_list.json deleted file mode 100644 index 8c53044..0000000 --- a/test_data/organization_list.json +++ /dev/null @@ -1 +0,0 @@ -{"organization_list": [{}]} \ No newline at end of file diff --git a/test_data/organization_list.json.minisig b/test_data/organization_list.json.minisig deleted file mode 100644 index 1fa546e..0000000 --- a/test_data/organization_list.json.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH31cHjNvTEh+TCqDVCwUgFVZoRdgWYAaQDxH3L3UIsRi9Qb1O4vLI4V1CYPatKzXZnSodSJM/AZgl9v7l/5bfPQ0= -trusted comment: timestamp:10 file:organization_list.json hashed -21zZv1DviMpLCdv1NgzLBl6d+F1ZllSNyjAquYxhTHGcs2F64bDFpqY0I0xjCHIoXly6HKqJKIBXNgud12ijCQ== diff --git a/test_data/organization_list.json.tc_servlist.minisig b/test_data/organization_list.json.tc_servlist.minisig deleted file mode 100644 index a7fe41f..0000000 --- a/test_data/organization_list.json.tc_servlist.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH31cHjNvTEh+TCqDVCwUgFVZoRdgWYAaQDxH3L3UIsRi9Qb1O4vLI4V1CYPatKzXZnSodSJM/AZgl9v7l/5bfPQ0= -trusted comment: timestamp:10 file:server_list.json hashed -R6hjM/oMS5LAvpYM4F6E7iUpnlPxqiY0QfuOnpum31CW0sUy/Ypy2PiomSwvZXKVR7keEZS/+lZjyra9TkrLDQ== diff --git a/test_data/other_list.json b/test_data/other_list.json deleted file mode 100644 index 25ba1a8..0000000 --- a/test_data/other_list.json +++ /dev/null @@ -1 +0,0 @@ -{"other_list": [{}]} \ No newline at end of file diff --git a/test_data/other_list.json.minisig b/test_data/other_list.json.minisig deleted file mode 100644 index eaa2248..0000000 --- a/test_data/other_list.json.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH366C1RnYeUAgEeX/S5A1Z9qmkV2+GJaVj06FWGd4aMLc+HS7iFMhG69u3TVD4YmzMH12rk7hQrnyCC6ex8ypIQA= -trusted comment: timestamp:10 file:other_list.json hashed -26+608n+bjQF9lwNdXbIK6t5bP8dzhjNQ9hACeYJLiB2tr437Aec2GkmJh0jSiRv1QV4RYBcKJeHQBUcV2grCQ== diff --git a/test_data/public.key b/test_data/public.key deleted file mode 100644 index 72676d3..0000000 --- a/test_data/public.key +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: minisign public key DF07F868DFAB9B4C -RWRMm6vfaPgH39iT++NBiUKZim2nDWnalgkNROovPbZdSwVFgUdKU4ac diff --git a/test_data/random.txt b/test_data/random.txt deleted file mode 100644 index b6fc4c6..0000000 --- a/test_data/random.txt +++ /dev/null @@ -1 +0,0 @@ -hello \ No newline at end of file diff --git a/test_data/secret.key b/test_data/secret.key deleted file mode 100644 index 6e4af37..0000000 --- a/test_data/secret.key +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: minisign encrypted secret key -RWRTY0IyobkTOt4ugAHNTPB6zOxHgX8spW6HQWddB5IrdCPDAgsAAAACAAAAAAAAAEAAAAAAvK1S1gsOgozZHuIdLWXq1IwxnWVr+dlySiykTbO6F85HvzPtgxZ7oLcGkT/vPdskAh0SV9H2ylHlt9oarXcWNDKs2r6EcZw/qy5FsD+5uhPfxwWV4qDF+1G456tYDYID63d50CgzdO0= diff --git a/test_data/server_list.json b/test_data/server_list.json deleted file mode 100644 index 67c4c8d..0000000 --- a/test_data/server_list.json +++ /dev/null @@ -1,3 +0,0 @@ -{ -"server_list": [{}] -} \ No newline at end of file diff --git a/test_data/server_list.json.blake2b b/test_data/server_list.json.blake2b deleted file mode 100644 index 5d2ca5a..0000000 Binary files a/test_data/server_list.json.blake2b and /dev/null differ diff --git a/test_data/server_list.json.forged_keyid.minisig b/test_data/server_list.json.forged_keyid.minisig deleted file mode 100644 index efa349d..0000000 --- a/test_data/server_list.json.forged_keyid.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: this signature was created with wrong_secret.key but has key ID changed to that of public.key -RURMm6vfaPgH35aarz3NMq4gbv6JvzOnjG003bDe6USu+HT/JzuxHjQcQGE/KBPdyCF6BDDwwFu+NVmi5jotYCJHWOEqSBU70gE= -trusted comment: timestamp:10 file:server_list.json hashed -3BWYJamM3t6ImuXQufTeO81UMZNyM7TujMu7SCmR+oapsSEBpmkazGOgzlJYR53HP9K9zrEA+4lV8gFFngooBA== diff --git a/test_data/server_list.json.forged_pure.minisig b/test_data/server_list.json.forged_pure.minisig deleted file mode 100644 index a362504..0000000 --- a/test_data/server_list.json.forged_pure.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: this signature has ED changed to Ed -RWRMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 file:server_list.json hashed -oK41aX7rmpbO2ohF3v3+JGgSexQaVlfWvYPzaKEkDlJm8mVZtuK/h26SCRuL6PbTR92DLZU59rw8ckICUH/ADw== diff --git a/test_data/server_list.json.large_time.minisig b/test_data/server_list.json.large_time.minisig deleted file mode 100644 index 79a2a52..0000000 --- a/test_data/server_list.json.large_time.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:4300000000 file:server_list.json -L9C58LIq7bTLf4otqW4Eb+ASL0+FM7nRRjstCBuCPtuUerFIsOqNUpDp2AQJJ4pZJKE7SkgIq2tV8/IaVpzxBQ== diff --git a/test_data/server_list.json.minisig b/test_data/server_list.json.minisig deleted file mode 100644 index 143585b..0000000 --- a/test_data/server_list.json.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 file:server_list.json hashed -oK41aX7rmpbO2ohF3v3+JGgSexQaVlfWvYPzaKEkDlJm8mVZtuK/h26SCRuL6PbTR92DLZU59rw8ckICUH/ADw== diff --git a/test_data/server_list.json.pure.minisig b/test_data/server_list.json.pure.minisig deleted file mode 100644 index 57dccfc..0000000 --- a/test_data/server_list.json.pure.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RWRMm6vfaPgH3zQ/rcq2GMsNz1SYySz+olupm0I+nzNpOkPyUHTBwig3Pep4biOk/bH73bH+0sLNoZPcDk1f2Acn8JINc9MWMw4= -trusted comment: timestamp:10 file:server_list.json -FZ0eA96SlADsMrSOUgStQJpmUnBGpPbRvNI/oaYhKrylu6jUcXOgsRu6571mmDxYdlruSuUSlQbdmG81Qbl4AA== diff --git a/test_data/server_list.json.tc_earliertime.minisig b/test_data/server_list.json.tc_earliertime.minisig deleted file mode 100644 index 03da710..0000000 --- a/test_data/server_list.json.tc_earliertime.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:9 file:server_list.json hashed -vw3wjLDNZWoV98/GnFv38REiaeh+wUPEZgmBUvY35CEq00jDdHiJcYRV/7zBoKv+n9TAYxZ8WKUOGWNOPonTBg== diff --git a/test_data/server_list.json.tc_emptyfile.minisig b/test_data/server_list.json.tc_emptyfile.minisig deleted file mode 100644 index a7aa3ed..0000000 --- a/test_data/server_list.json.tc_emptyfile.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 file: hashed -g4drZ91TcYXNLnIGbeH5ZIFzrs2wWB9JTXjV3Jwg9ehSC2D8lCTqw3u2Rg+PvLPRvYmXTHyuJoKNWelsSh64CA== diff --git a/test_data/server_list.json.tc_emptytime.minisig b/test_data/server_list.json.tc_emptytime.minisig deleted file mode 100644 index d3ef01e..0000000 --- a/test_data/server_list.json.tc_emptytime.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp: file:server_list.json hashed -lw5rnZsPi+TkZ4lOCy7bjsUgTXxG+jaGOGdHuNL95FSD2mmP9ZzEJPrJ2jnH7iYfkF3zDm0QvEUDxhEirlHBDA== diff --git a/test_data/server_list.json.tc_latertime.minisig b/test_data/server_list.json.tc_latertime.minisig deleted file mode 100644 index 8237123..0000000 --- a/test_data/server_list.json.tc_latertime.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:20 file:server_list.json hashed -rHcsHF2mmcZvDLreeuljVauuFULWiY8luCsxyBxxobcJkCedEDW3/RX5KeT+2NjHSFuQxkmrYOBWTY9+ECuUDQ== diff --git a/test_data/server_list.json.tc_nofile.minisig b/test_data/server_list.json.tc_nofile.minisig deleted file mode 100644 index 3c1dcbe..0000000 --- a/test_data/server_list.json.tc_nofile.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 hashed -NonaTZH7RDbsHXv85M7sL43YE7CTzs5qDRRoFYjajeqzHa+hdIuMGyemK85rAJ3prLGnMdWHkZhD4hsr3cZoDA== diff --git a/test_data/server_list.json.tc_nohashed.minisig b/test_data/server_list.json.tc_nohashed.minisig deleted file mode 100644 index 1d140c1..0000000 --- a/test_data/server_list.json.tc_nohashed.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 file:server_list.json -HaPGKT+Jqxjyw2Nt1GEKaPIZsAmVl/RI6p1mQ+S1LqzYicVgT5GxPs9NR6khdGGIFvo/xhVkXFceAWTRUCVQAg== diff --git a/test_data/server_list.json.tc_notime.minisig b/test_data/server_list.json.tc_notime.minisig deleted file mode 100644 index 39625c3..0000000 --- a/test_data/server_list.json.tc_notime.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: file:server_list.json hashed -dMhb+0Y0KAO2tzI4g0ukL/VdMiLVopmXa9BS1RQBY8bYwzmebdIM4DAIZrhtO1avkpdy0prZehuhA1No6cOSAw== diff --git a/test_data/server_list.json.tc_orglist.minisig b/test_data/server_list.json.tc_orglist.minisig deleted file mode 100644 index 7c2a3a8..0000000 --- a/test_data/server_list.json.tc_orglist.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 file:organization_list.json hashed -NreDM4iGEjMWs5sfaJCGZBZ7D9QLqxBKJ/fVW2lvIDr249DSUNR4ZRca8UL73e3c9eTXgHnY/ojsjDtzxDScDw== diff --git a/test_data/server_list.json.tc_otherfile.minisig b/test_data/server_list.json.tc_otherfile.minisig deleted file mode 100644 index 58a29b2..0000000 --- a/test_data/server_list.json.tc_otherfile.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: timestamp:10 file:otherfile hashed -PfDEIMlt2aNFyOnqHb45S7xm4fIg0vfUUbqXENPxry9GEZFX14c5BGtgcL/krDg8WFJHcIA5bzYcX58kgBiZCA== diff --git a/test_data/server_list.json.tc_random.minisig b/test_data/server_list.json.tc_random.minisig deleted file mode 100644 index 7240980..0000000 --- a/test_data/server_list.json.tc_random.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RURMm6vfaPgH3997FX/cHwhXJpcluwbNiznrfYV83WS/Gsd3BeO/g10Mo7Z9N5rMSXcpGrmT2CagiEEm5zSw/MEnTqs4YWICdQs= -trusted comment: random stuff -szGsyESH0EizTXH6n0yuQg6sHTKXr+TJW/Er9ZNJYgQV+1hVM+fc5q1EmVsJlA3kW4Rt/d1p9F0ShLIIgW2vAA== diff --git a/test_data/server_list.json.wrong_key.minisig b/test_data/server_list.json.wrong_key.minisig deleted file mode 100644 index 5a83c0e..0000000 --- a/test_data/server_list.json.wrong_key.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RUTQvDHvQuYCCJaarz3NMq4gbv6JvzOnjG003bDe6USu+HT/JzuxHjQcQGE/KBPdyCF6BDDwwFu+NVmi5jotYCJHWOEqSBU70gE= -trusted comment: timestamp:10 file:server_list.json hashed -3BWYJamM3t6ImuXQufTeO81UMZNyM7TujMu7SCmR+oapsSEBpmkazGOgzlJYR53HP9K9zrEA+4lV8gFFngooBA== diff --git a/test_data/wrong_public.key b/test_data/wrong_public.key deleted file mode 100644 index aa794d4..0000000 --- a/test_data/wrong_public.key +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: minisign public key 802E642EF31BCD0 -RWTQvDHvQuYCCPDLi3UCXzj3BbzFM5QxUFfrp174iaqYo8lT0VaAkhOt diff --git a/test_data/wrong_secret.key b/test_data/wrong_secret.key deleted file mode 100644 index 68e9092..0000000 --- a/test_data/wrong_secret.key +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: minisign encrypted secret key -RWRTY0Iyrc2CTG2W1ZqEq9tb94oQWTnYUy4k8boMf13478FwlDYAAAACAAAAAAAAAEAAAAAA2gFhwOtjETu5WN1LpgtJHV1dk/7466LBJ8dgO/pZoQ3LLAYxlswJHVR/N/Q1HmmKvlxWo2jNTJcARXuHHlMTEgg1MERTldE88CqETrVbvq1JaqJlAY/HMkiqNEUR3L6+5VHbYPKXlVQ= diff --git a/verify_test.go b/verify_test.go deleted file mode 100644 index 769bfbc..0000000 --- a/verify_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package eduvpn_discovery - -import ( - "bufio" - "errors" - "fmt" - "io/ioutil" - "os" - "strconv" - "testing" -) - -func Test_verifyWithKeys(t *testing.T) { - var err error - - var pk []string - { - file, err := os.Open("test_data/public.key") - if err != nil { - panic(err) - } - defer file.Close() - - // Get last line (key string) from file - scanner := bufio.NewScanner(file) - for i := 0; i < 2; i++ { - if !scanner.Scan() { - panic(scanner.Err()) - } - } - pk = []string{scanner.Text()} - } - - tests := []struct { - result detailedVerifyErrorCode - testName string - signatureFile string - jsonFile string - expectedFileName string - minSignTime uint64 - allowedPks []string - }{ - {errInvalidSignatureAlgorithm, "pure", "server_list.json.pure.minisig", "server_list.json", "server_list.json", 10, pk}, - - {ok, "valid server_list", "server_list.json.minisig", "server_list.json", "server_list.json", 10, pk}, - {ok, "TC no hashed", "server_list.json.tc_nohashed.minisig", "server_list.json", "server_list.json", 10, pk}, - {ok, "TC later time", "server_list.json.tc_latertime.minisig", "server_list.json", "server_list.json", 10, pk}, - {errWrongFileName, "server_list TC file:organization_list", "server_list.json.tc_orglist.minisig", "server_list.json", "server_list.json", 10, pk}, - {errWrongFileName, "organization_list as server_list", "organization_list.json.minisig", "organization_list.json", "server_list.json", 10, pk}, - {errWrongFileName, "TC file:otherfile", "server_list.json.tc_otherfile.minisig", "server_list.json", "server_list.json", 10, pk}, - {errInvalidTrustedComment, "TC no file", "server_list.json.tc_nofile.minisig", "server_list.json", "server_list.json", 10, pk}, - {errInvalidTrustedComment, "TC no time", "server_list.json.tc_notime.minisig", "server_list.json", "server_list.json", 10, pk}, - {errAny, "TC empty time", "server_list.json.tc_emptytime.minisig", "server_list.json", "server_list.json", 10, pk}, - {errAny, "TC empty file", "server_list.json.tc_emptyfile.minisig", "server_list.json", "server_list.json", 10, pk}, - {errInvalidTrustedComment, "TC random", "server_list.json.tc_random.minisig", "server_list.json", "server_list.json", 10, pk}, - {ok, "large time", "server_list.json.large_time.minisig", "server_list.json", "server_list.json", 43e8, pk}, - {ok, "lower min time", "server_list.json.minisig", "server_list.json", "server_list.json", 5, pk}, - {errTooOld, "higher min time", "server_list.json.minisig", "server_list.json", "server_list.json", 11, pk}, - - {ok, "valid organization_list", "organization_list.json.minisig", "organization_list.json", "organization_list.json", 10, pk}, - {errWrongFileName, "organization_list TC file:server_list", "organization_list.json.tc_servlist.minisig", "organization_list.json", "organization_list.json", 10, pk}, - {errWrongFileName, "server_list as organization_list", "server_list.json.minisig", "server_list.json", "organization_list.json", 10, pk}, - - {errUnknownExpectedFileName, "valid other_list", "other_list.json.minisig", "other_list.json", "other_list.json", 10, pk}, - {errWrongFileName, "other_list as server_list", "other_list.json.minisig", "other_list.json", "server_list.json", 10, pk}, - - {errInvalidSignatureFormat, "invalid signature file", "random.txt", "server_list.json", "server_list.json", 10, pk}, - {errInvalidSignatureFormat, "empty signature file", "empty", "server_list.json", "server_list.json", 10, pk}, - - {errWrongKey, "wrong key", "server_list.json.wrong_key.minisig", "server_list.json", "server_list.json", 10, pk}, - - {errInvalidSignatureAlgorithm, "forged pure signature", "server_list.json.forged_pure.minisig", "server_list.json.blake2b", "server_list.json", 10, pk}, - {errInvalidSignature, "forged key ID", "server_list.json.forged_keyid.minisig", "server_list.json", "server_list.json", 10, pk}, - - {errWrongKey, "no allowed keys", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{}}, - {ok, "multiple allowed keys 1", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{ - pk[0], "RWSf0PYToIUJmDlsz21YOXvgQzHj9NSdyJUqEY5ZdfS9GepeXt3+JJRZ", - }}, - {ok, "multiple allowed keys 2", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{ - "RWSf0PYToIUJmDlsz21YOXvgQzHj9NSdyJUqEY5ZdfS9GepeXt3+JJRZ", pk[0], - }}, - {errInvalidPublicKey, "invalid allowed key", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{"AAA"}}, - } - - // Cache file contents in map, mapping file names to contents - files := map[string][]byte{} - loadFile := func(name string) { - content, loaded := files[name] - if !loaded { - content, err = ioutil.ReadFile("test_data/" + name) - if err != nil { - panic(err) - } - files[name] = content - } - } - for _, test := range tests { - loadFile(test.signatureFile) - loadFile(test.jsonFile) - } - - for _, tt := range tests { - t.Run(tt.testName, func(t *testing.T) { - t.Parallel() - valid, err := verifyWithKeys(string(files[tt.signatureFile]), files[tt.jsonFile], - tt.expectedFileName, tt.minSignTime, tt.allowedPks) - compareResults(t, valid, err, int(tt.result), func() string { - return fmt.Sprintf("verifyWithKeys(%q, %q, %q, %v, %v)", - tt.signatureFile, tt.jsonFile, tt.expectedFileName, tt.minSignTime, tt.allowedPks) - }) - }) - } -} - -const ( - ok = -1 // Test should not give an error. - errAny = -2 // Test should give any error (specific error is an implementation detail). -) - -// compareResults compares returned ret, err from a verify function with expected error code expected. -// callStr is called to get the formatted parameters passed to the function. -func compareResults(t *testing.T, ret bool, err error, expected int, callStr func() string) { - getCode := func(err error) int { - switch e := err.(type) { - case detailedVerifyError: - return int(e.Code) - case VerifyError: - return int(e.Code) - } - panic(nil) - } - - if (err == nil) != (expected == ok) || err != nil && expected != errAny && getCode(err) != expected { - var errMsg string - if err != nil { - errMsg = fmt.Sprintf("%v %v (cause %v)", getCode(err), err, errors.Unwrap(err)) - } else { - errMsg = "" - } - - var wantErrCode string - switch expected { - case ok: - wantErrCode = "" - case errAny: - wantErrCode = "" - default: - wantErrCode = strconv.Itoa(expected) - } - - t.Errorf("%v\nerror = %v, wantErr %v", callStr(), errMsg, wantErrCode) - return - } - if ret != (expected == ok) { - t.Errorf("%v\n= %v, want %v", callStr(), ret, expected == ok) - } -} -- cgit v1.2.3