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
|
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 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
|
||||||
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
|
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 (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/mimoo/StrobeGo/strobe"
|
"github.com/mimoo/StrobeGo/strobe"
|
||||||
)
|
)
|
||||||
|
@ -60,3 +61,48 @@ func (t *Transcript) ExtractBytes(label []byte, outLen int) []byte {
|
||||||
outBytes := t.s.PRF(outLen)
|
outBytes := t.s.PRF(outLen)
|
||||||
return outBytes
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initialize STROBE-128(4d65726c696e2076312e30) # b"Merlin v1.0"
|
// 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)
|
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