gnunet-go

GNUnet Bindings for Go
Log | Files | Refs | README | LICENSE

commit 3d0b7cab3e273dd2f3f3d8990fb868b93b6b3f95
parent db7da66be57c6a9df87f3ea1f3cd681539ad9b51
Author: Bernd Fix <brf@hoi-polloi.org>
Date:   Wed,  1 Apr 2020 21:53:16 +0200

Adjusted revocation PoW to draft specification.

Diffstat:
Msrc/cmd/pow-test/main.go | 9++++++---
Msrc/gnunet/service/context.go | 34++++++++++++++++++++++------------
Msrc/gnunet/service/revocation/pow.go | 32++++++++++++++++----------------
3 files changed, 44 insertions(+), 31 deletions(-)

diff --git a/src/cmd/pow-test/main.go b/src/cmd/pow-test/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/hex" "flag" "fmt" "log" @@ -19,7 +20,11 @@ func main() { flag.IntVar(&bits, "b", 25, "Number of leading zero bits") flag.BoolVar(&quiet, "q", false, "Be quiet") flag.Parse() + + // pre-set difficulty fmt.Printf("Leading zeros required: %d\n", bits) + difficulty := math.TWO.Pow(512 - bits).Sub(math.ONE) + fmt.Printf("==> Difficulty: %v\n", difficulty) // generate a random key pair pkey, _ := ed25519.NewKeypair() @@ -27,9 +32,6 @@ func main() { // 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() @@ -45,4 +47,5 @@ func main() { } fmt.Printf("PoW found after %d iterations:\n", count) fmt.Printf("--> Nonce=%d\n", rd.GetNonce()) + fmt.Printf(" REV = %s\n", hex.EncodeToString(rd.GetBlob())) } diff --git a/src/gnunet/service/context.go b/src/gnunet/service/context.go @@ -30,28 +30,38 @@ import ( // by a service; the session is handled by the 'ServeClient' method of a // service implementation. type SessionContext struct { - Id int // session identifier - wg *sync.WaitGroup // wait group for the session - sig *concurrent.Signaller // signaller for the session - pending int // number of pending go-routines + Id int // session identifier + wg *sync.WaitGroup // wait group for the session + sig *concurrent.Signaller // signaller for the session + pending int // number of pending go-routines + active bool // is the context active (un-cancelled)? + onCancel *sync.Mutex // only run one Cancel() at a time } // NewSessionContext instantiates a new session context. func NewSessionContext() *SessionContext { return &SessionContext{ - Id: util.NextID(), - wg: new(sync.WaitGroup), - sig: concurrent.NewSignaller(), - pending: 0, + Id: util.NextID(), + wg: new(sync.WaitGroup), + sig: concurrent.NewSignaller(), + pending: 0, + active: true, + onCancel: new(sync.Mutex), } } // Cancel all go-routines associated with this context. func (ctx *SessionContext) Cancel() { - // send signal to terminate... - ctx.sig.Send(true) - // wait for session go-routines to finish - ctx.wg.Wait() + ctx.onCancel.Lock() + if ctx.active { + // we are going out-of-business + ctx.active = false + // send signal to terminate... + ctx.sig.Send(true) + // wait for session go-routines to finish + ctx.wg.Wait() + } + ctx.onCancel.Unlock() } // Add a go-routine to the wait group. diff --git a/src/gnunet/service/revocation/pow.go b/src/gnunet/service/revocation/pow.go @@ -20,12 +20,12 @@ package revocation import ( "bytes" + "crypto/cipher" "crypto/sha256" "crypto/sha512" "encoding/binary" "sync" - "gnunet/crypto" "gnunet/util" "github.com/bfix/gospel/crypto/ed25519" @@ -33,6 +33,7 @@ import ( "github.com/bfix/gospel/math" "golang.org/x/crypto/hkdf" "golang.org/x/crypto/scrypt" + "golang.org/x/crypto/twofish" ) //---------------------------------------------------------------------- @@ -73,6 +74,11 @@ func (r *RevData) GetNonce() uint64 { return r.Nonce } +// GetBlob returns the binary representation of RevData +func (r *RevData) GetBlob() []byte { + return r.blob +} + // Next selects the next nonce to be tested. func (r *RevData) Next() { var incr func(pos int) @@ -91,33 +97,27 @@ func (r *RevData) Next() { 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) + k, err := scrypt.Key(r.blob, []byte("gnunet-revocation-proof-of-work"), 2, 8, 2, 32) 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!")) + iv := make([]byte, 16) + prk := hkdf.Extract(sha512.New, k, []byte("gnunet-proof-of-work-iv")) 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) + rdr.Read(iv) - // perform encryption - enc, err := crypto.SymmetricEncrypt(r.blob, skey, iv) + // Encrypt with Twofish CFB stream cipher + out := make([]byte, len(r.blob)) + tf, err := twofish.NewCipher(k) if err != nil { return nil, err } + cipher.NewCFBEncrypter(tf, iv).XORKeyStream(out, r.blob) // compute result - result, err := scrypt.Key(enc, []byte("gnunet-revocation-proof-of-work"), 2, 8, 2, 64) + result, err := scrypt.Key(out, []byte("gnunet-revocation-proof-of-work"), 2, 8, 2, 64) return math.NewIntFromBytes(result), nil }