add transcript RNG

This commit is contained in:
vedhavyas 2020-01-19 16:26:08 +01:00
parent 8318aed1a7
commit 6b336b58be
No known key found for this signature in database
GPG Key ID: 317BF0923E3EB7E5
4 changed files with 114 additions and 1 deletions

5
go.mod
View File

@ -2,4 +2,7 @@ module github.com/gtank/merlin
go 1.12
require github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643
require (
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643
github.com/stretchr/testify v1.4.0
)

9
go.sum
View File

@ -1,2 +1,11 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -2,6 +2,7 @@ package merlin
import (
"encoding/binary"
"io"
"github.com/mimoo/StrobeGo/strobe"
)
@ -60,3 +61,48 @@ func (t *Transcript) ExtractBytes(label []byte, outLen int) []byte {
outBytes := t.s.PRF(outLen)
return outBytes
}
// BuildRNG returns the TranscriptRNG with the strbe state cloned.
func (t *Transcript) BuildRNG() *TranscriptRNG {
s := t.s.Clone()
return &TranscriptRNG{s: *s}
}
type TranscriptRNG struct {
s strobe.Strobe
}
// ReKeyWithWitnessBytes rekeys the transcript with witness data.
func (t *TranscriptRNG) ReKeyWithWitnessBytes(label, witness []byte) *TranscriptRNG {
sizeBuffer := make([]byte, 4)
binary.LittleEndian.PutUint32(sizeBuffer[0:], uint32(len(witness)))
// The StrobeGo API does not support continuation operations,
// so we have to pass the label and length as a single buffer.
// Otherwise it will record two meta-AD operations instead of one.
labelSize := append(label, sizeBuffer...)
t.s.AD(true, labelSize)
t.s.KEY(witness)
return t
}
// Finalize uses the supplied rng to re key the transcript.
func (t *TranscriptRNG) Finalize(rng io.Reader) (*TranscriptRNG, error) {
var randBytes [32]byte
_, err := rng.Read(randBytes[:])
if err != nil {
return nil, err
}
t.s.AD(true, []byte("rng"))
t.s.KEY(randBytes[:])
return t, nil
}
// RandomBytes returns random n bytes from the transcript.
func (t *TranscriptRNG) RandomBytes(outLen int) []byte {
sizeBuffer := make([]byte, 4)
binary.LittleEndian.PutUint32(sizeBuffer[0:], uint32(outLen))
t.s.AD(true, sizeBuffer)
return t.s.PRF(outLen)
}

View File

@ -2,7 +2,10 @@ package merlin
import (
"fmt"
"math/rand"
"testing"
"github.com/stretchr/testify/assert"
)
// Initialize STROBE-128(4d65726c696e2076312e30) # b"Merlin v1.0"
@ -50,3 +53,55 @@ func TestComplexTranscript(t *testing.T) {
t.Errorf("\nGot : %s\nWant: %s", chlHex, expectedChlHex)
}
}
func TestTranscriptRNG(t *testing.T) {
label := "test protocol"
t1 := NewTranscript(label)
t2 := NewTranscript(label)
t3 := NewTranscript(label)
t4 := NewTranscript(label)
comm1 := []byte("Commitment data 1")
comm2 := []byte("Commitment data 2")
witness1 := []byte("Witness data 1")
witness2 := []byte("Witness data 2")
// t1 will have commitment 1 and t2, t3, t4 will gave same commitment
t1.AppendMessage([]byte("com"), comm1)
t2.AppendMessage([]byte("com"), comm2)
t3.AppendMessage([]byte("com"), comm2)
t4.AppendMessage([]byte("com"), comm2)
// t1, t2 will have same witness data
// t3, t4 will have same witness data
r1, err := t1.BuildRNG().ReKeyWithWitnessBytes([]byte("witness"), witness1).Finalize(rand.New(rand.NewSource(0)))
assert.NoError(t, err)
r2, err := t2.BuildRNG().ReKeyWithWitnessBytes([]byte("witness"), witness1).Finalize(rand.New(rand.NewSource(0)))
assert.NoError(t, err)
r3, err := t3.BuildRNG().ReKeyWithWitnessBytes([]byte("witness"), witness2).Finalize(rand.New(rand.NewSource(0)))
assert.NoError(t, err)
r4, err := t4.BuildRNG().ReKeyWithWitnessBytes([]byte("witness"), witness2).Finalize(rand.New(rand.NewSource(0)))
assert.NoError(t, err)
s1 := r1.RandomBytes(32)
s2 := r2.RandomBytes(32)
s3 := r3.RandomBytes(32)
s4 := r4.RandomBytes(32)
// s1 shouldn't match with any due to different commitment data
// s2 shouldn't match with any due to different witness data
// s3 and s4 match since they same same commitment and witness data, given a bad rng.
// this says that above no equalities are due to different commitments and witness but not because of RNG
assert.NotEqual(t, s1, s2)
assert.NotEqual(t, s1, s3)
assert.NotEqual(t, s1, s4)
assert.NotEqual(t, s2, s3)
assert.NotEqual(t, s2, s4)
assert.Equal(t, s3, s4)
}