Skip to content

Commit

Permalink
crypto: add nil check, hashtimelock serialize test
Browse files Browse the repository at this point in the history
  • Loading branch information
Rjected committed Nov 24, 2019
1 parent 97ea50e commit c578b4d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 19 deletions.
31 changes: 28 additions & 3 deletions crypto/hashtimelock/hashtimelock.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,43 @@ type HashTimelock struct {
TimeToRun uint64
}

func (ht *HashTimelock) setupHashPuzzle(seed []byte, hashFunction hash.Hash) {
func (ht *HashTimelock) setupHashPuzzle(seed []byte, hashFunction hash.Hash) (err error) {
if hashFunction == nil {
err = fmt.Errorf("Error, annot create new timelock puzzle with nil hash function")
return
}
ht.TimelockSeed = seed
ht.hashFunction = hashFunction
return
}

// New creates a new hash timelock with seed bytes and a hash function
func New(seed []byte, hashFunction hash.Hash) (hashTimelock crypto.Timelock) {
func New(seed []byte, hashFunction hash.Hash) (hashTimelock crypto.Timelock, err error) {
if hashFunction == nil {
err = fmt.Errorf("Error, annot create new timelock puzzle with nil hash function")
return
}
ht := &HashTimelock{}
ht.setupHashPuzzle(seed, hashFunction)
if err = ht.setupHashPuzzle(seed, hashFunction); err != nil {
err = fmt.Errorf("Error setting up hash puzzle while creating a timelock: %s", err)
return
}
hashTimelock = ht
return
}

// SetHashFunction sets the hash function for the timelock puzzle
func (ht *HashTimelock) SetHashFunction(hashFunction hash.Hash) {
ht.hashFunction = hashFunction
return
}

// SetupTimelockPuzzle sends key k to the future in time t, returning a puzzle based on sequential hashing and an answer
func (ht *HashTimelock) SetupTimelockPuzzle(t uint64) (puzzle crypto.Puzzle, answer []byte, err error) {
if ht.hashFunction == nil {
err = fmt.Errorf("Error, hash function is nil, cannot setup timelock puzzle")
return
}
ht.TimeToRun = t
answer = make([]byte, ht.hashFunction.Size())

Expand All @@ -52,6 +73,10 @@ func (ht *HashTimelock) SetupTimelockPuzzle(t uint64) (puzzle crypto.Puzzle, ans

// Solve solves the hash puzzle and returns the answer, or fails
func (ht *HashTimelock) Solve() (answer []byte, err error) {
if ht.hashFunction == nil {
err = fmt.Errorf("Error, hash function is nil, cannot setup timelock puzzle")
return
}
answer = make([]byte, ht.hashFunction.Size())
copy(answer[:], ht.TimelockSeed)
for i := uint64(0); i < ht.TimeToRun; i++ {
Expand Down
71 changes: 56 additions & 15 deletions crypto/hashtimelock/hashtimelock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package hashtimelock

import (
"bytes"
"crypto/rand"
"crypto/sha256"
"testing"

"github.com/btcsuite/fastsha256"
"github.com/dchest/siphash"
"github.com/minio/highwayhash"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/sha3"
)

// TestZeroTimeSHA256 is a very useful test
Expand All @@ -17,7 +19,7 @@ func TestZeroTimeSHA256(t *testing.T) {
copy(seed[:], []byte("opencxzero"))
hashFunction := sha256.New()
// eh this whole New thing looks bad but really it'll look like hashtimelock.New(seed, hfunc) anyways which is a really nice way to do it so this will be good actually
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(0)
// throw away the answer because we already know what it's supposed to be: the seed
puzzle, _, err := hashPuzzle.SetupTimelockPuzzle(time)
Expand All @@ -39,7 +41,7 @@ func TestOneTimeSHA256(t *testing.T) {
copy(seed[:], []byte("opencxone"))
hashFunction := sha256.New()
// eh this whole New thing looks bad but really it'll look like hashtimelock.New(seed, hfunc) anyways which is a really nice way to do it so this will be good actually
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(1)
// throw away the answer because we already know what it's supposed to be: the seed
puzzle, _, err := hashPuzzle.SetupTimelockPuzzle(time)
Expand Down Expand Up @@ -71,7 +73,7 @@ func TestTenTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxten"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(10)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -90,7 +92,7 @@ func TestHundredTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxhundred"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -109,7 +111,7 @@ func TestThousandTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxthousand"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(1000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -127,7 +129,7 @@ func TestTenThousandTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxtenthousand"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(10000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -146,7 +148,7 @@ func TestHundredThousandTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxhundredthousand"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -166,7 +168,7 @@ func TestMillionTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxmillion"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(1000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -185,7 +187,7 @@ func TestTenMillionTimeSHA256(t *testing.T) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxtenmillion"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(10000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -204,7 +206,7 @@ func BenchmarkHundredMillionTimeSHA256(b *testing.B) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxhundredmillion"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -224,7 +226,7 @@ func BenchmarkHundredMillionTimeFastSHA256(b *testing.B) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxhundredmillion"))
hashFunction := fastsha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -249,7 +251,7 @@ func BenchmarkHundredMillionTimeBlake2B(b *testing.B) {
if err != nil {
b.Fatalf("Could not set up blake2b: %s\n", err)
}
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -269,7 +271,7 @@ func BenchmarkHundredMillionTimeSipHash(b *testing.B) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxhundredmillion"))
hashFunction := siphash.New(seed)
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -292,7 +294,7 @@ func BenchmarkHundredMillionTimeHighwayHash(b *testing.B) {
if err != nil {
b.Fatalf("Could not create highwayhash: %s\n", err)
}
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(100000000)
puzzle, expectedAns, err := hashPuzzle.SetupTimelockPuzzle(time)
if err != nil {
Expand All @@ -312,7 +314,7 @@ func BenchmarkBillionTimeSHA256(b *testing.B) {
seed := make([]byte, 32)
copy(seed[:], []byte("opencxbillion"))
hashFunction := sha256.New()
hashPuzzle := New(seed, hashFunction)
hashPuzzle, _ := New(seed, hashFunction)
time := uint64(1000000000)

// so we solve it once here, this can take some time
Expand All @@ -330,3 +332,42 @@ func BenchmarkBillionTimeSHA256(b *testing.B) {
b.Fatalf("Answer did not equal puzzle for time = 0. Expected %x, got %x\n", expectedAns, puzzleAns)
}
}

// TestHashTimelockSerialize tests that a hash timelock, when
// serialized and deserialized with gob, doesn't change
func TestHashTimelockSerialize(t *testing.T) {
var err error
tlSeed := [32]byte{}
if _, err = rand.Read(tlSeed[:]); err != nil {
t.Errorf("Error reading bytes to seed for hashtimelock serialize: %s", err)
return
}
htl := &HashTimelock{
TimelockSeed: tlSeed[:],
TimeToRun: uint64(10000),
}
htl.SetHashFunction(sha3.New256())
var timelockBytes []byte
if timelockBytes, err = htl.Serialize(); err != nil {
t.Errorf("Error, this is a valid hashtimelock, serialize should not return an error: %s", err)
return
}

finalHtlPtr := new(HashTimelock)
if err = finalHtlPtr.Deserialize(timelockBytes); err != nil {
t.Errorf("Error, deserialization should work for bytes that were just serialized: %s", err)
return
}

if finalHtlPtr.TimeToRun != htl.TimeToRun {
t.Errorf("TimeToRun for resulting struct is %d but should have been %d", finalHtlPtr.TimeToRun, htl.TimeToRun)
return
}

if bytes.Compare(finalHtlPtr.TimelockSeed, htl.TimelockSeed) != 0 {
t.Errorf("TimelockSeed for resulting struct is %8x but should be %8x", finalHtlPtr.TimelockSeed, htl.TimelockSeed)
return
}

return
}
5 changes: 4 additions & 1 deletion crypto/timelockencoders/blockciphers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import (
func createSHAPuzzle(t uint64, key []byte) (puzzle crypto.Puzzle, anskey []byte, err error) {
// Set up what the puzzle will encrypt
var timelock crypto.Timelock
timelock = hashtimelock.New(key, sha256.New())
if timelock, err = hashtimelock.New(key, sha256.New()); err != nil {
err = fmt.Errorf("Error creating new hash timelock for SHA256 puzzle: %s", err)
return
}

// Set up the puzzle to send
if puzzle, anskey, err = timelock.SetupTimelockPuzzle(t); err != nil {
Expand Down

0 comments on commit c578b4d

Please sign in to comment.