package implicitcert import ( "fmt" "io" "math/big" "xdx.jelly/xgcl/sm/sm2" "xdx.jelly/xgcl/sm/sm3" ) var ( ErrClientGenerateAgreementData = fmt.Errorf("client GenerateAgreementData error") errZeroPrivateKey = fmt.Errorf("private key got zero") ) type UserKey struct { d *sm2.PrivateKey // user's private key // w sm2.PublicKey // declare public key } func NewUserKey() *UserKey { return &UserKey{} } // GeneratePartialKey generate UserKey.d and partial public key U. // Then user should send ID and U to kgc. // The Input r should be a random number Reader. // r could use grand.Reader, or a wrapper of random generator from hard ware. // If want pass in a b of []byte slice, use grand.NewReaderFromBytes(b) to turn b to a // Reader: // b := []byte{...} // pk,err := u.GeneratePartialKey(grand.NewReaderFromBytes(b)) func (uk *UserKey) GeneratePartialKey(r io.Reader) (*sm2.PublicKey, error) { rnd := make([]byte, sm2.ByteSize()) _, err := r.Read(rnd) if err != nil { return nil, err } uk.d, _ = sm2.GenPrivateKey(rnd) u := sm2.GenPublicKey(uk.d) return u, nil } // GeneratePrivateKey generate user's privatekey and the declare public key // t - KGC generated partial private key for user func (uk *UserKey) GeneratePrivateKey(kgcGeneratedUserPartialPrivateKey *sm2.PrivateKey) (userPrivateKey *sm2.PrivateKey, err error) { d := new(big.Int) d.Add(uk.d.D, kgcGeneratedUserPartialPrivateKey.D) ret := d.Cmp(sm2.OrderN()) if ret == 0 { return nil, errZeroPrivateKey } if ret > 0 { d.Sub(d, sm2.OrderN()) } return &sm2.PrivateKey{D: d}, nil } // VerifyUserKeyPair verify the private key and declare public key are correct func VerifyUserKeyPair( id []byte, userPrivateKey *sm2.PrivateKey, userDeclarePublicKey *sm2.PublicKey, kgcPublicKey *sm2.PublicKey) bool { return sm2.VerifyKeyPair(userPrivateKey, RestoreUserPublicKey(id, userDeclarePublicKey, kgcPublicKey)) } // RestoreUserPublicKey restore user's public key from id, kgc's public key and user's // declare public key func RestoreUserPublicKey( id []byte, userDeclarePublicKey *sm2.PublicKey, kgcPublicKey *sm2.PublicKey) *sm2.PublicKey { h := sm2.PreComputeWithIdAndPubkey(id, kgcPublicKey) lambda := sm3.Sum(userDeclarePublicKey.Bytes(), h) x1, y1 := sm2.Curve().ScalarMult(kgcPublicKey.X, kgcPublicKey.Y, lambda[:]) x1, y1 = sm2.Curve().Add(x1, y1, userDeclarePublicKey.X, userDeclarePublicKey.Y) return &sm2.PublicKey{X: x1, Y: y1} }