add SubtractR/L operation on hashes

- add Inverse operation to sl2
- fix a bug in xN()
This commit is contained in:
Evgenii 2019-01-29 16:11:48 +03:00
parent ebb124e812
commit d5efd8bdce
6 changed files with 146 additions and 19 deletions

View file

@ -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) {

View file

@ -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}},
}

View file

@ -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)

View file

@ -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))
}
}

View file

@ -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()

View file

@ -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))
}
}