mirror of https://github.com/gtank/merlin
add transcript RNG
This commit is contained in:
parent
8318aed1a7
commit
6b336b58be
5
go.mod
5
go.mod
|
@ -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
9
go.sum
|
@ -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=
|
||||
|
|
46
merlin.go
46
merlin.go
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue