Skip to content

Commit

Permalink
Merge pull request #25 from tablelandnetwork/avichalp/use-ecmh
Browse files Browse the repository at this point in the history
Change hashing scheme to ECMH
  • Loading branch information
avichalp authored Dec 13, 2023
2 parents bc45387 + 4294802 commit 7e2c4e1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 41 deletions.
13 changes: 5 additions & 8 deletions internal/app/uploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import (
"io"
"os"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/sha3"
"github.com/tablelandnetwork/basin-cli/pkg/ecmh"
)

// BasinProviderUploader ...
Expand Down Expand Up @@ -63,28 +62,26 @@ func (bu *BasinUploader) Upload(ctx context.Context, filepath string, progress i

// Signer allows you to sign a big stream of bytes by calling Sum multiple times, then Sign.
type Signer struct {
state crypto.KeccakState
state *ecmh.MultisetHash
privateKey *ecdsa.PrivateKey
}

// NewSigner creates a new signer.
func NewSigner(pk *ecdsa.PrivateKey) *Signer {
return &Signer{
state: sha3.NewLegacyKeccak256().(crypto.KeccakState),
state: ecmh.NewMultisetHash(),
privateKey: pk,
}
}

// Sum updates the hash state with a new chunk.
func (s *Signer) Sum(chunk []byte) {
s.state.Write(chunk)
s.state.Insert(chunk)
}

// Sign signs the internal state.
func (s *Signer) Sign() ([]byte, error) {
var h common.Hash
_, _ = s.state.Read(h[:])
signature, err := crypto.Sign(h.Bytes(), s.privateKey)
signature, err := crypto.Sign(s.state.Bytes(), s.privateKey)
if err != nil {
return []byte{}, fmt.Errorf("sign: %s", err)
}
Expand Down
25 changes: 22 additions & 3 deletions pkg/basinprovider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/tablelandnetwork/basin-cli/internal/app"
basincapnp "github.com/tablelandnetwork/basin-cli/pkg/capnp"
"github.com/tablelandnetwork/basin-cli/pkg/ecmh"
"google.golang.org/grpc/test/bufconn"
)

Expand Down Expand Up @@ -61,7 +62,13 @@ func TestBasinProvider_Upload(t *testing.T) {
)
require.NoError(t, err)
require.Equal(t, filedata1, server.uploads["test.test"][0].bytes)
require.Equal(t, "801fb03a3a34fd9d3ac5445f693df74c822d2e8cfa736191e7919e099931d8a51cd0a62fc67da6d8f0aab4302c18aa0cf381c973a8817b7062805f19d03f88ce00", hex.EncodeToString(server.uploads["test.test"][0].sig)) // nolint
require.Equal(t, "1e75e243758ec30e3bbdfa3c48ec5d1f25eccae3e19b81372b5bb18fff70baed5b16436c07b2cf8963b14657b282ee7675efec88feb0c0b934508fd38be1b48f00", hex.EncodeToString(server.uploads["test.test"][0].sig)) // nolint

// verify signature
h := ecmh.NewMultisetHash()
h.Insert([]byte("hello"))
pubKey := crypto.PubkeyToAddress(privateKey.PublicKey)
crypto.VerifySignature(pubKey.Bytes(), h.Bytes(), server.uploads["test.test"][0].sig)
}

// Upload data 2 on test2.test2
Expand All @@ -71,7 +78,13 @@ func TestBasinProvider_Upload(t *testing.T) {
err := client.Upload(context.Background(), "test2", "test2", uint64(5), buf, app.NewSigner(privateKey), bytes.NewBuffer([]byte{}), app.Timestamp{}) // nolint
require.NoError(t, err)
require.Equal(t, filedata2, server.uploads["test2.test2"][0].bytes)
require.Equal(t, "3ad572a3483971285f3c6dc0e71d234a58543876f98b23183dc4e60008c1a92310f42202858b48ad917588535c2234c85413e124a2dcdd0759df9c555a9f585901", hex.EncodeToString(server.uploads["test2.test2"][0].sig)) // nolint
require.Equal(t, "f58c418ba46fececdd48b7979ca29bc2d200836f2f750e449d67d8c62e23a91a0bfcfbba35773da844bf6afed21cb689ea2b836ee4c88abf15831e6202734fa301", hex.EncodeToString(server.uploads["test2.test2"][0].sig)) // nolint

// verify signature
h := ecmh.NewMultisetHash()
h.Insert([]byte("World"))
pubKey := crypto.PubkeyToAddress(privateKey.PublicKey)
crypto.VerifySignature(pubKey.Bytes(), h.Bytes(), server.uploads["test2.test2"][0].sig)
}

