func (csp *CSPaillierEC) GetProofRandomData(u, e, label *big.Int) (*big.Int, *big.Int,
	*big.Int, *Point, *big.Int, error) {
	two := big.NewInt(2)
	t1 := new(big.Int).Exp(two, big.NewInt(int64(csp.PubKey.K+csp.PubKey.K1-2)), nil)
	b1 := new(big.Int).Mul(csp.PubKey.N, t1)
	r1, err := xlabcommon.GetRandomIntFromRange(new(big.Int).Neg(b1), b1)
	if err != nil {
		return nil, nil, nil, nil, nil, err
	}
	b2 := new(big.Int).Mul(csp.PubKey.VerifiableEncGroupN, t1)
	s1, err := xlabcommon.GetRandomIntFromRange(new(big.Int).Neg(b2), b2)
	if err != nil {
		return nil, nil, nil, nil, nil, err
	}
	t2 := new(big.Int).Exp(two, big.NewInt(int64(csp.PubKey.K+csp.PubKey.K1)), nil)
	b3 := new(big.Int).Mul(csp.PubKey.Gamma.N, t2)
	m1, err := xlabcommon.GetRandomIntFromRange(new(big.Int).Neg(b3), b3)
	if err != nil {
		return nil, nil, nil, nil, nil, err
	}
	n2 := new(big.Int).Mul(csp.PubKey.N, csp.PubKey.N)
	u1 := xlabcommon.Exponentiate(csp.PubKey.G, new(big.Int).Mul(big.NewInt(2), r1), n2)
	h := new(big.Int).Add(csp.PubKey.N, big.NewInt(1))  
	e1Part1 := xlabcommon.Exponentiate(csp.PubKey.Y1, new(big.Int).Mul(big.NewInt(2), r1), n2)
	e1Part2 := xlabcommon.Exponentiate(h, new(big.Int).Mul(big.NewInt(2), m1), n2)
	e1 := new(big.Int).Mul(e1Part1, e1Part2)
	e1.Mod(e1, n2)
	hashNum := xlabcommon.Hash(u, e, label)
	v11 := new(big.Int).Exp(csp.PubKey.Y3, hashNum, n2)
	v11.Mul(v11, csp.PubKey.Y2)
	v11.Mod(v11, n2)
	v1 := xlabcommon.Exponentiate(v11, new(big.Int).Mul(big.NewInt(2), r1), n2)
	delta1 := pt(csp.PubKey.Gamma.ScalarBaseMult(m1.Bytes()))
	l11 := xlabcommon.Exponentiate(csp.PubKey.VerifiableEncGroupG1, m1,
		csp.PubKey.VerifiableEncGroupN)
	l12 := xlabcommon.Exponentiate(csp.PubKey.VerifiableEncGroupH1, s1,
		csp.PubKey.VerifiableEncGroupN)
	l1 := new(big.Int).Mul(l11, l12)
	l1.Mod(l1, csp.PubKey.VerifiableEncGroupN)
	csp.proverRandomData.R1 = r1
	csp.proverRandomData.S1 = s1
	csp.proverRandomData.M1 = m1
	return u1, e1, v1, &delta1, l1, nil
}
Prover (encryptor) should use this function to generate values for the first sigma protocol message.
package pvss
import (
	"fmt"
	"log"
	"math/big"
	"github.com/torusresearch/torus-common/common"
	"github.com/torusresearch/torus-common/secp256k1"
	xlabcommon "github.com/xlab-si/emmy/crypto/common"
	"github.com/xlab-si/emmy/crypto/qr"
)
type DLEQProof struct {
	C  big.Int       
	R  big.Int       
	VG common.Point  
	VH common.Point  
}
func GenerateDLEQProof(G common.Point, H common.Point, x big.Int) (p *DLEQProof, xG common.Point, xH common.Point) {
	xG = common.BigIntToPoint(secp256k1.Curve.ScalarBaseMult(x.Bytes()))
	xH = common.BigIntToPoint(secp256k1.Curve.ScalarMult(&H.X, &H.Y, x.Bytes()))
	v := RandomBigInt()
	vG := common.BigIntToPoint(secp256k1.Curve.ScalarBaseMult(v.Bytes()))
	vH := common.BigIntToPoint(secp256k1.Curve.ScalarMult(&H.X, &H.Y, v.Bytes()))
	tempBytes := make([]byte, 0)
	for _, element := range [4]common.Point{xG, xH, vG, vH} {
		tempBytes = append(tempBytes, element.X.Bytes()...)
		tempBytes = append(tempBytes, element.Y.Bytes()...)
	}
	hash := secp256k1.Keccak256(tempBytes)
	c := new(big.Int).SetBytes(hash)
	c.Mod(c, secp256k1.GeneratorOrder)
	r := new(big.Int)
	r.Mul(&x, c)
	r.Sub(v, r)
	r.Mod(r, secp256k1.GeneratorOrder)
	p = &DLEQProof{
		C:  *c,
		R:  *r,
		VG: vG,
		VH: vH,
	}
	return
}
func (p *DLEQProof) VerifyDLEQProof(G common.Point, H common.Point, xG common.Point, xH common.Point) bool {
	rG := common.BigIntToPoint(secp256k1.Curve.ScalarMult(&G.X, &G.Y, p.R.Bytes()))
	rH := common.BigIntToPoint(secp256k1.Curve.ScalarMult(&H.X, &H.Y, p.R.Bytes()))
	cxG := common.BigIntToPoint(secp256k1.Curve.ScalarMult(&xG.X, &xG.Y, p.C.Bytes()))
	cxH := common.BigIntToPoint(secp256k1.Curve.ScalarMult(&xH.X, &xH.Y, p.C.Bytes()))
	a := common.BigIntToPoint(secp256k1.Curve.Add(&rG.X, &rG.Y, &cxG.X, &cxG.Y))
	b := common.BigIntToPoint(secp256k1.Curve.Add(&rH.X, &rH.Y, &cxH.X, &cxH.Y))
	if !(p.VG.X.Cmp(&a.X) == 0 &&
		p.VG.Y.Cmp(&a.Y) == 0 &&
		p.VH.X.Cmp(&b.X) == 0 &&
		p.VH.Y.Cmp(&b.Y) == 0) {
		return false
	} else {
		return true
	}
}
type Point struct {
	X big.Int
	Y big.Int
}
func pt(x, y *big.Int) Point {
	return Point{
		X: *x,
		Y: *y,
	}
}
type CSPaillierEC struct {
	SecParams *CSPaillierECSecParams
	n1        *big.Int  
	PubKey    *CSPaillierECPubKey
	SecKey    *CSPaillierECSecKey
	verifierRandomData *CSPaillierECVerifierRandomData
	proverRandomData *CSPaillierECProverRandomData
	proverEncData    *CSPaillierECProverEncData
	verifierEncData  *CSPaillierECVerifierEncData
}
type CSPaillierECSecParams struct {
	L        int  
	RoLength int  
	K        int  
	K1       int  
}
type CSPaillierECSecKey struct {
	N  *big.Int
	G  *big.Int
	X1 *big.Int
	X2 *big.Int
	X3 *big.Int
	Gamma                *secp256k1.KoblitzCurve  
	VerifiableEncGroupN  *big.Int
	VerifiableEncGroupG1 *big.Int
	VerifiableEncGroupH1 *big.Int
	K                    int
	K1                   int
}
type CSPaillierECPubKey struct {
	N  *big.Int
	G  *big.Int
	Y1 *big.Int
	Y2 *big.Int
	Y3 *big.Int
	Gamma                *secp256k1.KoblitzCurve  
	VerifiableEncGroupN  *big.Int
	VerifiableEncGroupG1 *big.Int
	VerifiableEncGroupH1 *big.Int
	K                    int
	K1                   int
}
type CSPaillierECProverRandomData struct {
	S  *big.Int
	R1 *big.Int
	S1 *big.Int
	M1 *big.Int
}
type CSPaillierECVerifierRandomData struct {
	L      *big.Int
	U1     *big.Int
	E1     *big.Int
	V1     *big.Int
	Delta1 *Point
	L1     *big.Int
	C      *big.Int
}
type CSPaillierECProverEncData struct {
	R *big.Int
	M *big.Int
}
type CSPaillierECVerifierEncData struct {
	U     *big.Int
	E     *big.Int
	V     *big.Int
	Label *big.Int
	Delta *Point
}
func NewCSPaillierEC(secParams *CSPaillierECSecParams) *CSPaillierEC {
	cspaillier := CSPaillierEC{
		SecParams: secParams,
	}
	cspaillier.generateKey()
	return &cspaillier
}
func NewCSPaillierECFromSecKey(secKey *CSPaillierECSecKey) (*CSPaillierEC, error) {
	return &CSPaillierEC{
		SecKey: secKey,
		PubKey: &CSPaillierECPubKey{  
			N: secKey.N,
		},
	}, nil
}
func NewCSPaillierECFromPubKey(pubKey *CSPaillierECPubKey) *CSPaillierEC {
	return &CSPaillierEC{
		PubKey: pubKey,
	}
}
func (csp *CSPaillierEC) Encrypt(m, label *big.Int) (*big.Int, *big.Int, *big.Int, error) {
	if m.Cmp(csp.PubKey.N) >= 0 {
		err := fmt.Errorf("msg is too big")
		return nil, nil, nil, err
	}
	b := new(big.Int).Div(csp.PubKey.N, big.NewInt(4))
	r := xlabcommon.GetRandomInt(b)
	n2 := new(big.Int).Mul(csp.PubKey.N, csp.PubKey.N)
	u := new(big.Int).Exp(csp.PubKey.G, r, n2)
	e1 := new(big.Int).Exp(csp.PubKey.Y1, r, n2)        
	h := new(big.Int).Add(csp.PubKey.N, big.NewInt(1))  
	e2 := new(big.Int).Exp(h, m, n2)                    
	e := new(big.Int).Mul(e1, e2)  
	e.Mod(e, n2)
	hashNum := xlabcommon.Hash(u, e, label)
	t := new(big.Int).Exp(csp.PubKey.Y3, hashNum, n2)  
	t.Mul(csp.PubKey.Y2, t)                            
	t.Exp(t, r, n2)                                    
	v, _ := csp.Abs(t)
	csp.proverEncData = &CSPaillierECProverEncData{
		R: r,
		M: m,
	}
	return u, e, v, nil
}
func (csp *CSPaillierEC) Decrypt(u, e, v, label *big.Int) (*big.Int, error) {
	vAbs, _ := csp.Abs(v)
	if v.Cmp(vAbs) != 0 {
		err := fmt.Errorf("v != abs(v)")
		return nil, err
	}
	hashNum := xlabcommon.Hash(u, e, label)
	t := new(big.Int).Mul(hashNum, csp.SecKey.X3)
	t.Add(csp.SecKey.X2, t)
	t.Mul(t, big.NewInt(2))
	n2 := new(big.Int).Mul(csp.PubKey.N, csp.PubKey.N)
	t.Exp(u, t, n2)
	t.Mod(t, n2)
	v2 := new(big.Int).Mul(v, v)
	v2.Mod(v2, n2)
	if t.Cmp(v2) != 0 {
		err := fmt.Errorf("CSPaillierEC decryption failed 1")
		return nil, err
	}
	ux1 := new(big.Int).Exp(u, csp.SecKey.X1, n2)  
	ux1Inv := new(big.Int).ModInverse(ux1, n2)     
	m1 := new(big.Int).Mul(e, ux1Inv)
	m1.Mod(m1, n2)
	m1min := new(big.Int).Sub(m1, big.NewInt(1))
	m1minModulo := new(big.Int).Mod(m1min, csp.PubKey.N)
	if m1minModulo.Cmp(big.NewInt(0)) != 0 {
		err := fmt.Errorf("CSPaillierEC decryption failed 2")
		return nil, err
	}
	m := new(big.Int).Div(m1min, csp.PubKey.N)
	return m, nil
}
func (csp *CSPaillierEC) Abs(a *big.Int) (*big.Int, error) {
	n2 := new(big.Int).Mul(csp.PubKey.N, csp.PubKey.N)
	if a.Cmp(n2) >= 0 {
		err := fmt.Errorf("value is too big for abs function")
		return nil, err
	}
	b := new(big.Int).Div(n2, big.NewInt(2))
	if a.Cmp(b) <= 0 {
		return a, nil
	} else {
		t := new(big.Int).Sub(n2, a)  
		return t, nil
	}
}
func (csp *CSPaillierEC) generateKey() {
	p1 := xlabcommon.GetGermainPrime(csp.SecParams.L)
	q1 := xlabcommon.GetGermainPrime(csp.SecParams.L)
	p := new(big.Int).Add(p1, p1)
	p.Add(p, big.NewInt(1))
	q := new(big.Int).Add(q1, q1)
	q.Add(q, big.NewInt(1))
	n := new(big.Int).Mul(p, q)
	csp.n1 = new(big.Int).Mul(p1, q1)
	n2 := new(big.Int).Mul(n, n)
	pubKey := CSPaillierECPubKey{
		N: n,
	}
	Gamma := secp256k1.Curve
	pubKey.Gamma = Gamma
	check1 := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(csp.SecParams.K)), nil)
	if check1.Cmp(p1) >= 0 || check1.Cmp(q1) >= 0 || check1.Cmp(Gamma.N) >= 0 {
		log.Fatal("Does not pass check 1: 2**K < min{p1, q1, ro}; ro is Gamma.N")
	}
	tmp := csp.SecParams.K + csp.SecParams.K1 + 3
	check2 := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(tmp)), nil)
	check2.Mul(check2, Gamma.N)
	if check2.Cmp(n) >= 0 {
		log.Fatal("Does not pass check 2: N < n2**(-K-K1-3)")
	}
	pubKey.K = csp.SecParams.K
	pubKey.K1 = csp.SecParams.K1
	primes := qr.NewRSASpecialPrimes(p, q, p1, q1)
	verifiableEncGroup, err := NewVerifiableEncGroupEC(primes)
	if err != nil {
		log.Fatal(err)
	}
	pubKey.VerifiableEncGroupN = verifiableEncGroup.N
	pubKey.VerifiableEncGroupG1 = verifiableEncGroup.G1
	pubKey.VerifiableEncGroupH1 = verifiableEncGroup.H1
	secretKey := CSPaillierECSecKey{
		N:  n,
		K:  csp.SecParams.K,
		K1: csp.SecParams.K1,
	}
	secretKey.Gamma = Gamma
	secretKey.VerifiableEncGroupN = verifiableEncGroup.N
	secretKey.VerifiableEncGroupG1 = verifiableEncGroup.G1
	secretKey.VerifiableEncGroupH1 = verifiableEncGroup.H1
	b := new(big.Int).Div(n2, big.NewInt(4))
	secretKey.X1 = xlabcommon.GetRandomInt(b)
	secretKey.X2 = xlabcommon.GetRandomInt(b)
	secretKey.X3 = xlabcommon.GetRandomInt(b)
	for {  
		g1 := xlabcommon.GetRandomInt(n2)
		gcd := new(big.Int).GCD(nil, nil, g1, n2)  
		if gcd.Cmp(big.NewInt(1)) == 0 {
			t := new(big.Int).Mul(big.NewInt(2), n)
			g := new(big.Int).Exp(g1, t, n2)
			pubKey.G = g
			secretKey.G = g
			break
		}
	}
	pubKey.Y1 = new(big.Int).Exp(pubKey.G, secretKey.X1, n2)
	pubKey.Y2 = new(big.Int).Exp(pubKey.G, secretKey.X2, n2)
	pubKey.Y3 = new(big.Int).Exp(pubKey.G, secretKey.X3, n2)
	csp.PubKey = &pubKey
	csp.SecKey = &secretKey
}
func (csp *CSPaillierEC) GetOpeningMsg(m *big.Int) (*big.Int, *Point) {
	b := new(big.Int).Div(csp.PubKey.VerifiableEncGroupN, big.NewInt(4))
	s := xlabcommon.GetRandomInt(b)
	t1 := new(big.Int).Exp(csp.PubKey.VerifiableEncGroupG1, m,
		csp.PubKey.VerifiableEncGroupN)
	t2 := new(big.Int).Exp(csp.PubKey.VerifiableEncGroupH1, s,
		csp.PubKey.VerifiableEncGroupN)
	l := new(big.Int).Mul(t1, t2)
	l.Mod(l, csp.PubKey.VerifiableEncGroupN)
	csp.proverRandomData = &CSPaillierECProverRandomData{
		S: s,
	}
	delta := pt(csp.PubKey.Gamma.ScalarBaseMult(m.Bytes()))
	return l, &delta
}