summaryrefslogtreecommitdiff
path: root/verify.go
diff options
context:
space:
mode:
authorStevenWdV <stevenwdv@gmail.com>2022-01-24 14:59:25 +0100
committerStevenWdV <stevenwdv@gmail.com>2022-01-24 16:24:57 +0100
commite544c6fa9e15e7277da79e2464243e90b2706b8c (patch)
treede6613747e0e34a799089d4677f9833a85748712 /verify.go
parentaab2e4b966c82b67eb0e204060e5ea6cd4ea15cf (diff)
Cleanup
Added variables to Makefiles to specify custom exports/ directory; Split exception classes in Java & C#; Added more comments; Renamed library and Go package; Removed real (pure) tests; Added generate_lib.ps1 to generate import .lib for Windows (Swift); Moved built Go libraries to exports/lib/; Switch to hopefully faster Swift GitHub Action.
Diffstat (limited to 'verify.go')
-rw-r--r--verify.go50
1 files changed, 32 insertions, 18 deletions
diff --git a/verify.go b/verify.go
index 5cca4d0..336ba73 100644
--- a/verify.go
+++ b/verify.go
@@ -1,4 +1,4 @@
-package eduvpn_verify
+package eduvpn_discovery
import (
"fmt"
@@ -6,9 +6,17 @@ import (
"os"
)
+// getKeys returns keys taken from https://git.sr.ht/~eduvpn/disco.eduvpn.org#public-keys.
+func getKeys() []string {
+ return []string{
+ "RWRtBSX1alxyGX+Xn3LuZnWUT0w//B6EmTJvgaAxBMYzlQeI+jdrO6KF", // fkooman@tuxed.net, kolla@uninett.no
+ "RWQKqtqvd0R7rUDp0rWzbtYPA3towPWcLDCl7eY9pBMMI/ohCmrS0WiM", // RoSp
+ }
+}
+
// Verify verifies the signature (.minisig file format) on signedJson.
//
-// expectedFileName must be set to the file type to be verified, either server_list.json or organization_list.json.
+// 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.
//
@@ -16,10 +24,7 @@ import (
//
// 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) {
- keyStrs := []string{
- "RWRtBSX1alxyGX+Xn3LuZnWUT0w//B6EmTJvgaAxBMYzlQeI+jdrO6KF", // fkooman@tuxed.net, kolla@uninett.no
- "RWQKqtqvd0R7rUDp0rWzbtYPA3towPWcLDCl7eY9pBMMI/ohCmrS0WiM", // RoSp
- }
+ keyStrs := getKeys()
if extraKey != "" {
keyStrs = append(keyStrs, extraKey)
_, err := fmt.Fprintf(os.Stderr, "INSECURE TEST MODE ENABLED WITH KEY %q\n", extraKey)
@@ -37,22 +42,25 @@ func Verify(signatureFileContent string, signedJson []byte, expectedFileName str
return valid, nil
}
-// Extra allowed key for testing
+// extraKey is an extra allowed key for testing.
var extraKey = ""
// InsecureTestingSetExtraKey adds an extra allowed key for verification with Verify.
-// ONLY USE FOR TESTING. Probably not thread-safe. Do not call in parallel to Verify.
+// ONLY USE FOR TESTING. Applies to all threads. Probably not thread-safe. Do not call in parallel to Verify.
+//
+// keyString must be a Base64-encoded Minisign key, or empty to reset.
func InsecureTestingSetExtraKey(keyString string) {
extraKey = keyString
}
-type VerifyErrorCode int
+// VerifyErrorCode Simplified error code for public interface.
+type VerifyErrorCode int8
const (
- ErrUnknownExpectedFileName VerifyErrorCode = iota + 1
- ErrInvalidSignature
- ErrInvalidSignatureUnknownKey
- ErrTooOld
+ ErrUnknownExpectedFileName VerifyErrorCode = iota + 1 // Unknown expected file name specified. The signature has not been verified.
+ ErrInvalidSignature // Signature is invalid (for the expected file type).
+ ErrInvalidSignatureUnknownKey // Signature was created with an unknown key and has not been verified.
+ ErrTooOld // Signature timestamp smaller than specified minimum signing time (rollback).
)
type VerifyError struct {
@@ -71,9 +79,9 @@ func (err VerifyError) Unwrap() error {
//
// 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 file type that is verified is indicated by expectedFileName, which must be one of server_list.json/organization_list.json.
+// 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 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) {
@@ -89,18 +97,21 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile
return false, detailedVerifyError{errInvalidSignatureFormat, "invalid signature format", err}
}
+ // Check if signature is prehashed, see https://jedisct1.github.io/minisign/#signature-format
if sig.SignatureAlgorithm != [2]byte{'E', 'D'} {
return false, detailedVerifyError{errInvalidSignatureAlgorithm, "BLAKE2b-prehashed EdDSA signature required", nil}
}
+ // Find allowed key used for signature
for _, keyStr := range allowedPublicKeys {
key, err := minisign.NewPublicKey(keyStr)
if err != nil {
+ // Should only happen if Verify is wrong or extraKey is invalid
return false, detailedVerifyError{errInvalidPublicKey, "internal error: could not create public key", err}
}
if sig.KeyId != key.KeyId {
- continue
+ continue // Wrong key
}
valid, err := key.Verify(signedJson, sig)
@@ -108,6 +119,7 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile
return false, detailedVerifyError{errInvalidSignature, "invalid signature", err}
}
+ // Parse trusted comment
var signTime uint64
var sigFileName string
// sigFileName cannot have spaces
@@ -127,10 +139,12 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile
return true, nil
}
- return false, detailedVerifyError{errWrongKey, "signature was created with unknown key", nil}
+ // No matching allowed key found
+ return false, detailedVerifyError{errWrongKey, "signature was created with an unknown key", nil}
}
-type detailedVerifyErrorCode int
+// detailedVerifyErrorCode used for unit tests.
+type detailedVerifyErrorCode int8
const (
errUnknownExpectedFileName detailedVerifyErrorCode = iota + 1