package concentration import ( "encoding/binary" "fmt" "hash/crc32" "math/big" "xdx.jelly/xgcl/gmath" "xdx.jelly/xgcl/grand" "xdx.jelly/xgcl/sm/sm2" ) var ( ErrServerKeyGen = fmt.Errorf("GenerateAgreementData error") ErrInputDataInvalid = fmt.Errorf("input data invalid") ErrServerSignError = fmt.Errorf("server sign error") ) type ServerKeyGenContext struct { d *sm2.PrivateKey u *sm2.PublicKey clientPPub *sm2.PublicKey //sk *sm2.PrivateKey //pk *sm2.PublicKey } func NewServerKeyGenContext() *ServerKeyGenContext { return &ServerKeyGenContext{ d: sm2.NewPrivateKey(), u: sm2.NewPublicKey(), } } // GenerateAgreementData 根据客户端发送的数据生成临时数据并发送给客户度 func (s *ServerKeyGenContext) GenerateAgreementData(rnd32 []byte) ([]byte, error) { var data []byte var err error if len(rnd32) < sm2.ByteSize() { rnd32 = grand.GetRandom(sm2.ByteSize()) } if s.d, err = sm2.GenPrivateKey(rnd32); err != nil { return []byte{}, err } s.u = sm2.GenPublicKey(s.d) if data, err = s.u.MarshalBinary(); err != nil { return []byte{}, ErrServerKeyGen } return data, nil } // ComputeKeyPair clientData = ppub_x || ppub_y || W_x || W_y || t || check // out key pair func (s *ServerKeyGenContext) ComputeKeyPair(clientData []byte, clientID []byte) (*sm2.PrivateKey, *sm2.PublicKey, error) { if len(clientData) < 64+64+32+4 { return nil, nil, ErrInputDataInvalid } checkSumShouldBe := crc32.ChecksumIEEE(clientData[:64+64+32]) checkSum := binary.BigEndian.Uint32(clientData[128+32:]) if checkSum != checkSumShouldBe { return nil, nil, ErrInputDataInvalid } sk := sm2.NewPrivateKey() sk.SetBytes(clientData[128 : 128+32]) sk.D.Add(sk.D, s.d.D) sk.D.Mod(sk.D, sm2.OrderN()) if gmath.IsBigInt0(sk.D) { return nil, nil, ErrServerKeyGen } pk := sm2.GenPublicKey(sk) // //ppub := sm2.NewPublicKey() //if err := ppub.UnmarshalBinary(clientData); err != nil{ // return nil, nil, ErrServerKeyGen //} // //digest := sm3.Sum(clientData[64:128],sm2.PreComputeWithIdAndPubkey(clientID, ppub)) //PublicKey := sm2.Curve256.ScalarMult(ppub.X, ppub.Y, digest[:]) return sk, pk, nil } func (s *ServerKeyGenContext) Clear() { s.d.Clear() } type ServerSignContext struct { k1 *sm2.PrivateKey u *sm2.PublicKey clientPPub *sm2.PublicKey } func NewServerSignContext() *ServerSignContext { return &ServerSignContext{ sm2.NewPrivateKey(), sm2.NewPublicKey(), sm2.NewPublicKey(), } } func (s *ServerSignContext) MarshalBinary() ([]byte, error) { if s.k1 == nil { s.k1 = sm2.NewPrivateKey() } if s.u == nil { s.u = sm2.NewPublicKey() } if s.clientPPub == nil { s.clientPPub = sm2.NewPublicKey() } r := make([]byte, 0, 3*4+(4+sm2.ECCRefMaxLen)+(4+2*sm2.ECCRefMaxLen)+(4+2*sm2.ECCRefMaxLen)) var buf []byte var uintBuf = make([]byte, 4) var err error if buf, err = s.k1.MarshalBinary(); err != nil { return nil, err } binary.BigEndian.PutUint32(uintBuf, uint32(len(buf))) r = append(r, uintBuf...) r = append(r, buf...) if buf, err = s.u.MarshalBinary(); err != nil { return nil, err } binary.BigEndian.PutUint32(uintBuf, uint32(len(buf))) r = append(r, uintBuf...) r = append(r, buf...) if buf, err = s.clientPPub.MarshalBinary(); err != nil { return nil, err } binary.BigEndian.PutUint32(uintBuf, uint32(len(buf))) r = append(r, uintBuf...) r = append(r, buf...) return r, nil } func (s *ServerSignContext) UnmarshalBinary(data []byte) error { if s.k1 == nil { s.k1 = sm2.NewPrivateKey() } if s.u == nil { s.u = sm2.NewPublicKey() } if s.clientPPub == nil { s.clientPPub = sm2.NewPublicKey() } var err error if len(data) < 4 { return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary") } size := binary.BigEndian.Uint32(data) data = data[4:] if uint32(len(data)) < size { return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary") } if err = s.k1.UnmarshalBinary(data[:size]); err != nil { return err } data = data[size:] if len(data) < 4 { return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary") } size = binary.BigEndian.Uint32(data) data = data[4:] if uint32(len(data)) < size { return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary") } if err = s.u.UnmarshalBinary(data[:size]); err != nil { return err } data = data[size:] if len(data) < 4 { return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary") } size = binary.BigEndian.Uint32(data) data = data[4:] if uint32(len(data)) < size { return fmt.Errorf("invalid input of ServerSignContext.UnmarshalBinary") } if err = s.clientPPub.UnmarshalBinary(data[:size]); err != nil { return err } return nil } func (s *ServerSignContext) GenerateSignData(rnd32 []byte) ([]byte, error) { var data []byte = make([]byte, 0, 64) var err error if len(rnd32) < sm2.ByteSize() { rnd32 = grand.GetRandom(sm2.ByteSize()) } if s.k1, err = sm2.GenPrivateKey(rnd32); err != nil { } s.u = sm2.GenPublicKey(s.k1) data = append(data, gmath.BigIntToNByte(s.u.X, 32)...) data = append(data, gmath.BigIntToNByte(s.u.Y, 32)...) return data, nil } // Sign generate signature // input: clientData 32 bytes func (ssc *ServerSignContext) Sign(clientData []byte, e []byte, sk *sm2.PrivateKey) (*sm2.Signature, error) { k := new(big.Int) k.SetBytes(clientData) k.Mul(k, ssc.k1.D) k.Mod(k, sm2.OrderN()) x, _ := sm2.Curve256.ScalarBaseMult(k.Bytes()) r := new(big.Int) r.SetBytes(e) r.Add(x, r) r.Mod(r, sm2.OrderN()) s := new(big.Int) s.Set(sk.D) s.Add(s, gmath.BigInt1) s.ModInverse(s, sm2.OrderN()) k.Add(k, r) s.Mul(s, k) s.Sub(s, r) s.Mod(s, sm2.OrderN()) sig := &sm2.Signature{ R: r, S: s, } return sig, nil } func (ssc *ServerSignContext) Clear() { ssc.k1.Clear() }