taldir

Directory service to resolve wallet mailboxes by messenger addresses
Log | Files | Refs | Submodules | README | LICENSE

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:
Mpkg/taldir/command_validator.go | 8++++----
Mpkg/taldir/taldir.go | 39++++++++++++++++++++++++++++++---------
Mpkg/taldir/validator.go | 2+-
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) }