summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-02-09 18:10:09 +0100
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-04-05 12:26:10 +0200
commit23e63807085b13a9b221c3374d05099559583011 (patch)
tree61f53f9c8282ba60edba322499a3b68317bc53a7
parent70b4bad8904fe02fe4d783b75c6137ba959363ec (diff)
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 <jeroenwijenbergh@protonmail.com>
-rw-r--r--go.mod2
-rw-r--r--src/server.go56
-rw-r--r--src/test_data/empty (renamed from test_data/empty)0
-rw-r--r--src/test_data/generate.sh (renamed from test_data/generate.sh)0
-rw-r--r--src/test_data/generate_forged.py (renamed from test_data/generate_forged.py)0
-rw-r--r--src/test_data/organization_list.json (renamed from test_data/organization_list.json)0
-rw-r--r--src/test_data/organization_list.json.minisig (renamed from test_data/organization_list.json.minisig)0
-rw-r--r--src/test_data/organization_list.json.tc_servlist.minisig (renamed from test_data/organization_list.json.tc_servlist.minisig)0
-rw-r--r--src/test_data/other_list.json (renamed from test_data/other_list.json)0
-rw-r--r--src/test_data/other_list.json.minisig (renamed from test_data/other_list.json.minisig)0
-rw-r--r--src/test_data/public.key (renamed from test_data/public.key)0
-rw-r--r--src/test_data/random.txt (renamed from test_data/random.txt)0
-rw-r--r--src/test_data/secret.key (renamed from test_data/secret.key)0
-rw-r--r--src/test_data/server_list.json (renamed from test_data/server_list.json)0
-rw-r--r--src/test_data/server_list.json.blake2b (renamed from test_data/server_list.json.blake2b)bin64 -> 64 bytes
-rw-r--r--src/test_data/server_list.json.forged_keyid.minisig (renamed from test_data/server_list.json.forged_keyid.minisig)0
-rw-r--r--src/test_data/server_list.json.forged_pure.minisig (renamed from test_data/server_list.json.forged_pure.minisig)0
-rw-r--r--src/test_data/server_list.json.large_time.minisig (renamed from test_data/server_list.json.large_time.minisig)0
-rw-r--r--src/test_data/server_list.json.minisig (renamed from test_data/server_list.json.minisig)0
-rw-r--r--src/test_data/server_list.json.pure.minisig (renamed from test_data/server_list.json.pure.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_earliertime.minisig (renamed from test_data/server_list.json.tc_earliertime.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_emptyfile.minisig (renamed from test_data/server_list.json.tc_emptyfile.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_emptytime.minisig (renamed from test_data/server_list.json.tc_emptytime.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_latertime.minisig (renamed from test_data/server_list.json.tc_latertime.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_nofile.minisig (renamed from test_data/server_list.json.tc_nofile.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_nohashed.minisig (renamed from test_data/server_list.json.tc_nohashed.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_notime.minisig (renamed from test_data/server_list.json.tc_notime.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_orglist.minisig (renamed from test_data/server_list.json.tc_orglist.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_otherfile.minisig (renamed from test_data/server_list.json.tc_otherfile.minisig)0
-rw-r--r--src/test_data/server_list.json.tc_random.minisig (renamed from test_data/server_list.json.tc_random.minisig)0
-rw-r--r--src/test_data/server_list.json.wrong_key.minisig (renamed from test_data/server_list.json.wrong_key.minisig)0
-rw-r--r--src/test_data/wrong_public.key (renamed from test_data/wrong_public.key)0
-rw-r--r--src/test_data/wrong_secret.key (renamed from test_data/wrong_secret.key)0
-rw-r--r--src/verify.go14
-rw-r--r--src/verify_test.go (renamed from verify_test.go)9
35 files changed, 61 insertions, 20 deletions
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/test_data/empty b/src/test_data/empty
index e69de29..e69de29 100644
--- a/test_data/empty
+++ b/src/test_data/empty
diff --git a/test_data/generate.sh b/src/test_data/generate.sh
index b1b4545..b1b4545 100644
--- a/test_data/generate.sh
+++ b/src/test_data/generate.sh
diff --git a/test_data/generate_forged.py b/src/test_data/generate_forged.py
index 843b32d..843b32d 100644
--- a/test_data/generate_forged.py
+++ b/src/test_data/generate_forged.py
diff --git a/test_data/organization_list.json b/src/test_data/organization_list.json
index 8c53044..8c53044 100644
--- a/test_data/organization_list.json
+++ b/src/test_data/organization_list.json
diff --git a/test_data/organization_list.json.minisig b/src/test_data/organization_list.json.minisig
index 1fa546e..1fa546e 100644
--- a/test_data/organization_list.json.minisig
+++ b/src/test_data/organization_list.json.minisig
diff --git a/test_data/organization_list.json.tc_servlist.minisig b/src/test_data/organization_list.json.tc_servlist.minisig
index a7fe41f..a7fe41f 100644
--- a/test_data/organization_list.json.tc_servlist.minisig
+++ b/src/test_data/organization_list.json.tc_servlist.minisig
diff --git a/test_data/other_list.json b/src/test_data/other_list.json
index 25ba1a8..25ba1a8 100644
--- a/test_data/other_list.json
+++ b/src/test_data/other_list.json
diff --git a/test_data/other_list.json.minisig b/src/test_data/other_list.json.minisig
index eaa2248..eaa2248 100644
--- a/test_data/other_list.json.minisig
+++ b/src/test_data/other_list.json.minisig
diff --git a/test_data/public.key b/src/test_data/public.key
index 72676d3..72676d3 100644
--- a/test_data/public.key
+++ b/src/test_data/public.key
diff --git a/test_data/random.txt b/src/test_data/random.txt
index b6fc4c6..b6fc4c6 100644
--- a/test_data/random.txt
+++ b/src/test_data/random.txt
diff --git a/test_data/secret.key b/src/test_data/secret.key
index 6e4af37..6e4af37 100644
--- a/test_data/secret.key
+++ b/src/test_data/secret.key
diff --git a/test_data/server_list.json b/src/test_data/server_list.json
index 67c4c8d..67c4c8d 100644
--- a/test_data/server_list.json
+++ b/src/test_data/server_list.json
diff --git a/test_data/server_list.json.blake2b b/src/test_data/server_list.json.blake2b
index 5d2ca5a..5d2ca5a 100644
--- a/test_data/server_list.json.blake2b
+++ b/src/test_data/server_list.json.blake2b
Binary files differ
diff --git a/test_data/server_list.json.forged_keyid.minisig b/src/test_data/server_list.json.forged_keyid.minisig
index efa349d..efa349d 100644
--- a/test_data/server_list.json.forged_keyid.minisig
+++ b/src/test_data/server_list.json.forged_keyid.minisig
diff --git a/test_data/server_list.json.forged_pure.minisig b/src/test_data/server_list.json.forged_pure.minisig
index a362504..a362504 100644
--- a/test_data/server_list.json.forged_pure.minisig
+++ b/src/test_data/server_list.json.forged_pure.minisig
diff --git a/test_data/server_list.json.large_time.minisig b/src/test_data/server_list.json.large_time.minisig
index 79a2a52..79a2a52 100644
--- a/test_data/server_list.json.large_time.minisig
+++ b/src/test_data/server_list.json.large_time.minisig
diff --git a/test_data/server_list.json.minisig b/src/test_data/server_list.json.minisig
index 143585b..143585b 100644
--- a/test_data/server_list.json.minisig
+++ b/src/test_data/server_list.json.minisig
diff --git a/test_data/server_list.json.pure.minisig b/src/test_data/server_list.json.pure.minisig
index 57dccfc..57dccfc 100644
--- a/test_data/server_list.json.pure.minisig
+++ b/src/test_data/server_list.json.pure.minisig
diff --git a/test_data/server_list.json.tc_earliertime.minisig b/src/test_data/server_list.json.tc_earliertime.minisig
index 03da710..03da710 100644
--- a/test_data/server_list.json.tc_earliertime.minisig
+++ b/src/test_data/server_list.json.tc_earliertime.minisig
diff --git a/test_data/server_list.json.tc_emptyfile.minisig b/src/test_data/server_list.json.tc_emptyfile.minisig
index a7aa3ed..a7aa3ed 100644
--- a/test_data/server_list.json.tc_emptyfile.minisig
+++ b/src/test_data/server_list.json.tc_emptyfile.minisig
diff --git a/test_data/server_list.json.tc_emptytime.minisig b/src/test_data/server_list.json.tc_emptytime.minisig
index d3ef01e..d3ef01e 100644
--- a/test_data/server_list.json.tc_emptytime.minisig
+++ b/src/test_data/server_list.json.tc_emptytime.minisig
diff --git a/test_data/server_list.json.tc_latertime.minisig b/src/test_data/server_list.json.tc_latertime.minisig
index 8237123..8237123 100644
--- a/test_data/server_list.json.tc_latertime.minisig
+++ b/src/test_data/server_list.json.tc_latertime.minisig
diff --git a/test_data/server_list.json.tc_nofile.minisig b/src/test_data/server_list.json.tc_nofile.minisig
index 3c1dcbe..3c1dcbe 100644
--- a/test_data/server_list.json.tc_nofile.minisig
+++ b/src/test_data/server_list.json.tc_nofile.minisig
diff --git a/test_data/server_list.json.tc_nohashed.minisig b/src/test_data/server_list.json.tc_nohashed.minisig
index 1d140c1..1d140c1 100644
--- a/test_data/server_list.json.tc_nohashed.minisig
+++ b/src/test_data/server_list.json.tc_nohashed.minisig
diff --git a/test_data/server_list.json.tc_notime.minisig b/src/test_data/server_list.json.tc_notime.minisig
index 39625c3..39625c3 100644
--- a/test_data/server_list.json.tc_notime.minisig
+++ b/src/test_data/server_list.json.tc_notime.minisig
diff --git a/test_data/server_list.json.tc_orglist.minisig b/src/test_data/server_list.json.tc_orglist.minisig
index 7c2a3a8..7c2a3a8 100644
--- a/test_data/server_list.json.tc_orglist.minisig
+++ b/src/test_data/server_list.json.tc_orglist.minisig
diff --git a/test_data/server_list.json.tc_otherfile.minisig b/src/test_data/server_list.json.tc_otherfile.minisig
index 58a29b2..58a29b2 100644
--- a/test_data/server_list.json.tc_otherfile.minisig
+++ b/src/test_data/server_list.json.tc_otherfile.minisig
diff --git a/test_data/server_list.json.tc_random.minisig b/src/test_data/server_list.json.tc_random.minisig
index 7240980..7240980 100644
--- a/test_data/server_list.json.tc_random.minisig
+++ b/src/test_data/server_list.json.tc_random.minisig
diff --git a/test_data/server_list.json.wrong_key.minisig b/src/test_data/server_list.json.wrong_key.minisig
index 5a83c0e..5a83c0e 100644
--- a/test_data/server_list.json.wrong_key.minisig
+++ b/src/test_data/server_list.json.wrong_key.minisig
diff --git a/test_data/wrong_public.key b/src/test_data/wrong_public.key
index aa794d4..aa794d4 100644
--- a/test_data/wrong_public.key
+++ b/src/test_data/wrong_public.key
diff --git a/test_data/wrong_secret.key b/src/test_data/wrong_secret.key
index 68e9092..68e9092 100644
--- a/test_data/wrong_secret.key
+++ b/src/test_data/wrong_secret.key
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:<timestamp>\tfile:<expectedFileName>", 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/verify_test.go b/src/verify_test.go
index 769bfbc..b9cc033 100644
--- a/verify_test.go
+++ b/src/verify_test.go
@@ -1,4 +1,4 @@
-package eduvpn_discovery
+package eduvpn
import (
"bufio"
@@ -99,14 +99,15 @@ func Test_verifyWithKeys(t *testing.T) {
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)
+ 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)",
- tt.signatureFile, tt.jsonFile, tt.expectedFileName, tt.minSignTime, tt.allowedPks)
+ return fmt.Sprintf("verifyWithKeys(%q, %q, %q, %v, %v, %t)",
+ tt.signatureFile, tt.jsonFile, tt.expectedFileName, tt.minSignTime, tt.allowedPks, forcePrehash)
})
})
}