gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet-go] branch master updated: Milestone #3 (RC3): Using new test ca


From: gnunet
Subject: [gnunet-go] branch master updated: Milestone #3 (RC3): Using new test case from RFC draft.
Date: Tue, 26 May 2020 11:15:53 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new dfbb345  Milestone #3 (RC3): Using new test case from RFC draft.
dfbb345 is described below

commit dfbb3455b58cfa7b74c4442cae0c8bade7ffef7c
Author: Bernd Fix <address@hidden>
AuthorDate: Tue May 26 11:09:41 2020 +0200

    Milestone #3 (RC3): Using new test case from RFC draft.
---
 src/cmd/revoke-zonekey/main.go            |  25 ++--
 src/gnunet/message/msg_revocation.go      |   2 +
 src/gnunet/service/revocation/pow.go      | 215 ++++++++++++++++++++----------
 src/gnunet/service/revocation/pow_test.go | 132 ++++++++++++++++++
 4 files changed, 290 insertions(+), 84 deletions(-)

diff --git a/src/cmd/revoke-zonekey/main.go b/src/cmd/revoke-zonekey/main.go
index fe0baaa..7deeda6 100644
--- a/src/cmd/revoke-zonekey/main.go
+++ b/src/cmd/revoke-zonekey/main.go
@@ -31,7 +31,6 @@ import (
        "gnunet/service/revocation"
        "gnunet/util"
 
-       "github.com/bfix/gospel/crypto/ed25519"
        "github.com/bfix/gospel/data"
 )
 
