gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet-go] branch master updated (7bfc54a -> be8e465)


From: gnunet
Subject: [gnunet-go] branch master updated (7bfc54a -> be8e465)
Date: Wed, 19 Feb 2020 11:06:23 +0100

This is an automated email from the git hooks/post-receive script.

bernd-fix pushed a change to branch master
in repository gnunet-go.

    from 7bfc54a  Adjusted LEHO coexist rules to spec.
     new db8edd2  Started revocation implementation.
     new be8e465  Fixed filtering of supplemental records and GNS2DNS handling.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/cmd/pow-test/main.go                |  48 +++++++
 src/gnunet/message/factory.go           |  12 ++
 src/gnunet/message/msg_revocation.go    | 181 +++++++++++++++++++++++++
 src/gnunet/service/gns/block_handler.go |   8 +-
 src/gnunet/service/gns/module.go        |  14 +-
 src/gnunet/service/revocation/pow.go    | 231 ++++++++++++++++++++++++++++++++
 6 files changed, 490 insertions(+), 4 deletions(-)
 create mode 100644 src/cmd/pow-test/main.go
 create mode 100644 src/gnunet/message/msg_revocation.go
 create mode 100644 src/gnunet/service/revocation/pow.go

diff --git a/src/cmd/pow-test/main.go b/src/cmd/pow-test/main.go
new file mode 100644
index 0000000..4b74b6e
--- /dev/null
+++ b/src/cmd/pow-test/main.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+       "flag"
+       "fmt"
+       "log"
+
+       "gnunet/service/revocation"
+
+       "github.com/bfix/gospel/crypto/ed25519"
+       "github.com/bfix/gospel/math"
+)
+
+func main() {
+       var (
+               quiet bool
+               bits  int
+       )
+       flag.IntVar(&bits, "b", 25, "Number of leading zero bits")
+       flag.BoolVar(&quiet, "q", false, "Be quiet")
+       flag.Parse()
+       fmt.Printf("Leading zeros required: %d\n", bits)
+
+       // generate a random key pair
+       pkey, _ := ed25519.NewKeypair()
+
+       // initialize RevData structure
+       rd := revocation.NewRevData(0, pkey)
+
+       // pre-set difficulty
+       difficulty := math.TWO.Pow(512 - bits).Sub(math.ONE)
+
+       var count uint64 = 0
+       for {
+               result, err := rd.Compute()
+               if err != nil {
+                       log.Fatal(err)
+               }
+               //fmt.Printf("Nonce=%d, Result=(%d) %v\n", rd.GetNonce(), 
result.BitLen(), result)
+               if result.Cmp(difficulty) < 0 {
+                       break
+               }
+               count++
+               rd.Next()
+       }
+       fmt.Printf("PoW found after %d iterations:\n", count)
+       fmt.Printf("--> Nonce=%d\n", rd.GetNonce())
+}
diff --git a/src/gnunet/message/factory.go b/src/gnunet/message/factory.go
index f6a8783..e6e6e73 100644
--- a/src/gnunet/message/factory.go
+++ b/src/gnunet/message/factory.go
@@ -81,6 +81,18 @@ func NewEmptyMessage(msgType uint16) (Message, error) {
                return NewNamecacheCacheMsg(nil), nil
        case NAMECACHE_BLOCK_CACHE_RESPONSE:
                return NewNamecacheCacheResponseMsg(), nil
+
+       //------------------------------------------------------------------
+       // Revocation
+       //------------------------------------------------------------------
+       case REVOCATION_QUERY:
+               return NewRevocationQueryMsg(nil), nil
+       case REVOCATION_QUERY_RESPONSE:
+               return NewRevocationQueryResponseMsg(true), nil
+       case REVOCATION_REVOKE:
+               return NewRevocationRevokeMsg(0, nil, nil), nil
+       case REVOCATION_REVOKE_RESPONSE:
+               return NewRevocationRevokeResponseMsg(false), nil
        }
        return nil, errors.New(fmt.Sprintf("Unknown message type %d", msgType))
 }
