sm9: reduce gfp2 mul

This commit is contained in:
Sun Yimin 2023-04-28 11:25:09 +08:00 committed by GitHub
parent fab159f5f0
commit a454c5f5ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 155 additions and 224 deletions

View File

@ -251,6 +251,13 @@ func (e *gfP12) Invert(a *gfP12) *gfP12 {
return e
}
func (e *gfP12) Neg(a *gfP12) *gfP12 {
e.x.Neg(&a.x)
e.y.Neg(&a.y)
e.z.Neg(&a.z)
return e
}
// (z + y*w + x*w^2)^p
//= z^p + y^p*w*w^(p-1)+x^p*w^2*(w^2)^(p-1)
// w2ToP2Minus1 = vToPMinus1 * wToPMinus1

View File

@ -5,28 +5,21 @@ import (
"testing"
)
var testdataP4 = gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
}
func Test_gfP12Square(t *testing.T) {
x := &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
testdataP4,
testdataP4,
*(&gfP4{}).SetOne(),
}
xmulx := &gfP12{}
@ -42,30 +35,7 @@ func Test_gfP12Square(t *testing.T) {
}
}
func Test_gfP12Invert(t *testing.T) {
x := &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
*(&gfP4{}).SetOne(),
}
func testGfP12Invert(t *testing.T, x *gfP12) {
xInv := &gfP12{}
xInv.Invert(x)
@ -74,35 +44,27 @@ func Test_gfP12Invert(t *testing.T) {
if !y.IsOne() {
t.Fail()
}
}
func Test_gfP12Invert(t *testing.T) {
x := &gfP12{
testdataP4,
testdataP4,
*(&gfP4{}).SetOne(),
}
testGfP12Invert(t, x)
x = &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
testdataP4,
testdataP4,
*(&gfP4{}).SetZero(),
}
xInv.Invert(x)
y.Mul(x, xInv)
if !y.IsOne() {
t.Fail()
testGfP12Invert(t, x)
x = &gfP12{
testdataP4,
testdataP4,
testdataP4,
}
testGfP12Invert(t, x)
}
// Generate wToPMinus1
@ -227,36 +189,9 @@ func Test_gfP12FrobeniusP3_Case2(t *testing.T) {
func Test_gfP12Frobenius(t *testing.T) {
x := &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
testdataP4,
testdataP4,
testdataP4,
}
expected := &gfP12{}
expected.Exp(x, p)
@ -269,36 +204,9 @@ func Test_gfP12Frobenius(t *testing.T) {
func Test_gfP12FrobeniusP2(t *testing.T) {
x := &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
testdataP4,
testdataP4,
testdataP4,
}
expected := &gfP12{}
p2 := new(big.Int).Mul(p, p)
@ -312,36 +220,9 @@ func Test_gfP12FrobeniusP2(t *testing.T) {
func Test_gfP12FrobeniusP3(t *testing.T) {
x := &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
testdataP4,
testdataP4,
testdataP4,
}
expected := &gfP12{}
p3 := new(big.Int).Mul(p, p)
@ -356,36 +237,9 @@ func Test_gfP12FrobeniusP3(t *testing.T) {
func Test_gfP12FrobeniusP6(t *testing.T) {
x := &gfP12{
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
gfP4{
gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
},
gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
},
},
testdataP4,
testdataP4,
testdataP4,
}
expected := &gfP12{}
p6 := new(big.Int).Mul(p, p)
@ -412,3 +266,22 @@ func Test_W3(t *testing.T) {
t.Errorf("not expected")
}
}
func BenchmarkGfP12Frobenius(b *testing.B) {
x := &gfP12{
testdataP4,
testdataP4,
testdataP4,
}
expected := &gfP12{}
expected.Exp(x, p)
got := &gfP12{}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
got.Frobenius(x)
if *expected != *got {
b.Errorf("got %v, expected %v", got, expected)
}
}
}

View File

@ -9,9 +9,9 @@ import (
// http://eprint.iacr.org/2006/471.pdf.
// gfP2 implements a field of size p² as a quadratic extension of the base field
// where =-2.
// where u²=-2, beta=-2.
type gfP2 struct {
x, y gfP // value is xi+y.
x, y gfP // value is xu+y.
}
func gfP2Decode(in *gfP2) *gfP2 {
@ -105,45 +105,50 @@ func (e *gfP2) Triple(a *gfP2) *gfP2 {
// See "Multiplication and Squaring in Pairing-Friendly Fields",
// http://eprint.iacr.org/2006/471.pdf
// The Karatsuba method
//(a0+a1*i)(b0+b1*i)=c0+c1*i, where
//(a0+a1*u)(b0+b1*u)=c0+c1*u, where
//c0 = a0*b0 - 2a1*b1
//c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0
func (e *gfP2) Mul(a, b *gfP2) *gfP2 {
tx, t := &gfP{}, &gfP{}
gfpMul(tx, &a.x, &b.y)
gfpMul(t, &b.x, &a.y)
gfpAdd(tx, tx, t)
tx, ty, v0, v1 := &gfP{}, &gfP{}, &gfP{}, &gfP{}
ty := &gfP{}
gfpMul(ty, &a.y, &b.y)
gfpMul(t, &a.x, &b.x)
gfpMul(t, t, two)
gfpSub(ty, ty, t)
gfpMul(v0, &a.y, &b.y)
gfpMul(v1, &a.x, &b.x)
gfpAdd(tx, &a.x, &a.y)
gfpAdd(ty, &b.x, &b.y)
gfpMul(tx, tx, ty)
gfpSub(tx, tx, v0)
gfpSub(tx, tx, v1)
gfpSub(ty, v0, v1)
gfpSub(ty, ty, v1)
e.x.Set(tx)
e.y.Set(ty)
return e
}
// MulU: a * b * i
//(a0+a1*i)(b0+b1*i)*i=c0+c1*i, where
//c1 = (a0*b0 - 2a1*b1)i
// MulU: a * b * u
//(a0+a1*u)(b0+b1*u)*u=c0+c1*u, where
//c1 = (a0*b0 - 2a1*b1)u
//c0 = -2 * ((a0 + a1)(b0 + b1) - a0*b0 - a1*b1) = -2 * (a0*b1 + a1*b0)
func (e *gfP2) MulU(a, b *gfP2) *gfP2 {
// ty = -2 * (a0 * b1 + a1 * b0)
ty, t := &gfP{}, &gfP{}
gfpMul(ty, &a.x, &b.y)
gfpMul(t, &b.x, &a.y)
gfpAdd(ty, ty, t)
tx, ty, v0, v1 := &gfP{}, &gfP{}, &gfP{}, &gfP{}
gfpMul(v0, &a.y, &b.y)
gfpMul(v1, &a.x, &b.x)
gfpAdd(tx, &a.x, &a.y)
gfpAdd(ty, &b.x, &b.y)
gfpMul(ty, tx, ty)
gfpSub(ty, ty, v0)
gfpSub(ty, ty, v1)
gfpAdd(ty, ty, ty)
gfpNeg(ty, ty)
// tx = a0 * b0 - 2 * a1 * b1
tx := &gfP{}
gfpMul(tx, &a.y, &b.y)
gfpMul(t, &a.x, &b.x)
gfpMul(t, t, two)
gfpSub(tx, tx, t)
gfpSub(tx, v0, v1)
gfpSub(tx, tx, v1)
e.x.Set(tx)
e.y.Set(ty)
@ -152,7 +157,7 @@ func (e *gfP2) MulU(a, b *gfP2) *gfP2 {
func (e *gfP2) Square(a *gfP2) *gfP2 {
// Complex squaring algorithm:
// (xi+y)² = y^2-2*x^2 + 2*i*x*y
// (xu+y)² = y^2-2*x^2 + 2*u*x*y
tx, ty := &gfP{}, &gfP{}
gfpMul(tx, &a.x, &a.x)
gfpMul(ty, &a.y, &a.y)
@ -169,7 +174,7 @@ func (e *gfP2) Square(a *gfP2) *gfP2 {
func (e *gfP2) SquareU(a *gfP2) *gfP2 {
// Complex squaring algorithm:
// (xi+y)²*i = (y^2-2*x^2)i - 4*x*y
// (xu+y)²*u = (y^2-2*x^2)u - 4*x*y
tx, ty := &gfP{}, &gfP{}
// tx = a0^2 - 2 * a1^2
@ -231,10 +236,10 @@ func (e *gfP2) Exp(f *gfP2, power *big.Int) *gfP2 {
return e
}
// xi+y)^p = x * i^p + y
// = x * i * i^(p-1) + y
// = (-x)*i + y
// here i^(p-1) = -1
// xu+y)^p = x * u^p + y
// = x * u * u^(p-1) + y
// = (-x)*u + y
// here u^(p-1) = -1
func (e *gfP2) Frobenius(a *gfP2) *gfP2 {
e.Conjugate(a)
return e

View File

@ -126,6 +126,52 @@ func Test_gfP2Sqrt(t *testing.T) {
}
}
func BenchmarkGfP2Mul(b *testing.B) {
x := &gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
}
y := &gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
t := &gfP2{}
t.Mul(x, y)
}
}
func BenchmarkGfP2MulU(b *testing.B) {
x := &gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
}
y := &gfP2{
*fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")),
*fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")),
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
t := &gfP2{}
t.MulU(x, y)
}
}
func BenchmarkGfP2Square(b *testing.B) {
x := &gfP2{
*fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")),
*fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")),
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
x.Square(x)
}
}
/*
func Test_gfP2QuadraticResidue(t *testing.T) {
x := &gfP2{

View File

@ -8,9 +8,9 @@ import "math/big"
//
// gfP4 implements the field of size p^4 as a quadratic extension of gfP2
// where u²=i.
// where v²=ξ and ξ=u.
type gfP4 struct {
x, y gfP2 // value is xi+y.
x, y gfP2 // value is xv+y.
}
func gfP4Decode(in *gfP4) *gfP4 {