Skip to content

Commit

Permalink
add purb'd unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jbsv committed Nov 17, 2023
1 parent 2da026a commit 34cc2eb
Show file tree
Hide file tree
Showing 7 changed files with 560 additions and 102 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require (
github.com/stretchr/testify v1.8.4
go.dedis.ch/dela v0.0.0-20231011144949-4677467c030c
go.dedis.ch/kyber/v3 v3.1.1-0.20231024084410-31ea167adbbb
go.dedis.ch/libpurb v0.0.0-20231107160354-ffba29c17caf
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
go.dedis.ch/libpurb v0.0.0-20231108133532-c70e1b84b632
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
)

Expand All @@ -32,7 +32,7 @@ require (
go.dedis.ch/fixbuf v1.0.3 // indirect
go.etcd.io/bbolt v1.3.5 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/sys v0.14.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,16 @@ go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
go.dedis.ch/kyber/v3 v3.1.1-0.20231024084410-31ea167adbbb h1:G7GmitWgVMlkBaSzHJJo05bydYhLFCSPzKwCHTwf3NM=
go.dedis.ch/kyber/v3 v3.1.1-0.20231024084410-31ea167adbbb/go.mod h1:nL0a5f3E//lnOCKumtzMmb8qzykxOVsihqp8C1Eb5rc=
go.dedis.ch/libpurb v0.0.0-20231107160354-ffba29c17caf h1:kNjCdcUbtc4+ANLZWApokLVzkHuW1NPxb4fNpGzFjBY=
go.dedis.ch/libpurb v0.0.0-20231107160354-ffba29c17caf/go.mod h1:XCi40g75txGSLusqJOanJytpkxiQLJzRb9RRV9UN2p4=
go.dedis.ch/libpurb v0.0.0-20231108133532-c70e1b84b632 h1:e3rOQfoyJm6ywIbuBcRwoKdWSUsPmcW9qdHO47dOmyc=
go.dedis.ch/libpurb v0.0.0-20231108133532-c70e1b84b632/go.mod h1:XCi40g75txGSLusqJOanJytpkxiQLJzRb9RRV9UN2p4=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -134,8 +134,8 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
Expand Down
55 changes: 28 additions & 27 deletions store/kv/blob.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Blob is a wrapper around libpurb.Purb
package kv

import (
Expand All @@ -9,39 +10,31 @@ import (
"go.dedis.ch/kyber/v3/util/random"
)

type Blob struct {
purb *libpurb.Purb
}
const numberOfRecipients = 1

// NewBlob creates a new blob
func NewBlob() *Blob {
suitesInfo := getSuiteInfo()
simplified := true

func NewBlob(keypair []key.Pair) *libpurb.Purb {
p := libpurb.NewPurb(
suitesInfo,
simplified,
getSuiteInfo(),
false,
random.New(),
)
p.Recipients = createRecipients(keypair)

p.Recipients = createRecipients(1)

return &Blob{
purb: p,
}
return p
}

// Encode encodes a slice of bytes into a blob
func (b *Blob) Encode(data []byte) ([]byte, error) {
err := b.purb.Encode(data)
blob := b.purb.ToBytes()
func Encode(purb *libpurb.Purb, data []byte) ([]byte, error) {
err := purb.Encode(data)
blob := purb.ToBytes()

return blob, err
}

// Decode decodes a blob into a slice of bytes
func (b *Blob) Decode(blob []byte) ([]byte, error) {
success, decrypted, err := b.purb.Decode(blob)
func Decode(purb *libpurb.Purb, blob []byte) ([]byte, error) {
success, decrypted, err := purb.Decode(blob)

if !success {
err = xerrors.Errorf("Failed to decrypt blob: %v", err)
Expand Down Expand Up @@ -71,19 +64,27 @@ func getSuiteInfo() libpurb.SuiteInfoMap {
}

// see example in libpurb
func createRecipients(n int) []libpurb.Recipient {
decs := make([]libpurb.Recipient, 0)
func createRecipients(keypair []key.Pair) []libpurb.Recipient {
r := make([]libpurb.Recipient, 0)
suites := []libpurb.Suite{curve25519.NewBlakeSHA256Curve25519(true)}

if len(keypair) < numberOfRecipients {
keypair = make([]key.Pair, 0)
}

for _, suite := range suites {
for i := 0; i < n; i++ {
pair := key.NewKeyPair(suite)
decs = append(decs, libpurb.Recipient{
for i := 0; i < numberOfRecipients; i++ {
if len(keypair) < numberOfRecipients {
keypair = append(keypair, *key.NewKeyPair(suite))
}

r = append(r, libpurb.Recipient{
SuiteName: suite.String(),
Suite: suite,
PublicKey: pair.Public,
PrivateKey: pair.Private,
PublicKey: keypair[i].Public,
PrivateKey: keypair[i].Private,
})
}
}
return decs
return r
}
126 changes: 86 additions & 40 deletions store/kv/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package kv
import (
"bytes"
"encoding/gob"
"fmt"
"errors"
"io"
"os"
"sync"

"go.dedis.ch/kyber/v3/util/key"
"go.dedis.ch/libpurb/libpurb"
"golang.org/x/xerrors"
)

Expand All @@ -27,47 +30,70 @@ func newBucketDb() bucketDb {
//
// - implements kv.DB
type purbDB struct {
dbFilePath string
db bucketDb
purbIsOn bool
blob *Blob
dbFile string
bucketDb bucketDb
blob *libpurb.Purb
purbIsOn bool
}

// NewDB opens a new database to the given file.
func NewDB(path string, purbIsOn bool) (DB, error) {
func NewDB(path string, purbIsOn bool) (DB, []key.Pair, error) {
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
return nil, xerrors.Errorf("failed to open DB file: %v", err)
return nil, nil, xerrors.Errorf("failed to open DB file: %v", err)
}
defer f.Close()

stats, _ := f.Stat()
s := stats.Size()
if s > 0 {
return nil, nil, xerrors.New("failed to create DB file: file already exists")
}

var data = make([]byte, s)
l, err := f.Read(data)
if int64(l) < s || err != nil {
return nil, xerrors.Errorf("failed to read DB file: %v", err)
if int64(l) != 0 || err != nil {
return nil, nil, xerrors.Errorf("failed to read DB file: %v", err)
}

var b *libpurb.Purb = nil
keypair := make([]key.Pair, 0)
if purbIsOn {
b = NewBlob(nil)
pair := key.Pair{
Public: b.Recipients[0].PublicKey,
Private: b.Recipients[0].PrivateKey,
}
keypair = append(keypair, pair)
}

p := &purbDB{
dbFilePath: path,
db: newBucketDb(),
purbIsOn: purbIsOn,
blob: NewBlob(),
dbFile: path,
bucketDb: newBucketDb(),
purbIsOn: purbIsOn,
blob: b,
}

buffer := bytes.NewBuffer(data)
return p, keypair, nil
}

// LoadDB opens a database from a given file.
func LoadDB(path string, purbIsOn bool, keypair []key.Pair) (DB, error) {
var b *libpurb.Purb = nil
if purbIsOn {
decrypted, err := p.blob.Decode(data)
if err != nil {
return nil, err
}
buffer.Write(decrypted)
b = NewBlob(keypair)
}

err = p.deserialize(buffer)
if fmt.Sprint(err) != "EOF" {
return nil, xerrors.Errorf("failed to initialize new DB file: %v", err)
p := &purbDB{
dbFile: path,
bucketDb: newBucketDb(),
purbIsOn: purbIsOn,
blob: b,
}

err := p.load()
if err != nil {
return nil, err
}

return p, nil
Expand All @@ -76,7 +102,7 @@ func NewDB(path string, purbIsOn bool) (DB, error) {
// View implements kv.DB. It executes the read-only transaction in the context
// of the database.
func (p *purbDB) View(fn func(ReadableTx) error) error {
tx := &dpTx{db: p.db, new: newBucketDb()}
tx := &dpTx{db: p.bucketDb, new: newBucketDb()}

Check failure on line 105 in store/kv/db.go

View workflow job for this annotation

GitHub Actions / lint

copylocks: literal copies lock value from p.bucketDb: go.dedis.ch/purb-db/store/kv.bucketDb (govet)

err := fn(tx)

Expand All @@ -90,21 +116,20 @@ func (p *purbDB) View(fn func(ReadableTx) error) error {
// Update implements kv.DB. It executes the writable transaction in the context
// of the database.
func (p *purbDB) Update(fn func(WritableTx) error) error {
tx := &dpTx{db: p.db, new: newBucketDb()}
tx := &dpTx{db: p.bucketDb, new: newBucketDb()}

Check failure on line 119 in store/kv/db.go

View workflow job for this annotation

GitHub Actions / lint

copylocks: literal copies lock value from p.bucketDb: go.dedis.ch/purb-db/store/kv.bucketDb (govet)

err := fn(tx)
if err != nil {
return err
}

p.db.Lock()
p.bucketDb.Lock()
for k, v := range tx.new.Db {
p.db.Db[k] = v
p.bucketDb.Db[k] = v
}
p.bucketDb.Unlock()

p.db.Unlock()

err = p.savePurbified()
err = p.save()
if err != nil {
return err
}
Expand All @@ -125,46 +150,67 @@ func (p *purbDB) Close() error {
// ---------------------------------------------------------------------------
// helper functions

func (p *purbDB) serialize() (bytes.Buffer, error) {
func (p *purbDB) serialize() (*bytes.Buffer, error) {
var data bytes.Buffer
encoder := gob.NewEncoder(&data)

p.db.RLock()
defer p.db.RUnlock()
err := encoder.Encode(p.db)
return data, err
p.bucketDb.RLock()
defer p.bucketDb.RUnlock()
err := encoder.Encode(p.bucketDb.Db)
return &data, err
}

func (p *purbDB) deserialize(input *bytes.Buffer) error {
decoder := gob.NewDecoder(input)

err := decoder.Decode(&p.db)
err := decoder.Decode(&p.bucketDb.Db)

for _, x := range p.db.Db {
for _, x := range p.bucketDb.Db {
x.updateIndex()
}

return err
}

func (p *purbDB) savePurbified() error {
func (p *purbDB) save() error {
data, err := p.serialize()
if err != nil {
return xerrors.Errorf("failed to serialize DB file: %v", err)
}

if p.purbIsOn {
blob, err := p.blob.Encode(data.Bytes())
blob, err := Encode(p.blob, data.Bytes())
if err != nil {
return xerrors.Errorf("failed to purbify DB file: %v", err)
}
data.Write(blob)
data = bytes.NewBuffer(blob)
}

err = os.WriteFile(p.dbFilePath, data.Bytes(), 0755)
err = os.WriteFile(p.dbFile, data.Bytes(), 0755)
if err != nil {
return xerrors.Errorf("failed to save DB file: %v", err)
}

return nil
}

func (p *purbDB) load() error {
data, err := os.ReadFile(p.dbFile)
if err != nil {
return xerrors.Errorf("failed to load DB from file: %v", err)
}

if p.purbIsOn && len(data) > 0 {
data, err = Decode(p.blob, data)
if err != nil {
return xerrors.Errorf("failed to decode purbified DB file: %v", err)
}
}

buffer := bytes.NewBuffer(data)
err = p.deserialize(buffer)
if err != nil && errors.Is(err, io.EOF) {
return nil
}
return err
}
Loading

0 comments on commit 34cc2eb

Please sign in to comment.