mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 20:56:18 +08:00
sm2: generic use new method first
This commit is contained in:
parent
3e2158f68d
commit
974ba65845
1401
sm2/p256.go
1401
sm2/p256.go
File diff suppressed because it is too large
Load Diff
@ -3,11 +3,184 @@
|
||||
|
||||
package sm2
|
||||
|
||||
var (
|
||||
p256 p256Curve
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/sm2ec"
|
||||
)
|
||||
|
||||
func initP256Arch() {
|
||||
// Use pure Go implementation.
|
||||
p256 = p256Curve{p256Params}
|
||||
// TODO: will merge it with sm2p256_asm_ec.go from golang 1.18 with generic support.
|
||||
type sm2Curve struct {
|
||||
newPoint func() *sm2ec.SM2P256Point
|
||||
CurveParams *elliptic.CurveParams
|
||||
}
|
||||
|
||||
var p256 = &sm2Curve{newPoint: sm2ec.NewSM2P256Point}
|
||||
|
||||
func initP256() {
|
||||
p256.CurveParams = &elliptic.CurveParams{Name: "sm2p256v1"}
|
||||
p256.CurveParams.P, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
|
||||
p256.CurveParams.N, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
|
||||
p256.CurveParams.B, _ = new(big.Int).SetString("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16)
|
||||
p256.CurveParams.Gx, _ = new(big.Int).SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)
|
||||
p256.CurveParams.Gy, _ = new(big.Int).SetString("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16)
|
||||
p256.CurveParams.BitSize = 256
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Params() *elliptic.CurveParams {
|
||||
return curve.CurveParams
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) IsOnCurve(x, y *big.Int) bool {
|
||||
// IsOnCurve is documented to reject (0, 0), the conventional point at
|
||||
// infinity, which however is accepted by pointFromAffine.
|
||||
if x.Sign() == 0 && y.Sign() == 0 {
|
||||
return false
|
||||
}
|
||||
_, err := curve.pointFromAffine(x, y)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) pointFromAffine(x, y *big.Int) (p *sm2ec.SM2P256Point, err error) {
|
||||
p = curve.newPoint()
|
||||
// (0, 0) is by convention the point at infinity, which can't be represented
|
||||
// in affine coordinates. See Issue 37294.
|
||||
if x.Sign() == 0 && y.Sign() == 0 {
|
||||
return p, nil
|
||||
}
|
||||
// Reject values that would not get correctly encoded.
|
||||
if x.Sign() < 0 || y.Sign() < 0 {
|
||||
return p, errors.New("negative coordinate")
|
||||
}
|
||||
if x.BitLen() > curve.CurveParams.BitSize || y.BitLen() > curve.CurveParams.BitSize {
|
||||
return p, errors.New("overflowing coordinate")
|
||||
}
|
||||
// Encode the coordinates and let SetBytes reject invalid points.
|
||||
byteLen := (curve.CurveParams.BitSize + 7) / 8
|
||||
buf := make([]byte, 1+2*byteLen)
|
||||
buf[0] = 4 // uncompressed point
|
||||
x.FillBytes(buf[1 : 1+byteLen])
|
||||
y.FillBytes(buf[1+byteLen : 1+2*byteLen])
|
||||
return p.SetBytes(buf)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) pointToAffine(p *sm2ec.SM2P256Point) (x, y *big.Int) {
|
||||
out := p.Bytes()
|
||||
if len(out) == 1 && out[0] == 0 {
|
||||
// This is the encoding of the point at infinity, which the affine
|
||||
// coordinates API represents as (0, 0) by convention.
|
||||
return new(big.Int), new(big.Int)
|
||||
}
|
||||
byteLen := (curve.CurveParams.BitSize + 7) / 8
|
||||
x = new(big.Int).SetBytes(out[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(out[1+byteLen:])
|
||||
return x, y
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
||||
p1, err := curve.pointFromAffine(x1, y1)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: Add was called on an invalid point")
|
||||
}
|
||||
p2, err := curve.pointFromAffine(x2, y2)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: Add was called on an invalid point")
|
||||
}
|
||||
return curve.pointToAffine(p1.Add(p1, p2))
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
|
||||
p, err := curve.pointFromAffine(x1, y1)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: Double was called on an invalid point")
|
||||
}
|
||||
return curve.pointToAffine(p.Double(p))
|
||||
}
|
||||
|
||||
// normalizeScalar brings the scalar within the byte size of the order of the
|
||||
// curve, as expected by the nistec scalar multiplication functions.
|
||||
func (curve *sm2Curve) normalizeScalar(scalar []byte) []byte {
|
||||
byteSize := (curve.CurveParams.N.BitLen() + 7) / 8
|
||||
if len(scalar) == byteSize {
|
||||
return scalar
|
||||
}
|
||||
s := new(big.Int).SetBytes(scalar)
|
||||
if len(scalar) > byteSize {
|
||||
s.Mod(s, curve.CurveParams.N)
|
||||
}
|
||||
out := make([]byte, byteSize)
|
||||
return s.FillBytes(out)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
|
||||
p, err := curve.pointFromAffine(Bx, By)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: ScalarMult was called on an invalid point")
|
||||
}
|
||||
scalar = curve.normalizeScalar(scalar)
|
||||
p, err = p.ScalarMult(p, scalar)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
return curve.pointToAffine(p)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
|
||||
scalar = curve.normalizeScalar(scalar)
|
||||
p, err := curve.newPoint().ScalarBaseMult(scalar)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
return curve.pointToAffine(p)
|
||||
}
|
||||
|
||||
// CombinedMult returns [s1]G + [s2]P where G is the generator. It's used
|
||||
// through an interface upgrade in crypto/ecdsa.
|
||||
func (curve *sm2Curve) CombinedMult(Px, Py *big.Int, s1, s2 []byte) (x, y *big.Int) {
|
||||
s1 = curve.normalizeScalar(s1)
|
||||
q, err := curve.newPoint().ScalarBaseMult(s1)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
p, err := curve.pointFromAffine(Px, Py)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: CombinedMult was called on an invalid point")
|
||||
}
|
||||
s2 = curve.normalizeScalar(s2)
|
||||
p, err = p.ScalarMult(p, s2)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
return curve.pointToAffine(p.Add(p, q))
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
if len(data) == 0 || data[0] != 4 {
|
||||
return nil, nil
|
||||
}
|
||||
// Use SetBytes to check that data encodes a valid point.
|
||||
_, err := curve.newPoint().SetBytes(data)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
// We don't use pointToAffine because it involves an expensive field
|
||||
// inversion to convert from Jacobian to affine coordinates, which we
|
||||
// already have.
|
||||
byteLen := (curve.CurveParams.BitSize + 7) / 8
|
||||
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(data[1+byteLen:])
|
||||
return x, y
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) UnmarshalCompressed(data []byte) (x, y *big.Int) {
|
||||
if len(data) == 0 || (data[0] != 2 && data[0] != 3) {
|
||||
return nil, nil
|
||||
}
|
||||
p, err := curve.newPoint().SetBytes(data)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return curve.pointToAffine(p)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user