commit 4d18913f8c39448f892c3d018fd20daa8ec67faa
parent cfeed0cca3aba77cd2a5b365435e0df47d1c9d3d
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Sun, 27 Apr 2025 00:07:11 +0200
vendor base32 functions
Diffstat:
8 files changed, 116 insertions(+), 24 deletions(-)
diff --git a/Makefile.in b/Makefile.in
@@ -4,10 +4,10 @@ SCRIPT_TARGET:=$(shell dirname $(shell go list -f '{{.Target}}' ./cmd/taldir-ser
TALER_DIRECTORY_HOME=${datadir}/taler-directory
VERSION=`git describe --tags`
-server: gana
+server:
${GO} build -o taler-directory -ldflags "-X main.version=${VERSION} -X main.taldirdatahome=${TALER_DIRECTORY_HOME}" ./cmd/taldir-server
-cli: gana
+cli:
${GO} build -ldflags "-X main.version=${VERSION} -X main.taldirdatahome=${TALER_DIRECTORY_HOME}" ./cmd/taldir-cli
install: server cli
diff --git a/cmd/taldir-cli/main.go b/cmd/taldir-cli/main.go
@@ -26,7 +26,6 @@ import (
"net/url"
"os"
- gnunetutil "gnunet/util"
"gopkg.in/ini.v1"
"taler.net/taldir/internal/util"
)
@@ -35,7 +34,7 @@ import (
func generateLink(host string, addr string, challenge string) string {
h := sha512.New()
h.Write([]byte(addr))
- h_addr := gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ h_addr := util.Base32CrockfordEncode(h.Sum(nil))
return host + "/register/" + url.QueryEscape(h_addr) + "/" + url.QueryEscape(challenge) + "?address=" + url.QueryEscape(addr)
}
diff --git a/cmd/taldir-server/main_test.go b/cmd/taldir-server/main_test.go
@@ -30,8 +30,6 @@ import (
"strings"
"testing"
- gnunetutil "gnunet/util"
-
"github.com/schanzen/taler-go/pkg/merchant"
"gopkg.in/ini.v1"
"gorm.io/driver/sqlite"
@@ -150,7 +148,7 @@ func TestMain(m *testing.M) {
func getHAddress(addr string) string {
h := sha512.New()
h.Write([]byte(addr))
- return gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ return util.Base32CrockfordEncode(h.Sum(nil))
}
func TestNoEntry(s *testing.T) {
diff --git a/go.mod b/go.mod
@@ -8,7 +8,6 @@ require (
github.com/kataras/i18n v0.0.8
github.com/schanzen/taler-go v1.1.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
- gnunet v0.1.27
gopkg.in/ini.v1 v1.67.0
gorm.io/driver/postgres v1.5.11
gorm.io/driver/sqlite v1.5.7
@@ -17,7 +16,6 @@ require (
require (
github.com/BurntSushi/toml v1.5.0 // indirect
- github.com/bfix/gospel v1.2.31 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
@@ -33,5 +31,3 @@ require (
golang.org/x/text v0.22.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
-
-replace gnunet v0.1.27 => ./third_party/gnunet-go/src/gnunet
diff --git a/go.sum b/go.sum
@@ -1,7 +1,5 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
-github.com/bfix/gospel v1.2.31 h1:14ymN2Fo7aTYiJ0HEhL0jMg+ofe97HwTHvkntj0DutE=
-github.com/bfix/gospel v1.2.31/go.mod h1:s1zIBLFzCWoz2khLuNgDMtzzXtReGmyWVyGTO7ELkHg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=
diff --git a/internal/util/helper.go b/internal/util/helper.go
@@ -21,8 +21,9 @@ package util
import (
"crypto/sha512"
"crypto/rand"
- gnunetutil "gnunet/util"
"time"
+ "errors"
+ "strings"
talerutil "github.com/schanzen/taler-go/pkg/util"
)
@@ -32,7 +33,7 @@ func GenerateSolution(targetUriEncoded string, challenge string) string {
h := sha512.New()
h.Write([]byte(challenge))
h.Write([]byte(targetUriEncoded))
- return gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ return Base32CrockfordEncode(h.Sum(nil))
}
// Generates random reference token used in the validation flow.
@@ -42,7 +43,7 @@ func GenerateChallenge(bytes int) string {
if err != nil {
panic(err)
}
- return gnunetutil.EncodeBinaryToString(randBytes)
+ return Base32CrockfordEncode(randBytes)
}
// Check if this is a non-zero, positive amount
@@ -73,3 +74,106 @@ func CalculateCost(sliceCostAmount string, fixedCostAmount string, howLong time.
}
return sum, nil
}
+
+//------------------------------------------------------------------------
+// Base32 conversion between binary data and string representation
+//------------------------------------------------------------------------
+//
+// A binary array of size m is viewed as a consecutive stream of bits
+// from left to right. Bytes are ordered with ascending address, while
+// bits (in a byte) are ordered MSB to LSB.
+
+// For encoding the stream is partitioned into 5-bit chunks; the last chunk
+// is right-padded with 0's if 8*m is not divisible by 5. Each chunk (value
+// between 0 and 31) is encoded into a character; the mapping for encoding
+// is the same as in [https://www.crockford.com/wrmg/base32.html].
+//
+// For decoding each character is converted to a 5-bit chunk based on the
+// encoder mapping (with one addition: the character 'U' maps to the value
+// 27). The chunks are concatenated to produce the bit stream to be stored
+// in the output array.
+
+// character set used for encoding/decoding
+const xlate = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
+
+var (
+ // ErrInvalidEncoding signals an invalid encoding
+ ErrInvalidEncoding = errors.New("invalid encoding")
+ // ErrBufferTooSmall signalsa too small buffer for decoding
+ ErrBufferTooSmall = errors.New("buffer to small")
+)
+
+// EncodeBinaryToString encodes a byte array into a string.
+func Base32CrockfordEncode(data []byte) string {
+ size, pos, bits, n := len(data), 0, 0, 0
+ out := ""
+ for {
+ if n < 5 {
+ if pos < size {
+ bits = (bits << 8) | (int(data[pos]) & 0xFF)
+ pos++
+ n += 8
+ } else if n > 0 {
+ bits <<= uint(5 - n)
+ n = 5
+ } else {
+ break
+ }
+ }
+ out += string(xlate[(bits>>uint(n-5))&0x1F])
+ n -= 5
+ }
+ return out
+}
+
+// Base32CrockfordDecode decodes a string into a byte array.
+// The function expects the size of the output buffer to be sepcified as an
+// argument ('num'); the function returns an error if the buffer is overrun
+// or if an invalid character is found in the encoded string. If the decoded
+// bit stream is smaller than the output buffer, it is padded with 0's.
+func Base32CrockfordDecode(s string, num int) ([]byte, error) {
+ size := len(s)
+ out := make([]byte, num)
+ rpos, wpos, n, bits := 0, 0, 0, 0
+ for {
+ if n < 8 {
+ if rpos < size {
+ c := rune(s[rpos])
+ rpos++
+ v := strings.IndexRune(xlate, c)
+ if v == -1 {
+ switch c {
+ case 'O':
+ v = 0
+ case 'I', 'L':
+ v = 1
+ case 'U':
+ v = 27
+ default:
+ return nil, ErrInvalidEncoding
+ }
+ }
+ bits = (bits << 5) | (v & 0x1F)
+ n += 5
+ } else {
+ if wpos < num {
+ out[wpos] = byte(bits & ((1 << uint(n+1)) - 1))
+ wpos++
+ for i := wpos; i < num; i++ {
+ out[i] = 0
+ }
+ }
+ break
+ }
+ } else {
+ if wpos < num {
+ out[wpos] = byte((bits >> uint(n-8)) & 0xFF)
+ wpos++
+ n -= 8
+ } else {
+ return nil, ErrBufferTooSmall
+ }
+ }
+ }
+ return out, nil
+}
diff --git a/pkg/rest/taldir.go b/pkg/rest/taldir.go
@@ -39,8 +39,6 @@ import (
"strings"
"time"
- gnunetutil "gnunet/util"
-
"github.com/gertd/go-pluralize"
"github.com/gorilla/mux"
"github.com/kataras/i18n"
@@ -381,7 +379,7 @@ func saltHAddress(hAddress string, salt string) string {
h := sha512.New()
h.Write([]byte(hAddress))
h.Write([]byte(salt))
- return gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ return util.Base32CrockfordEncode(h.Sum(nil))
}
// Called by the registrant to validate the registration request. The reference ID was
@@ -524,7 +522,7 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request) {
// exists.
h := sha512.New()
h.Write([]byte(req.Address))
- hAddress := gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ hAddress := util.Base32CrockfordEncode(h.Sum(nil))
validation.HAddress = hAddress
hsAddress := saltHAddress(validation.HAddress, t.Salt)
err = t.Db.First(&entry, "hs_address = ?", hsAddress).Error
@@ -695,7 +693,7 @@ func (t *Taldir) validationPage(w http.ResponseWriter, r *http.Request) {
h := sha512.New()
h.Write([]byte(address))
- expectedHAddress := gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ expectedHAddress := util.Base32CrockfordEncode(h.Sum(nil))
if expectedHAddress != validation.HAddress {
log.Println("Address does not match challenge!")
@@ -850,7 +848,7 @@ func (t *Taldir) methodLookupResultPage(w http.ResponseWriter, r *http.Request)
return
} else {
hAddressBin := sha512.Sum512([]byte(r.URL.Query().Get("address")))
- hAddress := gnunetutil.EncodeBinaryToString(hAddressBin[:])
+ hAddress := util.Base32CrockfordEncode(hAddressBin[:])
hsAddress := saltHAddress(hAddress, t.Salt)
err = t.Db.First(&entry, "hs_address = ?", hsAddress).Error
if err != nil {
@@ -979,7 +977,7 @@ func (t *Taldir) Initialize(cfg TaldirConfig) {
continue
}
vname := strings.TrimPrefix(sec.Name(), "taldir-validator-")
- vlandingPageTplFile := sec.Key("registration_page").MustString(t.getFileName("web/templates/landing_"+vname+".html"))
+ vlandingPageTplFile := sec.Key("registration_page").MustString(t.getFileName("web/templates/landing_" + vname + ".html"))
vlandingPageTpl, err := template.ParseFiles(vlandingPageTplFile, navTplFile, footerTplFile)
if err != nil {
log.Printf("`%s` template not found, disabling validator `%s`.\n", vlandingPageTplFile, vname)
diff --git a/third_party/gnunet-go b/third_party/gnunet-go
@@ -1 +0,0 @@
-Subproject commit f425c2aeef06d1a6105678c8b058bdde65a26e78