From 662fb0a57c1c2d60bba3bd62d9b8c30b161f6cba Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 19 Oct 2026 10:37:03 +0200 Subject: [PATCH] Map every byte the router's id refuses in an ask id, so a group with = gives a usable ask (issue 1201) --- go/delivery/gate.go | 18 +++++++++++++++--- go/delivery/gate_test.go | 4 +++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/go/delivery/gate.go b/go/delivery/gate.go index 51fdb44..cd85b3f 100644 --- a/go/delivery/gate.go +++ b/go/delivery/gate.go @@ -94,18 +94,30 @@ func ParseAskKey(key string) (kind, group, hash string, err error) { func AnswerKey(askKey string) string { return askKey } // AskID is the id the teller gives the router for the ask at askKey. The router's ids refuse dots (asks.UsableID), -// so in the readable part a dot becomes `-` and a slash `_`; that part is cut to fit, and every id ends in `-` and +// so in the readable part a dot becomes `-` and any other byte outside letters, digits, `_` and `-` becomes `_`; that part is cut to fit, and every id ends in `-` and // the first 12 hex digits of the sha256 of the whole key, so two keys never give one id. It cannot be read back: // the teller keeps the key beside it. func AskID(askKey string) string { const most = 64 // the router's bound on an id const tail = 13 // "-" and 12 hex digits - readable := strings.NewReplacer(".", "-", "/", "_").Replace(askKey) + readable := []byte(askKey) + for i, c := range readable { + switch { + case c >= 'A' && c <= 'Z', c >= 'a' && c <= 'z', c >= '0' && c <= '9': + case c == '.': + readable[i] = '-' + default: // a slash, an equals sign or any other byte the router's id refuses + readable[i] = '_' + } + } + if len(readable) > 0 && (readable[0] == '-' || readable[0] == '_') { + readable[0] = 'k' // an id starts with a letter or digit + } if len(readable) > most-tail { readable = readable[:most-tail] } sum := sha256.Sum256([]byte(askKey)) - return readable + "-" + hex.EncodeToString(sum[:])[:12] + return string(readable) + "-" + hex.EncodeToString(sum[:])[:12] } func checkOwedAct(act string) (kind, context string, err error) { diff --git a/go/delivery/gate_test.go b/go/delivery/gate_test.go index 4f6dcb7..d8306a1 100644 --- a/go/delivery/gate_test.go +++ b/go/delivery/gate_test.go @@ -57,8 +57,10 @@ func TestAskID(t *testing.T) { // 1201/AC2 long2, _ := MergeAskKey("feat/"+strings.Repeat("long-", 20)+"2", gateHeads()) slash, _ := MergeAskKey("a/b", gateHeads()) under, _ := MergeAskKey("a_b", gateHeads()) + eq, _ := MergeAskKey("feat=x", gateHeads()) + eqs, _ := MergeAskKey("feat_x", gateHeads()) seen := map[string]string{} - for _, k := range []string{k1, k2, k3, long, long2, slash, under} { + for _, k := range []string{k1, k2, k3, long, long2, slash, under, eq, eqs, "=odd.key"} { id := AskID(k) if strings.Contains(id, ".") { t.Errorf("id %q holds a dot", id)