github.com/hellobchain/newcryptosm@v0.0.0-20221019060107-edb949a317e9/sm9/curve_interface.go (about)

     1  package sm9
     2  
     3  import (
     4  	"math/big"
     5  )
     6  
     7  // type impl struct{}
     8  
     9  /*
    10  type ECCInternal interface {
    11  	AffineToPoint(x, y *big.Int) (point *ECCInternalPoint)
    12  	PointToAffine(point *ECCInternalPoint) (x, y *big.Int)
    13  	//JacobianAdd(p1, p2 *ECCInternalPoint) (r *ECCInternalPoint, equal int)
    14  	JacobianAdd(p1, p2 *ECCInternalPoint) (r *ECCInternalPoint)
    15  	JacobianDouble(p1 *ECCInternalPoint) (r *ECCInternalPoint)
    16  	PointNegCondition(p1 *ECCInternalPoint, c int)
    17  	FieldMul(res, in1, in2 []uint64)
    18  	MontgomaryR() []uint64
    19  	MontgomaryR2() []uint64
    20  	ModSqrtP(a *big.Int) *big.Int
    21  	ModInverseP(a []uint64) []uint64
    22  	ModInverseOrder(a *big.Int) *big.Int
    23  }
    24  
    25  type ECCInternalPoint struct {
    26  	XYZ [12]uint64
    27  }
    28  */
    29  // func New() supercurve.JacobianIF { //name is not good
    30  // 	return &impl{}
    31  // }
    32  
    33  func InternalP2CurveP(xyz *[12]uint64) (out *curvePoint) {
    34  	out = &curvePoint{}
    35  	copy(out.x[:], xyz[0:4])
    36  	copy(out.y[:], xyz[4:8])
    37  	copy(out.z[:], xyz[8:12])
    38  	return
    39  }
    40  
    41  func InternalP2CurveAffineP(xyz *[12]uint64) (out *curvePointAffine) {
    42  	out = &curvePointAffine{}
    43  	copy(out.x[:], xyz[0:4])
    44  	copy(out.y[:], xyz[4:8])
    45  	return
    46  }
    47  
    48  func CurveP2InternalP(point *curvePoint) (out *[12]uint64) {
    49  	out = &[12]uint64{}
    50  	copy(out[0:4], point.x[:])
    51  	copy(out[4:8], point.y[:])
    52  	copy(out[8:12], point.z[:])
    53  	return
    54  }
    55  
    56  func AffineToPoint(x, y *big.Int) (xyz *[12]uint64) {
    57  
    58  	xyz = &[12]uint64{}
    59  
    60  	t := new(big.Int).Mul(x, mogo_bigInt)
    61  	t.Mod(t, p)
    62  	fromBig(xyz[0:4], t) // change x to montgomery format
    63  
    64  	t.Mul(y, mogo_bigInt)
    65  	t.Mod(t, p)
    66  	fromBig(xyz[4:8], t) // change y to montgomery format
    67  
    68  	xyz[8] = 0x1a9064d81caeba83
    69  	xyz[9] = 0xde0d6cb4e5851124
    70  	xyz[10] = 0x29fc54b00a7138ba
    71  	xyz[11] = 0x49bffffffd5c590e
    72  
    73  	return
    74  }
    75  
    76  func PointToAffine(xyz *[12]uint64) (x, y *big.Int) {
    77  
    78  	ret1 := make([]byte, 32)
    79  	ret2 := make([]byte, 32)
    80  
    81  	temp := InternalP2CurveP(xyz)
    82  	temp.MakeAffine()
    83  
    84  	montDecode(&temp.x, &temp.x)
    85  	montDecode(&temp.y, &temp.y)
    86  
    87  	temp.x.Marshal(ret1)
    88  	temp.y.Marshal(ret2)
    89  
    90  	x1 := new(big.Int).SetBytes(ret1)
    91  	y1 := new(big.Int).SetBytes(ret2)
    92  
    93  	return x1, y1
    94  }
    95  
    96  func JacobianAdd(p1, p2 *[12]uint64) (r1 *[12]uint64) {
    97  
    98  	t1 := InternalP2CurveP(p1)
    99  	t2 := InternalP2CurveP(p2)
   100  	t1.Add(t1, t2)
   101  
   102  	r1 = CurveP2InternalP(t1)
   103  	return
   104  }
   105  
   106  func JacobianAddAffine(p1, p2 *[12]uint64) (r1 *[12]uint64) {
   107  
   108  	t1 := InternalP2CurveP(p1)
   109  	t2 := InternalP2CurveAffineP(p2)
   110  	t1.Add_JA(t1, t2)
   111  
   112  	r1 = CurveP2InternalP(t1)
   113  	return
   114  }
   115  
   116  func JacobianDouble(p1 *[12]uint64) (r1 *[12]uint64) {
   117  	t1 := InternalP2CurveP(p1)
   118  	t1.Double(t1)
   119  	r1 = CurveP2InternalP(t1)
   120  	return
   121  }
   122  
   123  func PointNegCondition(p1 *[12]uint64, condition int) { //if c!=0, p1 <--(-p1)
   124  	if condition == 0 {
   125  		return
   126  	}
   127  	t1 := InternalP2CurveP(p1)
   128  	t1.Neg(t1)
   129  	copy(p1[0:4], t1.x[:])
   130  	copy(p1[4:8], t1.y[:])
   131  	copy(p1[8:12], t1.z[:])
   132  	return
   133  }
   134  
   135  func isOdd(a *big.Int) bool {
   136  	return a.Bit(0) == 1
   137  }
   138  
   139  // decompressPoint decompresses a point on the given curve given the X point and the solution to use.
   140  func DecompressPointX4Y(x *big.Int, ybit bool) *big.Int {
   141  	// x³ - 3x + b
   142  	x3 := new(big.Int).Mul(x, x)
   143  	x3.Mul(x3, x)
   144  
   145  	//	threeX := new(big.Int).Lsh(x, 1)
   146  	//	threeX.Add(threeX, x)
   147  
   148  	//	x3.Sub(x3, threeX)
   149  	x3.Add(x3, big.NewInt(5))
   150  	x3.Mod(x3, Sm9_p)
   151  
   152  	//y := new(big.Int).ModSqrt(x3, curve.Params().P)
   153  	//y := new(big.Int)
   154  	//y:=new(big.Int).ModSqrt(x3, SM9().Params().P)
   155  	y := ModSqrtP(x3)
   156  
   157  	if y == nil {
   158  		return nil
   159  	}
   160  
   161  	if ybit != isOdd(y) {
   162  		y.Sub(Sm9_p, y)
   163  	}
   164  
   165  	return y
   166  }
   167  
   168  // Compress compress a point to a byte string
   169  func CompressP(x, y *big.Int) []byte {
   170  	if x.Sign() == 0 && y.Sign() == 0 {
   171  		return []byte{0x00}
   172  	}
   173  	//byteLen := (sm9inter.SM9().Params().BitSize+7)/8
   174  	byteLen := 32
   175  
   176  	ret := make([]byte, 1+byteLen)
   177  	if y.Bit(0) == 0 {
   178  		ret[0] = 0x02
   179  	} else {
   180  		ret[0] = 0x03
   181  	}
   182  
   183  	xBytes := x.Bytes()
   184  	copy(ret[byteLen-len(xBytes)+1:], xBytes)
   185  	return ret
   186  }
   187  
   188  // Decompress decompress a byte string to a point
   189  func DecompressP(data []byte) (x, y *big.Int) {
   190  	if data == nil {
   191  		return nil, nil
   192  	}
   193  	if len(data) == 0 {
   194  		return nil, nil
   195  	}
   196  	//byteLen := (sm9inter.SM9().Params().BitSize+7)/8
   197  	byteLen := 32
   198  	switch data[0] {
   199  	case 0x00:
   200  		if len(data) == 1 {
   201  			return new(big.Int), new(big.Int)
   202  		}
   203  		return nil, nil
   204  	case 0x02, 0x03:
   205  		{
   206  			if len(data) != 1+byteLen {
   207  				return nil, nil
   208  			}
   209  			x = new(big.Int).SetBytes(data[1:])
   210  
   211  			// x³ + b
   212  			x3 := new(big.Int).Mul(x, x)
   213  			x3.Mul(x3, x)
   214  
   215  			x3.Add(x3, big.NewInt(5))
   216  			x3.Mod(x3, Sm9_p)
   217  
   218  			y := ModSqrtP(x3)
   219  
   220  			if y == nil {
   221  				return nil, nil
   222  			}
   223  			if y.Bit(0) != uint(data[0]&0x01) {
   224  				y.Sub(Sm9_p, y)
   225  			}
   226  			return x, y
   227  		}
   228  	case 0x04:
   229  		{
   230  			x = new(big.Int).SetBytes(data[1 : 1+byteLen])
   231  			y = new(big.Int).SetBytes(data[1+byteLen:])
   232  			return x, y
   233  		}
   234  	default:
   235  		return nil, nil
   236  	}
   237  }
   238  
   239  func FieldMul(res, in1, in2 []uint64) { //res,in1,in2:mogo format
   240  	var temp1 = &gfP{in1[0], in1[1], in1[2], in1[3]}
   241  	var temp2 = &gfP{in2[0], in2[1], in2[2], in2[3]}
   242  	gfpMul(temp2, temp2, temp1)
   243  	for i := 0; i < 4; i++ {
   244  		res[i] = temp2[i]
   245  	}
   246  }
   247  
   248  func MontgomaryR() []uint64 {
   249  	return []uint64{0x1a9064d81caeba83, 0xde0d6cb4e5851124, 0x29fc54b00a7138ba, 0x49bffffffd5c590e}
   250  }
   251  
   252  func MontgomaryR2() []uint64 {
   253  	return []uint64{0x27dea312b417e2d2, 0x88f8105fae1a5d3f, 0xe479b522d6706e7b, 0x2ea795a656f62fbd}
   254  	//2ea795a656f62fbd e479b522d6706e7b 88f8105fae1a5d3f 27dea312b417e2d2
   255  }
   256  
   257  /*
   258  func (c *impl) ModSqrtP(a *big.Int) *big.Int {
   259  	var temp = big.NewInt(1)
   260  	temp.ModSqrt(a, p)
   261  	return temp
   262  }
   263  */
   264  
   265  func ModSqrtP(a *big.Int) *big.Int { //a>=0,a!=2;//ALG see:SM_1_P29
   266  
   267  	var temp = big.NewInt(1)
   268  	var one = big.NewInt(1)
   269  	var fone = big.NewInt(-1)
   270  	fone.Mod(fone, p)
   271  	temp.Exp(a, const2uplus1, p) //g^(2u+1)
   272  
   273  	if temp.Cmp(one) == 0 {
   274  		temp.Exp(a, constuplus1, p)
   275  	} else if temp.Cmp(fone) == 0 {
   276  		one.Add(a, a) //2g
   277  		one.Mod(one, p)
   278  		fone.Add(one, one) //4g
   279  		fone.Mod(fone, p)
   280  		fone.Exp(fone, constu, p)
   281  		fone.Mul(fone, one)
   282  		fone.Mod(fone, p)
   283  		temp.Set(fone)
   284  	} else {
   285  		return a
   286  	}
   287  	return temp
   288  }
   289  
   290  //func montEncode(c, a *gfP) { gfpMul(c, a, r2) }
   291  func ModInverseP(a []uint64) []uint64 { //a: mogo format;return mogo format too;
   292  	temp := &gfP{a[0], a[1], a[2], a[3]}
   293  	temp.Invert(temp)
   294  
   295  	X := make([]uint64, 4)
   296  	for i := 0; i < 4; i++ {
   297  		X[i] = temp[i]
   298  	}
   299  	return X
   300  }
   301  
   302  func ModInverseOrder(a *big.Int) *big.Int {
   303  	var b = big.NewInt(1)
   304  	b.ModInverse(a, Order)
   305  	return b
   306  }
   307  
   308  func InitBigTable(Bx, By *big.Int) *[43][32 * 8]uint64 {
   309  	var precomputed [43][32 * 8]uint64
   310  
   311  	btpoint := AffineToPoint(Bx, By)
   312  
   313  	basepoint := &curvePoint{}
   314  	for i := 0; i < 4; i++ {
   315  		basepoint.x[i] = btpoint[i]
   316  		basepoint.y[i] = btpoint[i+4]
   317  		basepoint.z[i] = btpoint[i+8]
   318  	}
   319  
   320  	t1 := new(G1).Set(&G1{basepoint})
   321  	t2 := new(G1).Set(&G1{basepoint})
   322  	t3 := new(G1).Set(&G1{basepoint})
   323  	var count int
   324  	for j := 0; j < 32; j++ {
   325  		t1.Set(t2)
   326  
   327  		for i := 0; i < 43; i++ {
   328  			// The window size is 6 so we need to double 6 times.
   329  			if i != 0 {
   330  				for k := 0; k < 6; k++ {
   331  					//p256PointDoubleAsm(t1, t1)
   332  					t3.p.Double(t1.p)
   333  					t1.Set(t3)
   334  				}
   335  			}
   336  
   337  			t1.p.MakeAffine()
   338  			t1.p.z[0] = 0x1a9064d81caeba83
   339  			t1.p.z[1] = 0xde0d6cb4e5851124
   340  			t1.p.z[2] = 0x29fc54b00a7138ba
   341  			t1.p.z[3] = 0x49bffffffd5c590e
   342  
   343  			if t1.p.IsInfinity() {
   344  				for count = 0; count < 4; count++ {
   345  					precomputed[i][j*8+count] = 0
   346  					precomputed[i][j*8+count+4] = 0
   347  				}
   348  			}
   349  			for count = 0; count < 4; count++ {
   350  				precomputed[i][j*8+count] = t1.p.x[count]
   351  				precomputed[i][j*8+count+4] = t1.p.y[count]
   352  			}
   353  
   354  		}
   355  		if j == 0 {
   356  			//p256PointDoubleAsm(t2, basePoint)
   357  			t2.p.Double(basepoint)
   358  		} else { //t2:3-->32G
   359  			t2.p.Add(t2.p, basepoint)
   360  		}
   361  	}
   362  	return &precomputed
   363  }