summaryrefslogtreecommitdiff
path: root/internal/verify.go
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-05-02 14:34:35 +0200
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-05-02 14:34:35 +0200
commit466450f0c47bdc614e66326d90e5fc6fb56ae732 (patch)
treea01518a58d50d2f8449d37dadecc40e35c9f1fe1 /internal/verify.go
parenta2a8efdcaad3d9b1852b1367a7cd7e8c5860cecf (diff)
Refactor: Wrap most errors in a custom type
Diffstat (limited to 'internal/verify.go')
-rw-r--r--internal/verify.go154
1 files changed, 77 insertions, 77 deletions
diff --git a/internal/verify.go b/internal/verify.go
index 9128777..713e4d7 100644
--- a/internal/verify.go
+++ b/internal/verify.go
@@ -58,13 +58,81 @@ func InsecureTestingSetExtraKey(keyString string) {
extraKey = keyString
}
+// 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 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, filename string, minSignTime uint64, allowedPublicKeys []string, forcePrehash bool) (bool, error) {
+ switch filename {
+ case "server_list.json", "organization_list.json":
+ break
+ default:
+ return false, &VerifyUnknownExpectedFilenameError{Filename: filename, Expected: "server_list.json or organization_list.json"}
+ }
+
+ sig, err := minisign.DecodeSignature(signatureFileContent)
+ if err != nil {
+ return false, &VerifyInvalidSignatureFormatError{Err: err}
+ }
+
+ // Check if signature is prehashed, see https://jedisct1.github.io/minisign/#signature-format
+ if forcePrehash && sig.SignatureAlgorithm != [2]byte{'E', 'D'} {
+ return false, &VerifyInvalidSignatureAlgorithmError{Algorithm: string(sig.SignatureAlgorithm[:]), WantedAlgorithm: "ED (BLAKE2b-prehashed EdDSA)"}
+ }
+
+ // 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, &VerifyCreatePublicKeyError{PublicKey: keyStr, Err: err}
+ }
+
+ if sig.KeyId != key.KeyId {
+ continue // Wrong key
+ }
+
+ valid, err := key.Verify(signedJson, sig)
+ if !valid {
+ return false, &VerifyInvalidSignatureError{Err: err}
+ }
+
+ // Parse trusted comment
+ var signTime uint64
+ var sigFileName string
+ // sigFileName cannot have spaces
+ _, err = fmt.Sscanf(sig.TrustedComment, "trusted comment: timestamp:%d\tfile:%s", &signTime, &sigFileName)
+ if err != nil {
+ return false, &VerifyInvalidTrustedCommentError{TrustedComment: sig.TrustedComment, Err: err}
+ }
+
+ if sigFileName != filename {
+ return false, &VerifyWrongSigFilenameError{Filename: filename, SigFilename: sigFileName}
+ }
+
+ if signTime < minSignTime {
+ return false, &VerifySigTimeEarlierError{SigTime: signTime, MinSigTime: minSignTime}
+ }
+
+ return true, nil
+ }
+
+ // No matching allowed key found
+ return false, &VerifyUnknownKeyError{Filename: filename}
+}
+
type VerifyUnknownExpectedFilenameError struct {
Filename string
Expected string
}
func (e *VerifyUnknownExpectedFilenameError) Error() string {
- return fmt.Sprintf("invalid filename %s, expected %s", e.Filename, e.Expected)
+ return fmt.Sprintf("invalid filename: %s, expected: %s", e.Filename, e.Expected)
}
type VerifyInvalidSignatureFormatError struct {
@@ -72,7 +140,7 @@ type VerifyInvalidSignatureFormatError struct {
}
func (e *VerifyInvalidSignatureFormatError) Error() string {
- return fmt.Sprintf("invalid signature format, error %v", e.Err)
+ return fmt.Sprintf("invalid signature format with error: %v", e.Err)
}
type VerifyInvalidSignatureAlgorithmError struct {
@@ -81,7 +149,7 @@ type VerifyInvalidSignatureAlgorithmError struct {
}
func (e *VerifyInvalidSignatureAlgorithmError) Error() string {
- return fmt.Sprintf("invalid signature algorithm %s, wanted %s", e.Algorithm, e.WantedAlgorithm)
+ return fmt.Sprintf("invalid signature algorithm: %s, wanted: %s", e.Algorithm, e.WantedAlgorithm)
}
type VerifyCreatePublicKeyError struct {
@@ -90,7 +158,7 @@ type VerifyCreatePublicKeyError struct {
}
func (e *VerifyCreatePublicKeyError) Error() string {
- return fmt.Sprintf("failed to create public key %s with error %v", e.PublicKey, e.Err)
+ return fmt.Sprintf("failed to create public key: %s with error: %v", e.PublicKey, e.Err)
}
type VerifyInvalidSignatureError struct {
@@ -98,7 +166,7 @@ type VerifyInvalidSignatureError struct {
}
func (e *VerifyInvalidSignatureError) Error() string {
- return fmt.Sprintf("invalid signature with error %v", e.Err)
+ return fmt.Sprintf("invalid signature with error: %v", e.Err)
}
type VerifyInvalidTrustedCommentError struct {
@@ -107,7 +175,7 @@ type VerifyInvalidTrustedCommentError struct {
}
func (e *VerifyInvalidTrustedCommentError) Error() string {
- return fmt.Sprintf("invalid trusted comment %s with error %v", e.TrustedComment, e.Err)
+ return fmt.Sprintf("invalid trusted comment: %s with error: %v", e.TrustedComment, e.Err)
}
type VerifyWrongSigFilenameError struct {
@@ -116,7 +184,7 @@ type VerifyWrongSigFilenameError struct {
}
func (e *VerifyWrongSigFilenameError) Error() string {
- return fmt.Sprintf("wrong filename %s, expected filename %s for signature", e.Filename, e.SigFilename)
+ return fmt.Sprintf("wrong filename: %s, expected filename: %s for signature", e.Filename, e.SigFilename)
}
type VerifySigTimeEarlierError struct {
@@ -125,7 +193,7 @@ type VerifySigTimeEarlierError struct {
}
func (e *VerifySigTimeEarlierError) Error() string {
- return fmt.Sprintf("Sign time %d is earlier than sign time %d", e.SigTime, e.MinSigTime)
+ return fmt.Sprintf("Sign time: %d is earlier than sign time: %d", e.SigTime, e.MinSigTime)
}
type VerifyUnknownKeyError struct {
@@ -133,73 +201,5 @@ type VerifyUnknownKeyError struct {
}
func (e *VerifyUnknownKeyError) Error() string {
- return fmt.Sprintf("signature for filename %s was created with an unknown key", e.Filename)
-}
-
-// 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 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, filename string, minSignTime uint64, allowedPublicKeys []string, forcePrehash bool) (bool, error) {
- switch filename {
- case "server_list.json", "organization_list.json":
- break
- default:
- return false, &VerifyUnknownExpectedFilenameError{Filename: filename, Expected: "server_list.json or organization_list.json"}
- }
-
- sig, err := minisign.DecodeSignature(signatureFileContent)
- if err != nil {
- return false, &VerifyInvalidSignatureFormatError{Err: err}
- }
-
- // Check if signature is prehashed, see https://jedisct1.github.io/minisign/#signature-format
- if forcePrehash && sig.SignatureAlgorithm != [2]byte{'E', 'D'} {
- return false, &VerifyInvalidSignatureAlgorithmError{Algorithm: string(sig.SignatureAlgorithm[:]), WantedAlgorithm: "ED (BLAKE2b-prehashed EdDSA)"}
- }
-
- // 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, &VerifyCreatePublicKeyError{PublicKey: keyStr, Err: err}
- }
-
- if sig.KeyId != key.KeyId {
- continue // Wrong key
- }
-
- valid, err := key.Verify(signedJson, sig)
- if !valid {
- return false, &VerifyInvalidSignatureError{Err: err}
- }
-
- // Parse trusted comment
- var signTime uint64
- var sigFileName string
- // sigFileName cannot have spaces
- _, err = fmt.Sscanf(sig.TrustedComment, "trusted comment: timestamp:%d\tfile:%s", &signTime, &sigFileName)
- if err != nil {
- return false, &VerifyInvalidTrustedCommentError{TrustedComment: sig.TrustedComment, Err: err}
- }
-
- if sigFileName != filename {
- return false, &VerifyWrongSigFilenameError{Filename: filename, SigFilename: sigFileName}
- }
-
- if signTime < minSignTime {
- return false, &VerifySigTimeEarlierError{SigTime: signTime, MinSigTime: minSignTime}
- }
-
- return true, nil
- }
-
- // No matching allowed key found
- return false, &VerifyUnknownKeyError{Filename: filename}
+ return fmt.Sprintf("signature for filename: %s was created with an unknown key", e.Filename)
}