@@ -59,12 +58,12 @@ func main() {
 
        // define layout of persistant data
        var revData struct {
-               Rd      *revocation.RevData // Revocation data
-               T       util.RelativeTime   // time spend in calculations
-               Last    uint64              // last value used for PoW test
-               Numbits uint8               // number of leading zero-bits
+               Rd      *revocation.RevDataCalc // Revocation data
+               T       util.RelativeTime       // time spend in calculations
+               Last    uint64                  // last value used for PoW test
+               Numbits uint8                   // number of leading zero-bits
        }
-       dataBuf := make([]byte, 377)
+       dataBuf := make([]byte, 450)
 
        // read revocation object from file
        file, err := os.Open(filename)
@@ -77,8 +76,7 @@ func main() {
                if err != nil {
                        log.Fatal("Invalid zonekey: " + err.Error())
                }
-               pkey := ed25519.NewPublicKeyFromBytes(keyData)
-               revData.Rd = revocation.NewRevData(util.AbsoluteTimeNow(), pkey)
+               revData.Rd = revocation.NewRevDataCalc(keyData)
                revData.Numbits = uint8(bits)
                revData.T = util.NewRelativeTime(0)
                cont = false
@@ -121,11 +119,14 @@ func main() {
        wg.Add(1)
        go func() {
                defer wg.Done()
+               cb := func(average float64, last uint64) {
+                       log.Printf("Improved PoW: %f average zero bits, %d 
steps\n", average, last)
+               }
 
                startTime := util.AbsoluteTimeNow()
-               result, last := revData.Rd.Compute(ctx, bits, revData.Last)
-               if result != 32 {
-                       log.Printf("Incomplete revocation: Only %d of 32 PoWs 
available!\n", result)
+               average, last := revData.Rd.Compute(ctx, bits, revData.Last, cb)
+               if average < float64(bits) {
+                       log.Printf("Incomplete revocation: Only %f zero bits on 
average!\n", average)
                } else {
                        log.Println("Revocation data object:")
                        log.Println("   0x" + 
hex.EncodeToString(revData.Rd.Blob()))
@@ -158,7 +159,7 @@ func main() {
                                log.Fatal("Internal error: " + err.Error())
                        }
                        if len(buf) != len(dataBuf) {
-                               log.Fatal("Internal error: Buffer mismatch")
+                               log.Fatalf("Internal error: Buffer mismatch %d 
!= %d", len(buf), len(dataBuf))
                        }
                        n, err := file.Write(buf)
                        if err != nil {
diff --git a/src/gnunet/message/msg_revocation.go 
b/src/gnunet/message/msg_revocation.go
index 8c7db06..c17f440 100644
--- a/src/gnunet/message/msg_revocation.go
+++ b/src/gnunet/message/msg_revocation.go
@@ -105,6 +105,7 @@ type RevocationRevokeMsg struct {
        MsgSize   uint16            `order:"big"` // total size of message
        MsgType   uint16            `order:"big"` // REVOCATION_REVOKE (638)
        Timestamp util.AbsoluteTime // Timestamp of revocation creation
+       TTL       util.RelativeTime // TTL of revocation
        PoWs      []uint64          `size:"32" order:"big"` // (Sorted) list of 
PoW values
        Signature []byte            `size:"64"`             // Signature 
(Proof-of-ownership).
        ZoneKey   []byte            `size:"32"`             // public zone key 
to be revoked
@@ -116,6 +117,7 @@ func NewRevocationRevokeMsg(zoneKey *ed25519.PublicKey, sig 
*ed25519.EcSignature
                MsgSize:   364,
                MsgType:   REVOCATION_REVOKE,
                Timestamp: util.AbsoluteTimeNow(),
+               TTL:       util.RelativeTime{0},
                PoWs:      make([]uint64, 32),
                Signature: make([]byte, 64),
                ZoneKey:   make([]byte, 32),
diff --git a/src/gnunet/service/revocation/pow.go 
b/src/gnunet/service/revocation/pow.go
index 4f7fde2..03a89af 100644
--- a/src/gnunet/service/revocation/pow.go
+++ b/src/gnunet/service/revocation/pow.go
@@ -22,6 +22,8 @@ import (
        "bytes"
        "context"
        "encoding/binary"
+       "fmt"
+       "sort"
        "time"
 
        "gnunet/crypto"
@@ -62,13 +64,13 @@ func NewPoWData(pow uint64, ts util.AbsoluteTime, zoneKey 
[]byte) *PoWData {
        return rd
 }
 
+// SetPoW sets a new PoW value in the data structure
 func (p *PoWData) SetPoW(pow uint64) error {
        p.PoW = pow
-       blob, err := data.Marshal(p)
-       if err != nil {
-               return err
+       p.blob = p.Blob()
+       if p.blob == nil {
+               return fmt.Errorf("Invalid PoW work unit")
        }
-       p.blob = blob
        return nil
 }
 
@@ -98,10 +100,19 @@ func (p *PoWData) Next() {
 // Compute calculates the current result for a PoWData content.
 // The result is returned as a big integer value.
 func (p *PoWData) Compute() *math.Int {
-       key := argon2.Key(p.blob, []byte("gnunet-revocation-proof-of-work"), 3, 
1024, 1, 64)
+       key := argon2.IDKey(p.blob, []byte("gnunet-revocation-proof-of-work"), 
3, 1024, 1, 64)
        return math.NewIntFromBytes(key)
 }
 
+// Blob returns a serialized instance of the work unit
+func (p *PoWData) Blob() []byte {
+       blob, err := data.Marshal(p)
+       if err != nil {
+               return nil
+       }
+       return blob
+}
+
 //----------------------------------------------------------------------
 // Revocation data
 //----------------------------------------------------------------------
@@ -109,6 +120,7 @@ func (p *PoWData) Compute() *math.Int {
 // RevData is the revocation data (wire format)
 type RevData struct {
        Timestamp util.AbsoluteTime // Timestamp of creation
+       TTL       util.RelativeTime // TTL of revocation
        PoWs      []uint64          `size:"32" order:"big"` // (Sorted) list of 
PoW values
        Signature []byte            `size:"64"`             // Signature 
(Proof-of-ownership).
        ZoneKey   []byte            `size:"32"`             // public zone key 
to be revoked
@@ -121,18 +133,6 @@ type SignedRevData struct {
        Timestamp util.AbsoluteTime // Timestamp of creation
 }
 
-// NewRevData initializes a new RevData instance
-func NewRevData(ts util.AbsoluteTime, pkey *ed25519.PublicKey) *RevData {
-       rd := &RevData{
-               Timestamp: ts,
-               PoWs:      make([]uint64, 32),
-               Signature: make([]byte, 64),
-               ZoneKey:   make([]byte, 32),
-       }
-       copy(rd.ZoneKey, pkey.Bytes())
-       return rd
-}
-
 // NewRevDataFromMsg initializes a new RevData instance from a GNUnet message
 func NewRevDataFromMsg(m *message.RevocationRevokeMsg) *RevData {
        rd := &RevData{
@@ -153,7 +153,7 @@ func (rd *RevData) Sign(skey *ed25519.PrivateKey) error {
                        Size:    48,
                        Purpose: enums.SIG_REVOCATION,
                },
-               ZoneKey:   rd.ZoneKey,
+               ZoneKey:   util.Clone(rd.ZoneKey),
                Timestamp: rd.Timestamp,
        }
        sigData, err := data.Marshal(sigBlock)
@@ -182,7 +182,7 @@ func (rd *RevData) Verify(withSig bool) int {
                                Size:    48,
                                Purpose: enums.SIG_REVOCATION,
                        },
-                       ZoneKey:   rd.ZoneKey,
+                       ZoneKey:   util.Clone(rd.ZoneKey),
                        Timestamp: rd.Timestamp,
                }
                sigData, err := data.Marshal(sigBlock)
@@ -202,8 +202,8 @@ func (rd *RevData) Verify(withSig bool) int {
 
        // (2) check PoWs
        var (
-               zbits int    = 512
-               last  uint64 = 0
+               zbits float64 = 0
+               last  uint64  = 0
        )
        for _, pow := range rd.PoWs {
                // check sequence order
@@ -213,73 +213,144 @@ func (rd *RevData) Verify(withSig bool) int {
                last = pow
                // compute number of leading zero-bits
                work := NewPoWData(pow, rd.Timestamp, rd.ZoneKey)
-               lzb := 512 - work.Compute().BitLen()
-               if lzb < zbits {
-                       zbits = lzb
-               }
+               zbits += float64(512 - work.Compute().BitLen())
        }
+       zbits /= 32.0
 
        // (3) check expiration
-       ttl := time.Duration((zbits-24)*365*24) * time.Hour
-       if util.AbsoluteTimeNow().Add(ttl).Expired() {
-               return -2
+       if zbits > 24.0 {
+               ttl := time.Duration(int((zbits-24)*365*24)) * time.Hour
+               if util.AbsoluteTimeNow().Add(ttl).Expired() {
+                       return -2
+               }
+       }
+       return int(zbits)
+}
+
+//----------------------------------------------------------------------
+// RevData structure for computation
+//----------------------------------------------------------------------
+
+// RevDataCalc is the revocation data structure used while computing
+// the revocation data object.
+type RevDataCalc struct {
+       RevData
+       Bits        []uint16 `size:"32" order:"big"` // number of leading zeros
+       SmallestIdx byte     // index of smallest number of leading zeros
+}
+
+// NewRevDataCalc initializes a new RevDataCalc instance
+func NewRevDataCalc(pkey []byte) *RevDataCalc {
+       rd := &RevDataCalc{
+               RevData: RevData{
+                       Timestamp: util.AbsoluteTimeNow(),
+                       PoWs:      make([]uint64, 32),
+                       Signature: make([]byte, 64),
+                       ZoneKey:   make([]byte, 32),
+               },
+               Bits:        make([]uint16, 32),
+               SmallestIdx: 0,
        }
-       return zbits
+       copy(rd.ZoneKey, pkey)
+       return rd
 }
 
-// Compute tries to compute a valid Revocation; it returns the number of
-// solved PoWs. The computation is complete if 32 PoWs have been found.
-func (rd *RevData) Compute(ctx context.Context, bits int, last uint64) (int, 
uint64) {
-       // set difficulty based on requested number of leading zero-bits
-       difficulty := math.TWO.Pow(512 - bits).Sub(math.ONE)
+// Average number of leading zero-bits in current list
+func (rdc *RevDataCalc) Average() float64 {
+       var sum uint16 = 0
+       for _, num := range rdc.Bits {
+               sum += num
+       }
+       return float64(sum) / 32.
+}
 
-       // initialize a new work record (single PoW computation)
-       work := NewPoWData(0, rd.Timestamp, rd.ZoneKey)
+// Insert a PoW that is "better than the worst" current PoW element.
+func (rdc *RevDataCalc) Insert(pow uint64, bits uint16) (float64, uint16) {
+       if bits > rdc.Bits[rdc.SmallestIdx] {
+               rdc.PoWs[rdc.SmallestIdx] = pow
+               rdc.Bits[rdc.SmallestIdx] = bits
+               rdc.sortBits()
+       }
+       return rdc.Average(), rdc.Bits[rdc.SmallestIdx]
+}
 
-       // work on all PoWs in a revocation data structure; make sure all PoWs
-       // are set to a valid value (that results in a valid compute() result
-       // below a given threshold)
-       for i, pow := range rd.PoWs {
-               // handle "new" pow value: set it to last_pow+1
-               // this ensures a correctly sorted pow list by design.
-               if pow == 0 && last != 0 {
-                       pow, last = last, 0
+// Get the smallest bit position
+func (rdc *RevDataCalc) sortBits() {
+       var (
+               min uint16 = 512
+               pos        = 0
+       )
+       for i, bits := range rdc.Bits {
+               if bits < min {
+                       min = bits
+                       pos = i
                }
-               if pow == 0 && i > 0 {
-                       pow = rd.PoWs[i-1] + 1
+       }
+       rdc.SmallestIdx = byte(pos)
+}
+
+// Compute tries to compute a valid Revocation; it returns the average number
+// of leading zero-bits and the last PoW value tried. The computation is
+// complete if the average above is greater or equal to 'bits'.
+func (rdc *RevDataCalc) Compute(ctx context.Context, bits int, last uint64, cb 
func(float64, uint64)) (float64, uint64) {
+       // find the largest PoW value in current work unit
+       work := NewPoWData(0, rdc.Timestamp, rdc.ZoneKey)
+       var max uint64 = 0
+       for i, pow := range rdc.PoWs {
+               if pow == 0 {
+                       max++
+                       work.SetPoW(max)
+                       res := work.Compute()
+                       rdc.Bits[i] = uint16(512 - res.BitLen())
+               } else if pow > max {
+                       max = pow
                }
-               // prepare for PoW_i
-               work.SetPoW(pow)
+       }
+       // adjust 'last' value
+       if last <= max {
+               last = max + 1
+       }
 
-               // Find PoW value in an (interruptable) loop
-               out := make(chan bool)
-               go func() {
-                       for {
-                               res := work.Compute()
-                               if res.Cmp(difficulty) < 0 {
-                                       break
-                               }
-                               work.Next()
-                       }
-                       out <- true
-               }()
-       loop:
-               for {
-                       select {
-                       case <-out:
-                               rd.PoWs[i] = work.GetPoW()
-                               break loop
-                       case <-ctx.Done():
-                               return i, work.GetPoW() + 1
+       // Find PoW value in an (interruptable) loop
+       out := make(chan bool)
+       go func() {
+               work.SetPoW(last + 1)
+               smallest := rdc.Bits[rdc.SmallestIdx]
+               average := rdc.Average()
+               for average < float64(bits) {
+                       res := work.Compute()
+                       num := uint16(512 - res.BitLen())
+                       if num > smallest {
+                               pow := work.GetPoW()
+                               average, smallest = rdc.Insert(pow, num)
+                               cb(average, pow)
                        }
+                       work.Next()
+               }
+               out <- true
+       }()
+loop:
+       for {
+               select {
+               case <-out:
+                       break loop
+               case <-ctx.Done():
+                       break loop
                }
        }
-       // we have found all valid PoW values.
-       return 32, 0
+       // re-order the PoWs for compliance
+       sort.Slice(rdc.PoWs, func(i, j int) bool { return rdc.PoWs[i] < 
rdc.PoWs[j] })
+       for i, pow := range rdc.PoWs {
+               work.SetPoW(pow)
+               rdc.Bits[i] = uint16(512 - work.Compute().BitLen())
+       }
+       rdc.sortBits()
+       return rdc.Average(), work.GetPoW()
 }
 
-func (rd *RevData) Blob() []byte {
-       blob, err := data.Marshal(rd)
+// Blob returns the binary data structure (wire format).
+func (rdc *RevDataCalc) Blob() []byte {
+       blob, err := data.Marshal(rdc)
        if err != nil {
                return nil
        }
diff --git a/src/gnunet/service/revocation/pow_test.go 
b/src/gnunet/service/revocation/pow_test.go
new file mode 100644
index 0000000..aba07d9
--- /dev/null
+++ b/src/gnunet/service/revocation/pow_test.go
@@ -0,0 +1,132 @@
+package revocation
+
+import (
+       "bytes"
+       "encoding/hex"
+       "fmt"
+       "testing"
+
+       "gnunet/util"
+
+       "github.com/bfix/gospel/crypto/ed25519"
+       "github.com/bfix/gospel/data"
+       "github.com/bfix/gospel/math"
+)
+
+type testData struct {
+       skey    string
+       pkey    string
+       revdata string
+}
+
+var (
+       test_data = []testData{
+               {
+
+                       
"e01d304d45676849edcb36c843ad31837c9de8c7e58028a2e7c2a9894f130b6f", // private 
scalar D
+                       
"d2c825295cfd3073b6149c4393aa9483c51cfaf62731d2bf1127856913233b78", // public 
key
+                       "" +
+                               "0005a5fc192e1d2c" + // timestamp
+                               "0000395d1827c000" + // TTL
+                               "f74d39f9ee9a7344" + // PoW_0
+                               "f74d39f9ee9a7610" +
+                               "f74d39f9ee9a7677" +
+                               "f74d39f9ee9a7774" +
+                               "f74d39f9ee9a777d" +
+                               "f74d39f9ee9a77a3" +
+                               "f74d39f9ee9a77ad" +
+                               "f74d39f9ee9a77b9" +
+                               "f74d39f9ee9a77de" +
+                               "f74d39f9ee9a7851" +
+                               "f74d39f9ee9a786f" +
+                               "f74d39f9ee9a78a3" +
+                               "f74d39f9ee9a78ba" +
+                               "f74d39f9ee9a78ca" +
+                               "f74d39f9ee9a7916" +
+                               "f74d39f9ee9a79a9" +
+                               "f74d39f9ee9a7a37" +
+                               "f74d39f9ee9a7a57" +
+                               "f74d39f9ee9a7a5c" +
+                               "f74d39f9ee9a7a9e" +
+                               "f74d39f9ee9a7ad3" +
+                               "f74d39f9ee9a7b1b" +
+                               "f74d39f9ee9a7b7b" +
+                               "f74d39f9ee9a7b83" +
+                               "f74d39f9ee9a7b8b" +
+                               "f74d39f9ee9a7bbe" +
+                               "f74d39f9ee9a7bcc" +
+                               "f74d39f9ee9a7be6" +
+                               "f74d39f9ee9a7c2b" +
+                               "f74d39f9ee9a7c5b" +
+                               "f74d39f9ee9a7c5f" +
+                               "f74d39f9ee9a7c83" + // PoW_31
+                               
"05b94e2ad6496a8938aaf122f91edbacf2401cce8ec02e551e2a4433e0a76256" + // Sig.R
+                               
"09195bbe7636e9fd9076f8f20bc62467cc8371c487e7809efeaeb6ef7178b623" + // Sig.S
+                               
"d2c825295cfd3073b6149c4393aa9483c51cfaf62731d2bf1127856913233b78", // PKEY
+               },
+       }
+)
+
+func TestRevocationRFC(t *testing.T) {
+
+       for i, td := range test_data {
+               if testing.Verbose() {
+                       fmt.Println("---------------------------------")
+                       fmt.Printf("Test case #%d\n", i+1)
+                       fmt.Println("---------------------------------")
+               }
+
+               // construct private/public key pair from test data
+               skey_d, err := hex.DecodeString(td.skey)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               d := math.NewIntFromBytes(util.Reverse(skey_d))
+               skey := ed25519.NewPrivateKeyFromD(d)
+               pkey_d, err := hex.DecodeString(td.pkey)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if bytes.Compare(skey.Public().Bytes(), pkey_d) != 0 {
+                       t.Fatal("Private/Public key mismatch")
+               }
+
+               // assemble revocation data object
+               rev_d, err := hex.DecodeString(td.revdata)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               revData := new(RevData)
+               if err = data.Unmarshal(revData, rev_d); err != nil {
+                       t.Fatal(err)
+               }
+               if bytes.Compare(revData.ZoneKey, pkey_d) != 0 {
+                       t.Fatal("Wrong zone key in test revocation")
+               }
+
+               // show revdata content
+               if testing.Verbose() {
+                       fmt.Println("REVDATA:")
+                       fmt.Printf("    Timestamp: %s\n", 
revData.Timestamp.String())
+                       fmt.Printf("    TTL: %s\n", revData.TTL.String())
+
+                       work := NewPoWData(0, revData.Timestamp, 
revData.ZoneKey)
+                       for i, pow := range revData.PoWs {
+                               fmt.Printf("    PoW #%d: %d\n", i, pow)
+                               work.SetPoW(pow)
+                               buf := work.Blob()
+                               fmt.Printf("        P: %s\n", 
hex.EncodeToString(buf))
+                               v := work.Compute()
+                               fmt.Printf("        H: %s\n", 
hex.EncodeToString(v.Bytes()))
+                               num := 512 - v.BitLen()
+                               fmt.Printf("        --> %d leading zeros\n", 
num)
+                       }
+                       fmt.Printf("    Signature: %s\n", 
hex.EncodeToString(revData.Signature))
+                       fmt.Printf("    ZoneKey: %s\n", 
hex.EncodeToString(revData.ZoneKey))
+               }
+
+               // verify revocation data object
+               rc := revData.Verify(true)
+               fmt.Printf("REV_Verify (pkey): %d\n", rc)
+       }
+}

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



reply via email to

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