add SubtractR/L operation on hashes
- add Inverse operation to sl2 - fix a bug in xN()
This commit is contained in:
parent
ebb124e812
commit
d5efd8bdce
6 changed files with 146 additions and 19 deletions
|
@ -19,7 +19,7 @@ import (
|
||||||
type GF127 [2]uint64
|
type GF127 [2]uint64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
msb64 = 0x8000000000000000
|
msb64 = uint64(0x8000000000000000)
|
||||||
byteSize = 16
|
byteSize = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -110,8 +110,7 @@ func Inv(a, b *GF127) {
|
||||||
// becasuse mul performs reduction on t, we need
|
// becasuse mul performs reduction on t, we need
|
||||||
// manually reduce u at first step
|
// manually reduce u at first step
|
||||||
if msb(&u) == 127 {
|
if msb(&u) == 127 {
|
||||||
Add(&u, &x127x63, &u)
|
Add(&u, &x127x631, &u)
|
||||||
Add(&u, &GF127{1, 0}, &u)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mul(x, d, t)
|
Mul(x, d, t)
|
||||||
|
@ -124,7 +123,7 @@ func xN(n int) *GF127 {
|
||||||
if n < 64 {
|
if n < 64 {
|
||||||
return &GF127{1 << uint(n), 0}
|
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) {
|
func msb(a *GF127) (x int) {
|
||||||
|
|
|
@ -71,6 +71,7 @@ func TestMul11(t *testing.T) {
|
||||||
|
|
||||||
var testCasesInv = [][2]*GF127{
|
var testCasesInv = [][2]*GF127{
|
||||||
{&GF127{1, 0}, &GF127{1, 0}},
|
{&GF127{1, 0}, &GF127{1, 0}},
|
||||||
|
{&GF127{3, 0}, &GF127{msb64, ^msb64}},
|
||||||
{&GF127{54321, 12345}, &GF127{8230555108620784737, 3929873967650665114}},
|
{&GF127{54321, 12345}, &GF127{8230555108620784737, 3929873967650665114}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
38
tz/hash.go
38
tz/hash.go
|
@ -133,4 +133,42 @@ func Validate(h []byte, hs [][]byte) (bool, error) {
|
||||||
return expected == got, nil
|
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)
|
func mulBitRight(c00, c01, c10, c11, e *gf127.GF127)
|
||||||
|
|
|
@ -15,9 +15,9 @@ func TestHash(t *testing.T) {
|
||||||
err error
|
err error
|
||||||
h, h1, h2 [hashSize]byte
|
h, h1, h2 [hashSize]byte
|
||||||
b []byte
|
b []byte
|
||||||
)
|
|
||||||
|
|
||||||
g := NewGomegaWithT(t)
|
g = NewGomegaWithT(t)
|
||||||
|
)
|
||||||
|
|
||||||
b = make([]byte, 64)
|
b = make([]byte, 64)
|
||||||
n, err = rand.Read(b)
|
n, err = rand.Read(b)
|
||||||
|
@ -31,6 +31,7 @@ func TestHash(t *testing.T) {
|
||||||
|
|
||||||
err = c1.UnmarshalBinary(h1[:])
|
err = c1.UnmarshalBinary(h1[:])
|
||||||
g.Expect(err).NotTo(HaveOccurred())
|
g.Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
err = c2.UnmarshalBinary(h2[:])
|
err = c2.UnmarshalBinary(h2[:])
|
||||||
g.Expect(err).NotTo(HaveOccurred())
|
g.Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
@ -62,9 +63,9 @@ func TestConcat(t *testing.T) {
|
||||||
got, expected []byte
|
got, expected []byte
|
||||||
ps [][]byte
|
ps [][]byte
|
||||||
err error
|
err error
|
||||||
)
|
|
||||||
|
|
||||||
g := NewGomegaWithT(t)
|
g = NewGomegaWithT(t)
|
||||||
|
)
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
expected, err = hex.DecodeString(tc.Hash)
|
expected, err = hex.DecodeString(tc.Hash)
|
||||||
|
@ -107,3 +108,46 @@ func TestValidate(t *testing.T) {
|
||||||
g.Expect(got).To(Equal(true))
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
tz/sl2.go
19
tz/sl2.go
|
@ -132,6 +132,25 @@ func (c *sl2) Mul(a, b *sl2) *sl2 {
|
||||||
return c.mul(a, b, new([4]gf127.GF127))
|
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 {
|
func (c *sl2) String() string {
|
||||||
return c[0][0].String() + c[0][1].String() +
|
return c[0][0].String() + c[0][1].String() +
|
||||||
c[1][0].String() + c[1][1].String()
|
c[1][0].String() + c[1][1].String()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package tz
|
package tz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -14,25 +13,52 @@ func init() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
||||||
func u64() uint64 {
|
func random() (a *sl2) {
|
||||||
return rand.Uint64() & (math.MaxUint64 >> 1)
|
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) {
|
func TestSL2_MarshalBinary(t *testing.T) {
|
||||||
g := NewGomegaWithT(t)
|
var (
|
||||||
|
a = random()
|
||||||
a := new(sl2)
|
b = new(sl2)
|
||||||
a[0][0] = *gf127.New(u64(), u64())
|
g = NewGomegaWithT(t)
|
||||||
a[0][1] = *gf127.New(u64(), u64())
|
)
|
||||||
a[1][0] = *gf127.New(u64(), u64())
|
|
||||||
a[1][1] = *gf127.New(u64(), u64())
|
|
||||||
|
|
||||||
data, err := a.MarshalBinary()
|
data, err := a.MarshalBinary()
|
||||||
g.Expect(err).NotTo(HaveOccurred())
|
g.Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
b := new(sl2)
|
|
||||||
err = b.UnmarshalBinary(data)
|
err = b.UnmarshalBinary(data)
|
||||||
g.Expect(err).NotTo(HaveOccurred())
|
g.Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
g.Expect(a).To(Equal(b))
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue