commit 808ecaa9274b8b38c0fb03a417692bbb7b9ed1c0
parent d034fde5da9851e09d3acffd015576ad9115a468
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Fri, 8 Aug 2025 14:06:11 +0200
hash with prefix free encoding
Diffstat:
3 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/pkg/taldir/command_validator.go b/pkg/taldir/command_validator.go
@@ -73,19 +73,19 @@ func (t *CommandValidator) IsAliasValid(alias string) (err error) {
return
}
-func (t *CommandValidator) RegistrationStart(topic string, link string, message string, address string, challenge string) error {
+func (t *CommandValidator) RegistrationStart(topic string, link string, message string, address string, challenge string) (string, error) {
path, err := exec.LookPath(t.command)
if err != nil {
- return err
+ return "", err
}
out, err := exec.Command(path, address, challenge, topic, message).Output()
// FIXME logger
fmt.Printf("Executing `%s %s %s %s %s`\n", path, address, challenge, topic, message)
if err != nil {
fmt.Printf("%s, %v\n", out, err)
- return err
+ return "", err
}
- return nil
+ return "", nil
}
func make_command_validator(cfg *TaldirConfig, name string, landingPageTpl *template.Template) CommandValidator {
diff --git a/pkg/taldir/taldir.go b/pkg/taldir/taldir.go
@@ -26,6 +26,7 @@ package taldir
import (
"crypto/sha512"
"encoding/base64"
+ "encoding/binary"
"encoding/json"
"errors"
"fmt"
@@ -215,6 +216,9 @@ type Validation struct {
// The order ID associated with this validation
OrderID string `json:"-"`
+
+ // Name of the validator
+ ValidatorName string
}
// ErrorDetail is the detailed error payload returned from Taldir endpoints
@@ -331,7 +335,19 @@ func (t *Taldir) disseminateEntries() error {
return nil
}
-// Hashes an identity key (e.g. sha256(<email address>)) with a salt for
+// Hashes the alias with its type in a prefix-free fashion
+// SHA512(len(atype||alias)||atype||alias)
+func hashAlias(atype string, alias string) []byte {
+ h := sha512.New()
+ b := make([]byte, 4)
+ binary.BigEndian.PutUint32(b, uint32(len(atype)+len(alias)))
+ h.Write(b)
+ h.Write([]byte(atype))
+ h.Write([]byte(alias))
+ return h.Sum(nil)
+}
+
+// Hashes an identity key (see hashAlias) with a salt for
// Lookup and storage.
func saltHAddress(hAddress string, salt string) string {
h := sha512.New()
@@ -480,10 +496,10 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request) {
// Setup validation object. Retrieve object from DB if it already
// exists.
- h := sha512.New()
- h.Write([]byte(req.Address))
- hAddress := util.Base32CrockfordEncode(h.Sum(nil))
+ hAddressBin := hashAlias(validator.Name(), req.Address)
+ hAddress := util.Base32CrockfordEncode(hAddressBin)
validation.HAddress = hAddress
+ validation.ValidatorName = validator.Name()
hsAddress := saltHAddress(validation.HAddress, t.Salt)
err = t.Db.First(&entry, "hs_address = ?", hsAddress).Error
// Round to the nearest multiple of a month
@@ -582,7 +598,7 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request) {
topic := t.I18n.GetLocale(r).GetMessage("taldirRegTopic")
link := t.Host + "/register/" + url.QueryEscape(validation.HAddress) + "/" + url.QueryEscape(validation.Challenge) + "?address=" + url.QueryEscape(req.Address)
message := t.I18n.GetLocale(r).GetMessage("taldirRegMessage", link)
- err = validator.RegistrationStart(topic, link, message, req.Address, validation.Challenge)
+ redirectionLink, err := validator.RegistrationStart(topic, link, message, req.Address, validation.Challenge)
if err != nil {
t.Logger.Logf(LogError, err.Error()+"\n")
t.Db.Delete(&validation)
@@ -591,6 +607,11 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request) {
}
// FIXME does this persist this boolean or do we need to call Db.Save again?
validation.ChallengeSent = true
+ if len(redirectionLink) > 0 {
+ // This is dangerous, of course, but our validators are trusted, right?
+ http.Redirect(w, r, redirectionLink, http.StatusSeeOther)
+ return
+ }
w.WriteHeader(202)
}
@@ -642,9 +663,9 @@ func (t *Taldir) validationPage(w http.ResponseWriter, r *http.Request) {
return
}
- h := sha512.New()
- h.Write([]byte(address))
- expectedHAddress := util.Base32CrockfordEncode(h.Sum(nil))
+ // FIXME requires a prefix-free encoding
+ hAddressBin := hashAlias(validation.ValidatorName, address)
+ expectedHAddress := util.Base32CrockfordEncode(hAddressBin)
if expectedHAddress != validation.HAddress {
t.Logger.Logf(LogWarning, "Address does not match challenge!\n")
@@ -794,7 +815,7 @@ func (t *Taldir) methodLookupResultPage(w http.ResponseWriter, r *http.Request)
http.Redirect(w, r, fmt.Sprintf("/landing/"+val.Name()+"?error=%s", emsg), http.StatusSeeOther)
return
} else {
- hAddressBin := sha512.Sum512([]byte(r.URL.Query().Get("address")))
+ hAddressBin := hashAlias(val.Name(), r.URL.Query().Get("address"))
hAddress := util.Base32CrockfordEncode(hAddressBin[:])
hsAddress := saltHAddress(hAddress, t.Salt)
err = t.Db.First(&entry, "hs_address = ?", hsAddress).Error
diff --git a/pkg/taldir/validator.go b/pkg/taldir/validator.go
@@ -47,5 +47,5 @@ type Validator interface {
IsAliasValid(alias string) error
// Start registration
- RegistrationStart(topic string, link string, message string, address string, challenge string) error
+ RegistrationStart(topic string, link string, message string, address string, challenge string) (string, error)
}