// Upload data 3 on test.test
Expand All @@ -81,7 +94,13 @@ func TestBasinProvider_Upload(t *testing.T) {
err := client.Upload(context.Background(), "test", "test", uint64(5), buf, app.NewSigner(privateKey), bytes.NewBuffer([]byte{}), app.Timestamp{}) // nolint
require.NoError(t, err)
require.Equal(t, filedata3, server.uploads["test.test"][1].bytes)
require.Equal(t, "94dcba2012dd83edf1e379bbdc640e95321ea30d5318e1f5dfd46154603bba4970729b44a71844e3f4e07955dfb529ccf60d31b74a9971649d64fd8c12a32a7d00", hex.EncodeToString(server.uploads["test.test"][1].sig)) // nolint
require.Equal(t, "b0e5f145193a3a53da3cab406058037e96079630c120bd2faa59b545b29c7c060bfc53d7c86b222491d59e361d812c6a36b7f0372abf2bffd0e02aee1c8a731201", hex.EncodeToString(server.uploads["test.test"][1].sig)) // nolint

// verify signature
h := ecmh.NewMultisetHash()
h.Insert([]byte("WORLD"))
pubKey := crypto.PubkeyToAddress(privateKey.PublicKey)
crypto.VerifySignature(pubKey.Bytes(), h.Bytes(), server.uploads["test.test"][1].sig)
}

// check latest 2 deals for test2.test2, should return filedata2
Expand Down
33 changes: 19 additions & 14 deletions pkg/ecmh/ecmh.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ type MultisetHash struct {
// NewMultisetHash creates a new multiset hash.
func NewMultisetHash() *MultisetHash {
p := ristretto.Point{}
// shoud we use SetZero() here? base is the generator
// point
p.SetBase()
p.SetZero()

return &MultisetHash{
accumulator: &p,
Expand All @@ -25,14 +23,20 @@ func (h *MultisetHash) String() string {
return h.accumulator.String()
}

// Insert inserts a new item (point) into the multiset hash.
func (h *MultisetHash) Insert(p *ristretto.Point) {
h.accumulator.Add(h.accumulator, p)
// Bytes returns the byte representation of the multiset hash.
func (h *MultisetHash) Bytes() []byte {
return h.accumulator.Bytes()
}

// InsertAll inserts all items (points) into the multiset hash.
func (h *MultisetHash) InsertAll(ps []*ristretto.Point) {
for _, item := range ps {
// Insert inserts a new item (byte array) into the multiset hash.
func (h *MultisetHash) Insert(item []byte) {
p := ristretto.Point{}
h.accumulator.Add(h.accumulator, p.DeriveDalek(item))
}

// InsertAll inserts all items into the multiset hash.
func (h *MultisetHash) InsertAll(items [][]byte) {
for _, item := range items {
h.Insert(item)
}
}
Expand All @@ -47,14 +51,15 @@ func (h *MultisetHash) Difference(other *MultisetHash) {
h.accumulator.Sub(h.accumulator, other.accumulator)
}

// Remove removes an item (point) from the multiset hash.
func (h *MultisetHash) Remove(p *ristretto.Point) {
h.accumulator.Sub(h.accumulator, p)
// Remove removes an item (byte array) from the multiset hash.
func (h *MultisetHash) Remove(item []byte) {
p := ristretto.Point{}
h.accumulator.Sub(h.accumulator, p.DeriveDalek(item))
}

// RemoveAll removes all items (points) from the multiset hash.
func (h *MultisetHash) RemoveAll(ps []*ristretto.Point) {
for _, item := range ps {
func (h *MultisetHash) RemoveAll(items [][]byte) {
for _, item := range items {
h.Remove(item)
}
}
21 changes: 5 additions & 16 deletions pkg/ecmh/ecmh_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package ecmh

import (
"fmt"
"testing"

"github.com/bwesterb/go-ristretto"
"github.com/stretchr/testify/require"

// Register duckdb driver.
Expand All @@ -25,21 +23,15 @@ func TestECMHInsertRemove(t *testing.T) {
for _, tc := range testCases {
currentHash := NewMultisetHash()
for _, item := range tc.items {
newItem := ristretto.Point{}
currentHash.Insert(newItem.DeriveDalek([]byte(item)))
currentHash.Insert([]byte(item))
}
cr1 := currentHash.String()
fmt.Println("cr1", cr1)

// check if item is in the set?
newItem := ristretto.Point{}
currentHash.Remove(newItem.DeriveDalek([]byte(tc.items[0])))
cr2 := currentHash.String()
fmt.Println("cr2", cr2)
currentHash.Remove([]byte(tc.items[0]))

currentHash.Insert(newItem.DeriveDalek([]byte(tc.items[0])))
currentHash.Insert([]byte(tc.items[0]))
cr3 := currentHash.String()
fmt.Println("cr3", cr3)
require.Equal(t, cr1, cr3)
}
}
Expand All @@ -61,14 +53,12 @@ func TestECMHUnionDiff(t *testing.T) {
for _, tc := range testCases {
currentHash1 := NewMultisetHash()
for _, item := range tc.items1 {
newItem := ristretto.Point{}
currentHash1.Insert(newItem.DeriveDalek([]byte(item)))
currentHash1.Insert([]byte(item))
}

currentHash2 := NewMultisetHash()
for _, item := range tc.items2 {
newItem := ristretto.Point{}
currentHash2.Insert(newItem.DeriveDalek([]byte(item)))
currentHash2.Insert([]byte(item))
}

currentHash1.Union(currentHash2)
Expand All @@ -78,7 +68,6 @@ func TestECMHUnionDiff(t *testing.T) {

currentHash1.Union(currentHash2)
cr3 := currentHash1.String()
fmt.Println("cr3", cr3)
require.Equal(t, cr1, cr3)
}
}

0 comments on commit 7e2c4e1

Please sign in to comment.