func (publicKey *PublicKey) Gamma() *big.Int {
	return new(big.Int).Add(publicKey.N, one)
}
Gamma returns N+1
package paillier
import (
	"errors"
	"fmt"
	gmath "math"
	"math/big"
	"runtime"
	"strconv"
	"time"
	"github.com/otiai10/primes"
	"github.com/binance-chain/tss-lib/common"
	crypto2 "github.com/binance-chain/tss-lib/crypto"
)
const (
	ProofIters         = 13
	verifyPrimesUntil  = 1000  
	pQBitLenDifference = 3     
)
type (
	PublicKey struct {
		N *big.Int
	}
	PrivateKey struct {
		PublicKey
		LambdaN,  
		PhiN *big.Int  
	}
	Proof [ProofIters]*big.Int
)
var (
	ErrMessageTooLong = fmt.Errorf("the message is too large or < 0")
	zero = big.NewInt(0)
	one  = big.NewInt(1)
)
func init() {
	_ = primes.Globally.Until(verifyPrimesUntil)
}
func GenerateKeyPair(modulusBitLen int, timeout time.Duration, optionalConcurrency ...int) (privateKey *PrivateKey, publicKey *PublicKey, err error) {
	var concurrency int
	if 0 < len(optionalConcurrency) {
		if 1 < len(optionalConcurrency) {
			panic(errors.New("GeneratePreParams: expected 0 or 1 item in `optionalConcurrency`"))
		}
		concurrency = optionalConcurrency[0]
	} else {
		concurrency = runtime.NumCPU()
	}
	var P, Q, N *big.Int
	{
		tmp := new(big.Int)
		for {
			sgps, err := common.GetRandomSafePrimesConcurrent(modulusBitLen/2, 2, timeout, concurrency)
			if err != nil {
				return nil, nil, err
			}
			P, Q = sgps[0].SafePrime(), sgps[1].SafePrime()
			if tmp.Sub(P, Q).BitLen() >= (modulusBitLen/2)-pQBitLenDifference {
				break
			}
		}
		N = tmp.Mul(P, Q)
	}
	PMinus1, QMinus1 := new(big.Int).Sub(P, one), new(big.Int).Sub(Q, one)
	phiN := new(big.Int).Mul(PMinus1, QMinus1)
	gcd := new(big.Int).GCD(nil, nil, PMinus1, QMinus1)
	lambdaN := new(big.Int).Div(phiN, gcd)
	publicKey = &PublicKey{N: N}
	privateKey = &PrivateKey{PublicKey: *publicKey, LambdaN: lambdaN, PhiN: phiN}
	return
}
func (publicKey *PublicKey) EncryptAndReturnRandomness(m *big.Int) (c *big.Int, x *big.Int, err error) {
	if m.Cmp(zero) == -1 || m.Cmp(publicKey.N) != -1 {  
		return nil, nil, ErrMessageTooLong
	}
	x = common.GetRandomPositiveRelativelyPrimeInt(publicKey.N)
	N2 := publicKey.NSquare()
	Gm := new(big.Int).Exp(publicKey.Gamma(), m, N2)
	xN := new(big.Int).Exp(x, publicKey.N, N2)
	c = common.ModInt(N2).Mul(Gm, xN)
	return
}
func (publicKey *PublicKey) Encrypt(m *big.Int) (c *big.Int, err error) {
	c, _, err = publicKey.EncryptAndReturnRandomness(m)
	return
}
func (publicKey *PublicKey) HomoMult(m, c1 *big.Int) (*big.Int, error) {
	if m.Cmp(zero) == -1 || m.Cmp(publicKey.N) != -1 {  
		return nil, ErrMessageTooLong
	}
	N2 := publicKey.NSquare()
	if c1.Cmp(zero) == -1 || c1.Cmp(N2) != -1 {  
		return nil, ErrMessageTooLong
	}
	return common.ModInt(N2).Exp(c1, m), nil
}
func (publicKey *PublicKey) HomoAdd(c1, c2 *big.Int) (*big.Int, error) {
	N2 := publicKey.NSquare()
	if c1.Cmp(zero) == -1 || c1.Cmp(N2) != -1 {  
		return nil, ErrMessageTooLong
	}
	if c2.Cmp(zero) == -1 || c2.Cmp(N2) != -1 {  
		return nil, ErrMessageTooLong
	}
	return common.ModInt(N2).Mul(c1, c2), nil
}
func (publicKey *PublicKey) NSquare() *big.Int {
	return new(big.Int).Mul(publicKey.N, publicKey.N)
}
func (publicKey *PublicKey) AsInts() []*big.Int {
	return []*big.Int{publicKey.N, publicKey.Gamma()}
}