Skip to content

Commit

Permalink
Improvements and fixes
Browse files Browse the repository at this point in the history
- Fix to SSTDEG Read never return EOF.
- Relaxed random standard deviation to 50 (SSTDEG).
- Improvement to ReadAggr Read try to read from each source until return required bytes.
- Improvement to Salter try to read from source until return required bytes when creating a new token.
- Added a new test Bash script.
- Added a new file to keep track of benchmark results.
  • Loading branch information
skarllot committed Jan 25, 2016
1 parent 161fa84 commit b2db4c8
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 39 deletions.
3 changes: 3 additions & 0 deletions bench_result.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BenchmarkSalter-4 200000 10109 ns/op 672 B/op 9 allocs/op
BenchmarkSSTDEG-4 20000 96517 ns/op 3655 B/op 57 allocs/op
BenchmarkSSTDEGWait-4 30000 81137 ns/op 3053 B/op 47 allocs/op
4 changes: 2 additions & 2 deletions randomaggr.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ func (s *RandomAggr) Read(b []byte) (n int, err error) {

for _, v := range s.sources {
count := int(float32(remainder) * (float32(v.Weight) / float32(sumWeight)))
n, err = v.Reader.Read(b[pos : pos+count])
if err != nil {
n, err = io.ReadFull(v.Reader, b[pos:pos+count])
if err != nil && err != io.ErrUnexpectedEOF {
return
}

Expand Down
25 changes: 15 additions & 10 deletions randomaggr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package crypt

import (
"io"
"testing"
)

Expand All @@ -38,16 +39,20 @@ type LimitedSource struct {
}

func (s *LimitedSource) Read(b []byte) (int, error) {
if s.size <= 0 {
return 0, io.EOF
}

counter := 0

for i := range b {
if s.size <= 0 {
return counter, nil
}

b[i] = byte(s.val)
s.size--
counter++

if s.size <= 0 {
return counter, nil
}
}

return counter, nil
Expand Down Expand Up @@ -76,7 +81,7 @@ func TestRandomAggrDistribution(t *testing.T) {
buf := make([]byte, 100)
n, err := rnd.Read(buf)
if err != nil {
t.Errorf("Error reading from aggregation: %v", err)
t.Fatalf("Error reading from aggregation: %v", err)
}
if n != len(buf) {
t.Errorf("Should fill entire buffer: read %d bytes", n)
Expand All @@ -97,7 +102,7 @@ func TestRandomAggrDistribution2(t *testing.T) {
buf := make([]byte, 100)
n, err := rnd.Read(buf)
if err != nil {
t.Errorf("Error reading from aggregation: %v", err)
t.Fatalf("Error reading from aggregation: %v", err)
}
if n != len(buf) {
t.Errorf("Should fill entire buffer: read %d bytes", n)
Expand All @@ -118,7 +123,7 @@ func TestRandomAggrInsufficient(t *testing.T) {
buf := make([]byte, 100)
n, err := rnd.Read(buf)
if err != nil {
t.Errorf("Error reading from aggregation: %v", err)
t.Fatalf("Error reading from aggregation: %v", err)
}
if n != 60 {
t.Errorf("Should read 60 bytes: read %d bytes", n)
Expand All @@ -140,7 +145,7 @@ func TestRandomAggrWeight(t *testing.T) {
buf := make([]byte, 10+8+3)
n, err := rnd.Read(buf)
if err != nil {
t.Errorf("Error reading from aggregation: %v", err)
t.Fatalf("Error reading from aggregation: %v", err)
}
if n != len(buf) {
t.Errorf("Should fill entire buffer: read %d bytes", n)
Expand All @@ -160,7 +165,7 @@ func TestRandomAggrRepeatingDecimal(t *testing.T) {
buf := make([]byte, 9)
n, err := rnd.Read(buf)
if err != nil {
t.Errorf("Error reading from aggregation: %v", err)
t.Fatalf("Error reading from aggregation: %v", err)
}
if n != len(buf) {
t.Errorf("Should fill entire buffer: read %d bytes", n)
Expand All @@ -179,7 +184,7 @@ func TestRandomAggrRepeatingDecimal2(t *testing.T) {
buf := make([]byte, 10)
n, err := rnd.Read(buf)
if err != nil {
t.Errorf("Error reading from aggregation: %v", err)
t.Fatalf("Error reading from aggregation: %v", err)
}
if n != len(buf) {
t.Errorf("Should fill entire buffer: read %d bytes", n)
Expand Down
5 changes: 1 addition & 4 deletions salter.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,10 @@ func (s *Salter) BToken(size int) ([]byte, error) {
mac := hmac.New(sha256.New, s.salt)
buf := make([]byte, size)

n, err := s.rnd.Read(buf)
_, err := io.ReadFull(s.rnd, buf)
if err != nil {
return nil, err
}
if n != size {
return nil, io.ErrUnexpectedEOF
}

mac.Write(buf)
macSum := mac.Sum(nil)
Expand Down
1 change: 0 additions & 1 deletion sstdeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ func (s *SSTDEG) Read(b []byte) (n int, err error) {
var chunk []byte
if len(b) > defaultPoolSize {
chunk = b[:defaultPoolSize]
err = io.EOF
} else {
chunk = b
}
Expand Down
47 changes: 25 additions & 22 deletions sstdeg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ import (

const (
TestingRounds = 1000
PredictabilityThreshold = .05
MinimumStandardDeviation = 65.0
MaximumDups = .05
MinimumStandardDeviation = 50.0
)

func testUnpred(r io.Reader) (int, float64) {
func testUnpred(r io.Reader) (float64, float64) {
dict := make(map[int16]bool)
buff := make([]byte, 2)
count := 0
Expand All @@ -52,16 +52,17 @@ func testUnpred(r io.Reader) (int, float64) {
prob.Update(float64(buff[1]))
}

return count, prob.PopulationStandardDeviation()
return float64(count) / float64(TestingRounds),
prob.PopulationStandardDeviation()
}

func TestSystemUnpredictability(t *testing.T) {
count, stddev := testUnpred(rand.Reader)
dups, stddev := testUnpred(rand.Reader)

if count > TestingRounds*PredictabilityThreshold {
if dups > MaximumDups {
t.Errorf(
"System random generator: %d dups of %d",
count, TestingRounds)
int(TestingRounds*dups), TestingRounds)
}
if stddev < MinimumStandardDeviation {
t.Errorf(
Expand All @@ -70,19 +71,19 @@ func TestSystemUnpredictability(t *testing.T) {
}
t.Logf(
"System random generator: %.2f%% dups/%.2f STDDEV",
(float32(count)/float32(TestingRounds))*100, stddev)
dups*100, stddev)
}

func TestSSTDEGUnpredictability(t *testing.T) {
rnd := NewSSTDEG()
defer rnd.Close()

count, stddev := testUnpred(rnd)
dups, stddev := testUnpred(rnd)

if count > TestingRounds*PredictabilityThreshold {
if dups > MaximumDups {
t.Errorf(
"SSTDEG random generator: %d dups of %d",
count, TestingRounds)
int(TestingRounds*dups), TestingRounds)
}
if stddev < MinimumStandardDeviation {
t.Errorf(
Expand All @@ -91,7 +92,7 @@ func TestSSTDEGUnpredictability(t *testing.T) {
}
t.Logf(
"SSTDEG random generator: %.2f%% dups/%.2f STDDEV",
(float32(count)/float32(TestingRounds))*100, stddev)
dups*100, stddev)
}

func TestSSTDEGFillEntropyBuffer(t *testing.T) {
Expand All @@ -108,11 +109,12 @@ func BenchmarkSSTDEG(b *testing.B) {
buff := make([]byte, b.N)
b.ResetTimer()

n, err := rnd.Read(buff)
idx := n - 1
for err == io.EOF {
n, err = rnd.Read(buff[idx:])
idx += n - 1
n, err := io.ReadFull(rnd, buff)
if err != nil {
b.Fatalf("Error reading SSTDEG: %v", err)
} else if n < len(buff) {
b.Fatalf("Error reading SSTDEG: should read %d bytes but read %d",
len(buff), n)
}

b.StopTimer()
Expand All @@ -128,11 +130,12 @@ func BenchmarkSSTDEGWait(b *testing.B) {
}
b.ResetTimer()

n, err := rnd.Read(buff)
idx := n - 1
for err == io.EOF {
n, err = rnd.Read(buff[idx:])
idx += n - 1
n, err := io.ReadFull(rnd, buff)
if err != nil {
b.Fatalf("Error reading SSTDEG: %v", err)
} else if n < len(buff) {
b.Fatalf("Error reading SSTDEG: should read %d bytes but read %d",
len(buff), n)
}

b.StopTimer()
Expand Down
8 changes: 8 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

go test -v --race ./...
go test -v ./...
test -z "$(gofmt -s -l -w . | tee /dev/stderr)"
test -z "$(golint ./... | tee /dev/stderr)"
go vet ./...
go test -bench . -benchmem ./... | grep "Benchmark" > bench_result.txt

0 comments on commit b2db4c8

Please sign in to comment.