[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-taldir] branch master updated: forgot to add files; update base32
From: |
gnunet |
Subject: |
[taler-taldir] branch master updated: forgot to add files; update base32; fix solution calculation |
Date: |
Wed, 06 Jul 2022 14:20:17 +0200 |
This is an automated email from the git hooks/post-receive script.
martin-schanzenbach pushed a commit to branch master
in repository taldir.
The following commit(s) were added to refs/heads/master by this push:
new f01dddf forgot to add files; update base32; fix solution calculation
f01dddf is described below
commit f01dddf4da0689dc612b6a8b7cda332e0d2a3568
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Wed Jul 6 14:20:14 2022 +0200
forgot to add files; update base32; fix solution calculation
---
taldir.go | 66 +++++++++++++++++---
templates/validation_landing.html | 17 +++++
test.sh | 12 ++--
util/base32.go | 127 ++++++++++++++++++++++++++++++++++++++
4 files changed, 207 insertions(+), 15 deletions(-)
diff --git a/taldir.go b/taldir.go
index d8b19e0..38f1608 100644
--- a/taldir.go
+++ b/taldir.go
@@ -3,16 +3,18 @@ package main
import (
"os"
"os/exec"
+ "bufio"
"time"
"fmt"
"log"
+ "flag"
"net/http"
"html/template"
"encoding/json"
"github.com/gorilla/mux"
"gorm.io/gorm"
- "encoding/base32"
"encoding/base64"
+ "taler.net/taldir/util"
"math/rand"
"crypto/sha512"
"gorm.io/driver/postgres"
@@ -101,7 +103,7 @@ type Validation struct {
Method string `json:"method"`
Duration int64 `json:"duration"`
Inbox string `json:"inbox_url"`
- Solution string `json:"solution"`
+ Code string `json:"activation_code"`
PublicKey string `json:"public_key"`
}
@@ -184,11 +186,10 @@ func saltHAddress(h_address string) string {
if "" == salt {
salt = cfg.Section("taldir").Key("salt").MustString("ChangeMe")
}
- fmt.Println("Using salt " + salt)
h := sha512.New()
h.Write([]byte(h_address))
h.Write([]byte(salt))
- return base32.StdEncoding.EncodeToString(h.Sum(nil))
+ return util.EncodeBinaryToString(h.Sum(nil))
}
// Called by the registrant to validate the registration request. The
reference ID was
@@ -217,7 +218,8 @@ func validationRequest(w http.ResponseWriter, r
*http.Request){
w.WriteHeader(http.StatusNotFound)
return
}
- if confirm.Solution != validation.Solution {
+ expectedSolution := generateSolution(validation.PublicKey, validation.Code)
+ if confirm.Solution != expectedSolution {
// FIXME how TF do we rate limit here??
w.WriteHeader(http.StatusForbidden)
return
@@ -237,7 +239,6 @@ func validationRequest(w http.ResponseWriter, r
*http.Request){
err = db.First(&entry, "hs_address = ?", entry.HsAddress).Error
if err == nil {
db.Save(&entry)
- return
} else {
err = db.Create(&entry).Error
if err != nil {
@@ -256,7 +257,7 @@ func generateToken() string {
if err != nil {
panic(err)
}
- return base32.StdEncoding.EncodeToString(randBytes)
+ return util.EncodeBinaryToString(randBytes)
}
func registerRequest(w http.ResponseWriter, r *http.Request){
@@ -289,7 +290,7 @@ func registerRequest(w http.ResponseWriter, r
*http.Request){
}
h := sha512.New()
h.Write([]byte(req.Address))
- validation.HAddress = base32.StdEncoding.EncodeToString(h.Sum(nil))
+ validation.HAddress = util.EncodeBinaryToString(h.Sum(nil))
// We first try if there is already an entry for this address which
// is still valid and the duration is not extended.
hs_address := saltHAddress(validation.HAddress)
@@ -325,7 +326,7 @@ func registerRequest(w http.ResponseWriter, r
*http.Request){
w.WriteHeader(202)
return
} else {
- validation.Solution = generateToken()
+ validation.Code = generateToken()
validation.Inbox = req.Inbox
validation.Duration = req.Duration
validation.PublicKey = req.PublicKey
@@ -346,7 +347,7 @@ func registerRequest(w http.ResponseWriter, r
*http.Request){
return
}
command := cfg.Section("taldir-" + vars["method"]).Key("command").String()
- out, err := exec.Command(command, req.Address, validation.Solution).Output()
+ out, err := exec.Command(command, req.Address, validation.Code).Output()
if err != nil {
log.Fatal(err)
db.Delete(&validation)
@@ -403,6 +404,20 @@ func validationPage(w http.ResponseWriter, r
*http.Request) {
return
}
+// Generates a solution from a code and pubkey
+func generateSolution(pubkeyEncoded string, code string) string {
+ pubkey, err := util.DecodeStringToBinary(pubkeyEncoded, 36)
+ if err != nil {
+ fmt.Println("error decoding pubkey:", err)
+ return ""
+ }
+ h := sha512.New()
+ h.Write([]byte(code))
+ h.Write(pubkey)
+ return util.EncodeBinaryToString(h.Sum(nil))
+}
+
+
func handleRequests() {
myRouter := mux.NewRouter().StrictSlash(true)
@@ -435,6 +450,19 @@ func main() {
if cfg.Section("taldir").Key("production").MustBool(false) {
fmt.Println("Production mode enabled")
}
+ var solveFlag = flag.Bool("s", false, "Provide a solution for the
code/pubkey")
+ var codeFlag = flag.String("c", "", "Activation code")
+ var pubkeyFlag = flag.String("p", "", "Public key")
+ var dropFlag = flag.Bool("D", false, "Drop all data in table (DANGEROUS!)")
+ flag.Parse()
+ if *solveFlag {
+ if len(*codeFlag) == 0 || len(*pubkeyFlag) == 0 {
+ fmt.Println("You need to provide an activation code and a public key to
generate a solution")
+ os.Exit(1)
+ }
+ fmt.Println(generateSolution(*pubkeyFlag, *codeFlag))
+ os.Exit(0)
+ }
validators = make(map[string]bool)
for _, a := range
strings.Split(cfg.Section("taldir").Key("validators").String(), " ") {
validators[a] = true
@@ -456,6 +484,24 @@ func main() {
if err := db.AutoMigrate(&Validation{}); err != nil {
panic(err)
}
+ if *dropFlag {
+ fmt.Println("Really delete all data in database? [y/N]:")
+ reader := bufio.NewReader(os.Stdin)
+ char, _, err := reader.ReadRune()
+
+ if err == nil {
+ fmt.Println(char)
+ if char == 'y' {
+ fmt.Println("Deleting entries...")
+ db.Where("1 = 1").Delete(&Entry{})
+ fmt.Println("Deleting validations...")
+ db.Where("1 = 1").Delete(&Validation{})
+ }
+ os.Exit(0)
+ }
+ os.Exit(1)
+ }
+
validationTpl, err = template.ParseFiles("templates/validation_landing.html")
if err != nil {
fmt.Println(err)
diff --git a/templates/validation_landing.html
b/templates/validation_landing.html
new file mode 100644
index 0000000..ccaa770
--- /dev/null
+++ b/templates/validation_landing.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <!-- Required meta tags -->
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1,
shrink-to-fit=no">
+ <title>Validation Landing Page</title>
+ </head>
+ <body>
+ <div class="container">
+ <h1>Scan this QR code with your Taler Wallet to complete your
registration.</h1>
+ <a href="{{.WalletLink}}">
+ <img src="{{.QRCode}}"/>
+ </a>
+ </div>
+ </body>
+</html>
diff --git a/test.sh b/test.sh
index 411fcba..413b47c 100755
--- a/test.sh
+++ b/test.sh
@@ -1,13 +1,15 @@
#!/bin/bash
# New request
-curl -v localhost:11000/register/test --data '{"address": "abc@test",
"public_key": "pkey", "inbox_url": "myinbox@xyz", "duration": 23}'
+PUBKEY="000G006XE97PTWV3B7AJNCRQZA6BF26HPV3XZ07293FMY7KD4181946A90"
+curl -v localhost:11000/register/test --data "{\"address\": \"abc@test\",
\"public_key\": \"${PUBKEY}\", \"inbox_url\": \"myinbox@xyz\", \"duration\":
23}"
# Read validation code from tempfile
CODE=`cat validation_code`
-H_ADDRESS=`echo -n abc@test | openssl dgst -binary -sha512 | base32 -w0`
+H_ADDRESS=`echo -n abc@test | openssl dgst -binary -sha512 | gnunet-base32`
echo "Code: $CODE; Address: $H_ADDRESS"
# Validate
-echo localhost:11000/register/$H_ADDRESS/$CODE
-exit
-curl -v localhost:11000/$H_ADDRESS --data "{\"solution\": \"${CODE}\"}"
+# echo localhost:11000/register/$H_ADDRESS/$CODE
+SOLUTION=$(./taldir -s -c ${CODE} -p ${PUBKEY})
+echo "Solution: $SOLUTION"
+curl -v localhost:11000/$H_ADDRESS --data "{\"solution\": \"${SOLUTION}\"}"
# Get mapping
curl -v localhost:11000/$H_ADDRESS
diff --git a/util/base32.go b/util/base32.go
new file mode 100644
index 0000000..f0b149a
--- /dev/null
+++ b/util/base32.go
@@ -0,0 +1,127 @@
+// This file is part of gnunet-go, a GNUnet-implementation in Golang.
+// Copyright (C) 2019-2022 Bernd Fix >Y<
+//
+// gnunet-go is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package util
+
+import (
+ "errors"
+ "strings"
+)
+
+//------------------------------------------------------------------------
+// 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 EncodeBinaryToString(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
+}
+
+// DecodeStringToBinary 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 DecodeStringToBinary(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
+}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-taldir] branch master updated: forgot to add files; update base32; fix solution calculation,
gnunet <=