From d5efd8bdce73d0dfc26336549bd7b1d7e5b4b139 Mon Sep 17 00:00:00 2001 From: Evgenii Date: Tue, 29 Jan 2019 16:11:48 +0300 Subject: [PATCH] add SubtractR/L operation on hashes - add Inverse operation to sl2 - fix a bug in xN() --- gf127/gf127.go | 7 +++--- gf127/gf127_test.go | 1 + tz/hash.go | 38 +++++++++++++++++++++++++++++++++ tz/hash_test.go | 52 +++++++++++++++++++++++++++++++++++++++++---- tz/sl2.go | 19 +++++++++++++++++ tz/sl2_test.go | 48 +++++++++++++++++++++++++++++++---------- 6 files changed, 146 insertions(+), 19 deletions(-) diff --git a/gf127/gf127.go b/gf127/gf127.go index f923cf9..8d4152b 100644 --- a/gf127/gf127.go +++ b/gf127/gf127.go @@ -19,7 +19,7 @@ import ( type GF127 [2]uint64 const ( - msb64 = 0x8000000000000000 + msb64 = uint64(0x8000000000000000) byteSize = 16 ) @@ -110,8 +110,7 @@ func Inv(a, b *GF127) { // becasuse mul performs reduction on t, we need // manually reduce u at first step if msb(&u) == 127 { - Add(&u, &x127x63, &u) - Add(&u, &GF127{1, 0}, &u) + Add(&u, &x127x631, &u) } Mul(x, d, t) @@ -124,7 +123,7 @@ func xN(n int) *GF127 { if n < 64 { return &GF127{1 << uint(n), 0} } - return &GF127{0, 1 << (uint(n) >> 8)} + return &GF127{0, 1 << uint(n-64)} } func msb(a *GF127) (x int) { diff --git a/gf127/gf127_test.go b/gf127/gf127_test.go index eca46ad..bc7e902 100644 --- a/gf127/gf127_test.go +++ b/gf127/gf127_test.go @@ -71,6 +71,7 @@ func TestMul11(t *testing.T) { var testCasesInv = [][2]*GF127{ {&GF127{1, 0}, &GF127{1, 0}}, + {&GF127{3, 0}, &GF127{msb64, ^msb64}}, {&GF127{54321, 12345}, &GF127{8230555108620784737, 3929873967650665114}}, } diff --git a/tz/hash.go b/tz/hash.go index ac43932..dc46290 100644 --- a/tz/hash.go +++ b/tz/hash.go @@ -133,4 +133,42 @@ func Validate(h []byte, hs [][]byte) (bool, error) { return expected == got, nil } +// SubtractR returns hash a, such that Concat(a, b) == c +// This is possible, because Tillich-Zemor hash is actually a matrix +// which can be inversed. +func SubtractR(c, b []byte) (a []byte, err error) { + var p1, p2, r sl2 + + if err = r.UnmarshalBinary(c); err != nil { + return nil, err + } + if err = p2.UnmarshalBinary(b); err != nil { + return nil, err + } + + p1 = *Inv(&p2) + p1.Mul(&r, &p1) + + return p1.MarshalBinary() +} + +// SubtractL returns hash b, such that Concat(a, b) == c +// This is possible, because Tillich-Zemor hash is actually a matrix +// which can be inversed. +func SubtractL(c, a []byte) (b []byte, err error) { + var p1, p2, r sl2 + + if err = r.UnmarshalBinary(c); err != nil { + return nil, err + } + if err = p1.UnmarshalBinary(a); err != nil { + return nil, err + } + + p2 = *Inv(&p1) + p2.Mul(&p2, &r) + + return p2.MarshalBinary() +} + func mulBitRight(c00, c01, c10, c11, e *gf127.GF127) diff --git a/tz/hash_test.go b/tz/hash_test.go index 109e54b..683632e 100644 --- a/tz/hash_test.go +++ b/tz/hash_test.go @@ -15,9 +15,9 @@ func TestHash(t *testing.T) { err error h, h1, h2 [hashSize]byte b []byte - ) - g := NewGomegaWithT(t) + g = NewGomegaWithT(t) + ) b = make([]byte, 64) n, err = rand.Read(b) @@ -31,6 +31,7 @@ func TestHash(t *testing.T) { err = c1.UnmarshalBinary(h1[:]) g.Expect(err).NotTo(HaveOccurred()) + err = c2.UnmarshalBinary(h2[:]) g.Expect(err).NotTo(HaveOccurred()) @@ -62,9 +63,9 @@ func TestConcat(t *testing.T) { got, expected []byte ps [][]byte err error - ) - g := NewGomegaWithT(t) + g = NewGomegaWithT(t) + ) for _, tc := range testCases { expected, err = hex.DecodeString(tc.Hash) @@ -107,3 +108,46 @@ func TestValidate(t *testing.T) { g.Expect(got).To(Equal(true)) } } + +var testCasesSubtract = []struct { + first, second, result string +}{ + { + first: "4275945919296224acd268456be23b8b2df931787a46716477e32cd991e98074029d4f03a0fedc09125ee4640d228d7d40d430659a0b2b70e9cd4d4c5361865a", + second: "277c10e0d7c52fcc0b23ba7dbf2c3dde7dcfc1f7c0cc0d998b2de504b8c1e17c6f65ab1294aea676d4060ed2ca18c1c26fd7cec5012ab69a4ddb5e6555ac8a59", + result: "7f5c9280352a8debea738a74abd4ec787f2c5e556800525692f651087442f9883bb97a2c1bc72d12ba26e3df8dc0f670564292ebc984976a8e353ff69a5fb3cb", + }, + { + first: "18e2ce290cc74998ebd0bef76454b52a40428f13bb612e40b5b96187e9cc813248a0ed5f7ec9fb205d55d3f243e2211363f171b19eb8acc7931cf33853a79069", + second: "73a0582fa7d00d62fd09c1cd18589cdb2b126cb58b3a022ae47a8a787dabe35c4388aaf0d8bb343b1e58ee8d267812d115f40a0da611f42458f452e102f60700", + result: "54ccaad1bb15b2989fa31109713bca955ea5d87bbd3113b3008cea167c00052266e9c9fcb73ece98c6c08cccb074ba3d39b5d8685f022fc388e2bf1997c5bd1d", + }, +} + +func TestSubtract(t *testing.T) { + var ( + a, b, c, r []byte + err error + + g = NewGomegaWithT(t) + ) + + for _, tc := range testCasesSubtract { + a, err = hex.DecodeString(tc.first) + g.Expect(err).NotTo(HaveOccurred()) + + b, err = hex.DecodeString(tc.second) + g.Expect(err).NotTo(HaveOccurred()) + + c, err = hex.DecodeString(tc.result) + g.Expect(err).NotTo(HaveOccurred()) + + r, err = SubtractR(c, b) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(r).To(Equal(a)) + + r, err = SubtractL(c, a) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(r).To(Equal(b)) + } +} diff --git a/tz/sl2.go b/tz/sl2.go index caf56cc..ea56db0 100644 --- a/tz/sl2.go +++ b/tz/sl2.go @@ -132,6 +132,25 @@ func (c *sl2) Mul(a, b *sl2) *sl2 { return c.mul(a, b, new([4]gf127.GF127)) } +// Inv returns inverse of a in GL_2(GF(2^127)) +func Inv(a *sl2) (b *sl2) { + b = new(sl2) + inv(a, b, new([2]gf127.GF127)) + return +} + +func inv(a, b *sl2, t *[2]gf127.GF127) { + gf127.Mul(&a[0][0], &a[1][1], &t[0]) + gf127.Mul(&a[0][1], &a[1][0], &t[1]) + gf127.Add(&t[0], &t[1], &t[0]) + gf127.Inv(&t[0], &t[1]) + + gf127.Mul(&t[1], &a[0][0], &b[1][1]) + gf127.Mul(&t[1], &a[0][1], &b[0][1]) + gf127.Mul(&t[1], &a[1][0], &b[1][0]) + gf127.Mul(&t[1], &a[1][1], &b[0][0]) +} + func (c *sl2) String() string { return c[0][0].String() + c[0][1].String() + c[1][0].String() + c[1][1].String() diff --git a/tz/sl2_test.go b/tz/sl2_test.go index ad6d18d..162df39 100644 --- a/tz/sl2_test.go +++ b/tz/sl2_test.go @@ -1,7 +1,6 @@ package tz import ( - "math" "math/rand" "testing" "time" @@ -14,25 +13,52 @@ func init() { rand.Seed(time.Now().UnixNano()) } -func u64() uint64 { - return rand.Uint64() & (math.MaxUint64 >> 1) +func random() (a *sl2) { + a = new(sl2) + a[0][0] = *gf127.Random() + a[0][1] = *gf127.Random() + a[1][0] = *gf127.Random() + + // so that result is in SL2 + // d = a^-1*(1+b*c) + gf127.Mul(&a[0][1], &a[1][0], &a[1][1]) + gf127.Add(&a[1][1], gf127.New(1, 0), &a[1][1]) + + t := gf127.New(0, 0) + gf127.Inv(&a[0][0], t) + gf127.Mul(t, &a[1][1], &a[1][1]) + + return } func TestSL2_MarshalBinary(t *testing.T) { - g := NewGomegaWithT(t) - - a := new(sl2) - a[0][0] = *gf127.New(u64(), u64()) - a[0][1] = *gf127.New(u64(), u64()) - a[1][0] = *gf127.New(u64(), u64()) - a[1][1] = *gf127.New(u64(), u64()) + var ( + a = random() + b = new(sl2) + g = NewGomegaWithT(t) + ) data, err := a.MarshalBinary() g.Expect(err).NotTo(HaveOccurred()) - b := new(sl2) err = b.UnmarshalBinary(data) g.Expect(err).NotTo(HaveOccurred()) g.Expect(a).To(Equal(b)) } + +func TestInv(t *testing.T) { + var ( + a, b, c *sl2 + g = NewGomegaWithT(t) + ) + + c = new(sl2) + for i := 0; i < 5; i++ { + a = random() + b = Inv(a) + c = c.Mul(a, b) + + g.Expect(*c).To(Equal(id)) + } +}