diff --git a/src/gnunet/message/msg_revocation.go 
b/src/gnunet/message/msg_revocation.go
new file mode 100644
index 0000000..fea727c
--- /dev/null
+++ b/src/gnunet/message/msg_revocation.go
@@ -0,0 +1,181 @@
+// This file is part of gnunet-go, a GNUnet-implementation in Golang.
+// Copyright (C) 2019, 2020 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 message
+
+import (
+       "fmt"
+
+       "gnunet/crypto"
+       "gnunet/enums"
+       "gnunet/util"
+
+       "github.com/bfix/gospel/crypto/ed25519"
+)
+
+//----------------------------------------------------------------------
+// REVOCATION_QUERY
+//----------------------------------------------------------------------
+
+// RevocationQueryMsg
+type RevocationQueryMsg struct {
+       MsgSize  uint16 `order:"big"` // total size of message
+       MsgType  uint16 `order:"big"` // REVOCATION_QUERY (636)
+       Reserved uint32 `order:"big"` // Reserved for future use
+       Zone     []byte `size:"32"`   // Zone that is to be checked for 
revocation
+}
+
+// NewRevocationQueryMsg creates a new message for a given zone.
+func NewRevocationQueryMsg(zone *ed25519.PublicKey) *RevocationQueryMsg {
+       msg := &RevocationQueryMsg{
+               MsgSize:  40,
+               MsgType:  REVOCATION_QUERY,
+               Reserved: 0,
+               Zone:     make([]byte, 32),
+       }
+       if zone != nil {
+               copy(msg.Zone, zone.Bytes())
+       }
+       return msg
+}
+
+// String returns a human-readable representation of the message.
+func (m *RevocationQueryMsg) String() string {
+       return fmt.Sprintf("RevocationQueryMsg{zone=%s}", 
util.EncodeBinaryToString(m.Zone))
+}
+
+// Header returns the message header in a separate instance.
+func (msg *RevocationQueryMsg) Header() *MessageHeader {
+       return &MessageHeader{msg.MsgSize, msg.MsgType}
+}
+
+//----------------------------------------------------------------------
+// REVOCATION_QUERY_RESPONSE
+//----------------------------------------------------------------------
+
+// RevocationQueryResponseMsg
+type RevocationQueryResponseMsg struct {
+       MsgSize uint16 `order:"big"` // total size of message
+       MsgType uint16 `order:"big"` // REVOCATION_QUERY_RESPONSE (637)
+       Valid   uint32 `order:"big"` // revoked(0), valid(1)
+}
+
+// NewRevocationQueryResponseMsg creates a new response for a query.
+func NewRevocationQueryResponseMsg(revoked bool) *RevocationQueryResponseMsg {
+       valid := 1
+       if revoked {
+               valid = 0
+       }
+       return &RevocationQueryResponseMsg{
+               MsgSize: 8,
+               MsgType: REVOCATION_QUERY_RESPONSE,
+               Valid:   uint32(valid),
+       }
+}
+
+// String returns a human-readable representation of the message.
+func (m *RevocationQueryResponseMsg) String() string {
+       return fmt.Sprintf("RevocationQueryResponseMsg{valid=%d}", m.Valid)
+}
+
+// Header returns the message header in a separate instance.
+func (msg *RevocationQueryResponseMsg) Header() *MessageHeader {
+       return &MessageHeader{msg.MsgSize, msg.MsgType}
+}
+
+//----------------------------------------------------------------------
+// REVOCATION_REVOKE
+//----------------------------------------------------------------------
+
+// RevocationRevokeMsg
+type RevocationRevokeMsg struct {
+       MsgSize   uint16                   `order:"big"` // total size of 
message
+       MsgType   uint16                   `order:"big"` // REVOCATION_QUERY 
(636)
+       Reserved  uint32                   `order:"big"` // Reserved for future 
use
+       PoW       uint64                   `order:"big"` // Proof-of-work: 
nonce that satisfy condition
+       Signature []byte                   `size:"64"`   // Signature of the 
revocation.
+       Purpose   *crypto.SignaturePurpose // Size and purpose of signature (8 
bytes)
+       ZoneKey   []byte                   `size:"32"` // Zone key to be revoked
+}
+
+// NewRevocationRevokeMsg creates a new message for a given zone.
+func NewRevocationRevokeMsg(pow uint64, zoneKey *ed25519.PublicKey, sig 
*ed25519.EcSignature) *RevocationRevokeMsg {
+       msg := &RevocationRevokeMsg{
+               MsgSize:   120,
+               MsgType:   REVOCATION_REVOKE,
+               Reserved:  0,
+               PoW:       pow,
+               Signature: make([]byte, 64),
+               Purpose: &crypto.SignaturePurpose{
+                       Size:    40,
+                       Purpose: enums.SIG_REVOCATION,
+               },
+               ZoneKey: make([]byte, 32),
+       }
+       if zoneKey != nil {
+               copy(msg.ZoneKey, zoneKey.Bytes())
+       }
+       if sig != nil {
+               copy(msg.Signature, sig.Bytes())
+       }
+       return msg
+}
+
+// String returns a human-readable representation of the message.
+func (m *RevocationRevokeMsg) String() string {
+       return fmt.Sprintf("RevocationRevokeMsg{pow=%d,zone=%s}", m.PoW, 
util.EncodeBinaryToString(m.ZoneKey))
+}
+
+// Header returns the message header in a separate instance.
+func (msg *RevocationRevokeMsg) Header() *MessageHeader {
+       return &MessageHeader{msg.MsgSize, msg.MsgType}
+}
+
+//----------------------------------------------------------------------
+// REVOCATION_REVOKE_RESPONSE
+//----------------------------------------------------------------------
+
+// RevocationRevokeResponseMsg
+type RevocationRevokeResponseMsg struct {
+       MsgSize uint16 `order:"big"` // total size of message
+       MsgType uint16 `order:"big"` // REVOCATION_QUERY_RESPONSE (637)
+       Success uint32 `order:"big"` // Revoke successful?
+}
+
+// NewRevocationRevokeResponseMsg creates a new response for a query.
+func NewRevocationRevokeResponseMsg(success bool) *RevocationRevokeResponseMsg 
{
+       status := 0
+       if success {
+               status = 1
+       }
+       return &RevocationRevokeResponseMsg{
+               MsgSize: 8,
+               MsgType: REVOCATION_QUERY_RESPONSE,
+               Success: uint32(status),
+       }
+}
+
+// String returns a human-readable representation of the message.
+func (m *RevocationRevokeResponseMsg) String() string {
+       return fmt.Sprintf("RevocationRevokeResponseMsg{success=%v}", m.Success 
== 1)
+}
+
+// Header returns the message header in a separate instance.
+func (msg *RevocationRevokeResponseMsg) Header() *MessageHeader {
+       return &MessageHeader{msg.MsgSize, msg.MsgType}
+}
diff --git a/src/gnunet/service/gns/block_handler.go 
b/src/gnunet/service/gns/block_handler.go
index 1d5a9e5..3b3438d 100644
--- a/src/gnunet/service/gns/block_handler.go
+++ b/src/gnunet/service/gns/block_handler.go
@@ -148,10 +148,12 @@ func NewBlockHandlerList(records 
[]*message.GNSResourceRecord, labels []string)
        // Third pass: Traverse active list and build list of handler instances.
        for _, rec := range active {
                // update counter map for non-supplemental records
-               rrType := int(rec.Type)
-               if (rrType & enums.GNS_FLAG_SUPPL) == 0 {
-                       hl.counts.Add(rrType)
+               if (int(rec.Flags) & enums.GNS_FLAG_SUPPL) != 0 {
+                       logger.Printf(logger.DBG, "[gns] handler_list: skip 
%v\n", rec)
+                       continue
                }
+               rrType := int(rec.Type)
+               hl.counts.Add(rrType)
 
                // check for custom handler type
                if creat, ok := customHandler[rrType]; ok {
diff --git a/src/gnunet/service/gns/module.go b/src/gnunet/service/gns/module.go
index 5626432..d067633 100644
--- a/src/gnunet/service/gns/module.go
+++ b/src/gnunet/service/gns/module.go
@@ -214,7 +214,7 @@ func (gns *GNSModule) ResolveRelative(labels []string, pkey 
*ed25519.PublicKey,
                        inst := hdlr.(*Gns2DnsHandler)
                        // if we are at the end of the path and the requested 
type
                        // includes GNS_TYPE_GNS2DNS, the GNS2DNS records are 
returned...
-                       if len(labels) == 1 && 
kind.HasType(enums.GNS_TYPE_GNS2DNS) {
+                       if len(labels) == 1 && 
kind.HasType(enums.GNS_TYPE_GNS2DNS) && !kind.IsAny() {
                                records = inst.recs
                                break
                        }
@@ -246,8 +246,10 @@ func (gns *GNSModule) ResolveRelative(labels []string, 
pkey *ed25519.PublicKey,
                        // if we are at the end of the path and the requested 
type
                        // includes GNS_TYPE_DNS_CNAME, the records are 
returned...
                        if len(labels) == 1 && 
kind.HasType(enums.GNS_TYPE_DNS_CNAME) && !kind.IsAny() {
+                               logger.Println(logger.DBG, "[gns] CNAME 
requested.")
                                break
                        }
+                       logger.Println(logger.DBG, "[gns] CNAME resolution 
required.")
                        if set, err = gns.ResolveUnknown(inst.name, labels, 
pkey, kind, depth+1); err != nil {
                                logger.Println(logger.ERROR, "[gns] CNAME 
resolution failed.")
                                return
@@ -280,6 +282,16 @@ func (gns *GNSModule) ResolveRelative(labels []string, 
pkey *ed25519.PublicKey,
                        set.AddRecord(inst.rec)
                }
        }
+
+       // if the result set is not empty, add all supplemental records we are 
not
+       // asking for explicitly.
+       if set.Count > 0 {
+               for _, rec := range records {
+                       if !kind.HasType(int(rec.Type)) && 
(int(rec.Flags)&enums.GNS_FLAG_SUPPL) != 0 {
+                               set.AddRecord(rec)
+                       }
+               }
+       }
        return
 }
 
diff --git a/src/gnunet/service/revocation/pow.go 
b/src/gnunet/service/revocation/pow.go
new file mode 100644
index 0000000..368b4e4
--- /dev/null
+++ b/src/gnunet/service/revocation/pow.go
@@ -0,0 +1,231 @@
+// This file is part of gnunet-go, a GNUnet-implementation in Golang.
+// Copyright (C) 2019, 2020 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 revocation
+
+import (
+       "bytes"
+       "crypto/sha256"
+       "crypto/sha512"
+       "encoding/binary"
+       "sync"
+
+       "gnunet/crypto"
+       "gnunet/util"
+
+       "github.com/bfix/gospel/crypto/ed25519"
+       "github.com/bfix/gospel/data"
+       "github.com/bfix/gospel/math"
+       "golang.org/x/crypto/hkdf"
+       "golang.org/x/crypto/scrypt"
+)
+
+//----------------------------------------------------------------------
+// Revocation data
+//----------------------------------------------------------------------
+
+// RevData is the revocation data structure (wire format)
+type RevData struct {
+       Nonce   uint64 `order:"big"` // start with this nonce value
+       ZoneKey []byte `size:"32"`   // public zone key to be revoked
+
+       // transient attributes (not serialized)
+       blob []byte // binary representation of serialized data
+}
+
+// NewRevData creates a RevData instance for the given arguments.
+func NewRevData(nonce uint64, zoneKey *ed25519.PublicKey) *RevData {
+       rd := &RevData{
+               Nonce:   nonce,
+               ZoneKey: make([]byte, 32),
+       }
+       copy(rd.ZoneKey, zoneKey.Bytes())
+       blob, err := data.Marshal(rd)
+       if err != nil {
+               return nil
+       }
+       rd.blob = blob
+       return rd
+}
+
+// GetNonce returns the last checked nonce value
+func (r *RevData) GetNonce() uint64 {
+       if r.blob != nil {
+               var val uint64
+               binary.Read(bytes.NewReader(r.blob[:8]), binary.BigEndian, &val)
+               r.Nonce = val
+       }
+       return r.Nonce
+}
+
+// Next selects the next nonce to be tested.
+func (r *RevData) Next() {
+       var incr func(pos int)
+       incr = func(pos int) {
+               r.blob[pos]++
+               if r.blob[pos] != 0 || pos == 0 {
+                       return
+               }
+               incr(pos - 1)
+       }
+       incr(7)
+}
+
+// Compute calculates the current result for a RevData content.
+// The result is returned as a big integer value.
+func (r *RevData) Compute() (*math.Int, error) {
+
+       // generate key material
+       k, err := scrypt.Key(r.blob, []byte("gnunet-revocation-proof-of-work"), 
2, 8, 2, 64)
+       if err != nil {
+               return nil, err
+       }
+
+       // generate keys
+       skey := crypto.NewSymmetricKey()
+       copy(skey.AESKey, k[:32])
+       copy(skey.TwofishKey, k[32:])
+
+       // generate initialization vector
+       iv := crypto.NewSymmetricIV()
+       prk := hkdf.Extract(sha512.New, k[:32], 
[]byte("gnunet-proof-of-work-ivAES!"))
+       rdr := hkdf.Expand(sha256.New, prk, 
[]byte("gnunet-revocation-proof-of-work"))
+       rdr.Read(iv.AESIv)
+       prk = hkdf.Extract(sha512.New, k[32:], 
[]byte("gnunet-proof-of-work-ivFISH"))
+       rdr = hkdf.Expand(sha256.New, prk, 
[]byte("gnunet-revocation-proof-of-work"))
+       rdr.Read(iv.TwofishIv)
+
+       // perform encryption
+       enc, err := crypto.SymmetricEncrypt(r.blob, skey, iv)
+       if err != nil {
+               return nil, err
+       }
+
+       // compute result
+       result, err := scrypt.Key(enc, 
[]byte("gnunet-revocation-proof-of-work"), 2, 8, 2, 64)
+       return math.NewIntFromBytes(result), nil
+}
+
+//----------------------------------------------------------------------
+// Command types for Worker
+//----------------------------------------------------------------------
+
+// StartCmd starts the PoW calculation beginng at given nonce. If a
+// revocation is initiated the first time, the nonce is 0. If the computation
+// was interrupted (because the revocation service was shutting down), the
+// computation can resume for the next unchecked nonce value.
+// see: StartResponse
+type StartCmd struct {
+       ID   int      // Command identifier (to relate responses)
+       task *RevData // RevData instance to be started
+}
+
+// PauseCmd temporarily pauses the calculation of a PoW.
+// see: PauseResponse
+type PauseCmd struct {
+       ID     int // Command identifier (to relate responses)
+       taskID int // identifier for PoW task
+}
+
+// ResumeCmd resumes a paused PoW calculation.
+// see: ResumeResponse
+type ResumeCmd struct {
+       ID     int // Command identifier (to relate responses)
+       taskID int // identifier for PoW task
+}
+
+// BreakCmd interrupts a running PoW calculation
+type BreakCmd struct {
+       ID     int // Command identifier (to relate responses)
+       taskID int // identifier for PoW task
+}
+
+//----------------------------------------------------------------------
+// Response types for Worker
+//----------------------------------------------------------------------
+
+// StartResponse is a reply to the StartCmd message
+type StartResponse struct {
+       ID     int   // Command identifier (to relate responses)
+       taskID int   // identifier for PoW task
+       err    error // error code (nil on success)
+}
+
+// PauseResponse is a reply to the PauseCmd message
+type PauseResponse struct {
+       ID  int   // Command identifier (to relate responses)
+       err error // error code (nil on success)
+}
+
+// ResumeResponse is a reply to the ResumeCmd message
+type ResumeResponse struct {
+       ID  int   // Command identifier (to relate responses)
+       err error // error code (nil on success)
+}
+
+// BreakResponse is a reply to the BreakCmd message
+type BreakResponse struct {
+       ID    int    // Command identifier (to relate responses)
+       Nonce uint64 // last checked nonce value
+}
+
+//----------------------------------------------------------------------
+// Worker instance
+//----------------------------------------------------------------------
+
+// Task represents a currently active PoW calculation
+type Task struct {
+       ID     int
+       rev    *RevData
+       active bool
+}
+
+// Worker is the revocation worker. It is responsible to manage ad schedule
+// the proof-of-work tasks for revocations.
+type Worker struct {
+       tasks map[int]*Task
+       wg    *sync.WaitGroup
+}
+
+func NewWorker() *Worker {
+       return &Worker{
+               tasks: make(map[int]*Task),
+               wg:    new(sync.WaitGroup),
+       }
+}
+
+func (w *Worker) Run(wg *sync.WaitGroup, cmdCh chan interface{}, responseCh 
chan interface{}) {
+       defer wg.Done()
+       for {
+               select {
+               case cmd := <-cmdCh:
+                       switch x := cmd.(type) {
+                       case *StartCmd:
+                               task := &Task{
+                                       ID:     util.NextID(),
+                                       rev:    x.task,
+                                       active: true,
+                               }
+                               w.tasks[task.ID] = task
+                       }
+
+               default:
+                       // compute a single round of currently active tasks
+               }
+       }
+}

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]