gt: 			mes = mes.multiply(W);
context: package model;
  
  import java.math.BigInteger;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Random;
  
  
  import toolbox.Cipher;
  import toolbox.Key;
  import toolbox.RSA;
  
  public class Member {
  	protected BigInteger s;
  	protected BigInteger h;
  	private ArrayList<BigInteger> Fx;
  	private BigInteger ss;
  	private Group myGroup;
  	private HashMap<String, String> sessionInfo;
  	private HashMap<String, ArrayList<Key>> publicKeys;
  	private HashMap<String, ArrayList<Key>> privateKeys;
  
  	public Member(Group myGroup) {
  		this.myGroup = myGroup;
  		this.sessionInfo = new HashMap<>();
  		this.publicKeys = new HashMap<>();
  		this.privateKeys =  new HashMap<>();
  	}
  
  	public void generateKeys() throws Exception {
  		if (s != null && h != null)
  			return;
  		ArrayList<BigInteger> params = myGroup.getParams();
  		ArrayList<Key> publicKeys = new ArrayList<>();
  		ArrayList<Key> privateKeys = Cipher.KeyGeneration("DLB", publicKeys, params);
  		s = Key.findKey("s", privateKeys);
  		h = Key.findKey("h", publicKeys);
  	}
  
  	public void generateFx() throws Exception {
  		if (Fx != null)
  			return;
  		int t = myGroup.getTreshold();
  		BigInteger q = getQ();
  		Fx = new ArrayList<>();
  		if (s == null)
  			generateKeys();
  		Fx.add(s);
  		for (int j = 1; j < t; j++) {
  			BigInteger fij;
  			do {
  				fij = new BigInteger(new Random().nextInt(q.bitLength()) + 1, new Random());
  			} while (fij.compareTo(((q).subtract(BigInteger.ONE)).subtract(BigInteger.ONE)) != -1);
  
  			Fx.add(fij);
  		}
  	}
  
  	public BigInteger calculateF(int j) throws Exception {
  		if(j<1 || j>myGroup.getSize())
  			return null;
  		BigInteger q = getQ();
  		if (Fx == null)
  			generateFx();
  		BigInteger result = Fx.get(0);
  		BigInteger bigIntJ = BigInteger.valueOf(j);
  		for (int k = 1; k < Fx.size(); k++) {
  			BigInteger bigIntK = BigInteger.valueOf(k);
  			BigInteger term = ((Fx.get(k)).multiply(bigIntJ.modPow(bigIntK, q))).mod(q);
  			result = (result.add(term)).mod(q);
  		}
  		return result;
  		//return encrypt(result.toString());
  	}
  
  	public void generateSs() throws Exception {
  		if (ss != null)
  			return;
  		BigInteger q = getQ();
  		ss = BigInteger.ZERO;
  		ArrayList<Member> members = myGroup.getMembers();
  		int i = members.indexOf(this);
  		for (Member member : members) {
  			/*tlsEstablishment(member);
  			BigInteger bInt = new BigInteger(decrypt(member.calculateF(i + 1)));
  			ss = (ss.add(bInt)).mod(q);
  			closeSession(member);*/
  			BigInteger bInt = member.calculateF(i+1);
  			ss = (ss.add(bInt)).mod(q);
  		}
  	}
  
  	private BigInteger getQ() {
  		ArrayList<BigInteger> params = myGroup.getParams();
  		return params.get(1);
  	}
  
  	protected BigInteger getP() {
  		ArrayList<BigInteger> params = myGroup.getParams();
  		return params.get(0);
  	}
  
  	private BigInteger getG() {
  		ArrayList<BigInteger> params = myGroup.getParams();
  		return params.get(2);
  	}
  
  	public BigInteger getH() throws Exception {
  		if (h == null)
  			generateKeys();
  		return h;
  	}
  
  	protected BigInteger getW(BigInteger r) throws Exception {
  		BigInteger p = getP();
  		if (ss == null)
  			generateSs();
  		BigInteger res = r.modPow(ss, p);
  		return res;
  		//return encrypt(res);
  	}
  
  	public String decryptGroup(BigInteger X, BigInteger Y, ArrayList<Integer> indexes) throws Exception {
  
  		if (indexes.size() < myGroup.getTreshold())
  			return "index less than threshold";
  
  		ArrayList<Member> members = myGroup.getMembers();
  		ArrayList<BigInteger> ind = new ArrayList<>();
  		for (Integer i : indexes) {
  			ind.add(BigInteger.valueOf(i + 1));
  		}
  		BigInteger q = getQ();
  		BigInteger p = getP();
  		BigInteger mes = BigInteger.ONE;
  		for (BigInteger j : ind) {
  			BigInteger lambda = BigInteger.ONE;
  			for (BigInteger k : ind) {
  				if (k != j) {
  					BigInteger term = k.multiply((k.subtract(j)).modInverse(q));
  					lambda = lambda.multiply(term);
  					lambda = lambda.mod(q);
  				}
  			}
  			Member m = members.get(j.intValue() - 1);
  			//m.generateSs();
  			//tlsEstablishment(m);
  			//String decryptedW = decrypt(m.getW(X));
  			//BigInteger Wterm = new BigInteger(decryptedW);
  			BigInteger W = m.getW(X);
  			//closeSession(m);
  			W = W.modPow(lambda, p);
  			mes = mes.multiply(W);
  			mes = mes.mod(p);
  		}
  		mes = mes.modInverse(p);
  		mes = Y.multiply(mes); mes = mes.mod(p);
  		// TODO: Check if toString works properly. Otherwise use byteArray[]
  		StringBuilder sb = RSA.HexToText(mes.toString(16));
  		return sb.toString();
  	}
  	
  	public String decryptWithVerifierGroup(BigInteger X, BigInteger Y, ArrayList<Integer> indexes) throws Exception {
  
  		if (indexes.size() < myGroup.getTreshold())
  			return "index less than threshold";
  
  		ArrayList<Member> members = myGroup.getMembers();
  		ArrayList<BigInteger> ind = new ArrayList<>();
  		for (Integer i : indexes) {
  			ind.add(BigInteger.valueOf(i + 1));
  		}
  		BigInteger q = getQ();
  		BigInteger p = getP();
  		BigInteger mes = BigInteger.ONE;
  		for (BigInteger j : ind) {
  			BigInteger lambda = BigInteger.ONE;
  			for (BigInteger k : ind) {
  				if (k != j) {
  					BigInteger term = k.multiply((k.subtract(j)).modInverse(q));
  					lambda = lambda.multiply(term);
  					lambda = lambda.mod(q);
  				}
  			}
  			Member m = members.get(j.intValue() - 1);
  			//m.generateSs();
  			//tlsEstablishment(m);
  			//String decryptedW = decrypt(m.getW(X));
  			//BigInteger Wterm = new BigInteger(decryptedW);
  			BigInteger W = m.getW(X);
  			BigInteger u = m.getgToPowSS();
  			BigInteger c;
  			do {
  				c = new BigInteger(new Random().nextInt(q.bitLength()) + 1, new Random());
  			} while (c.compareTo(q) >= 0);
  			ArrayList<BigInteger> abz = m.getABZ(c, X);
  			BigInteger a = abz.get(0);
  			BigInteger b = abz.get(1);
  			BigInteger z = abz.get(2);
  			if(!(getG().modPow(z, p)).equals(a.multiply(u.modPow(c, p)).mod(p)))
  				return "There is a cheater";
  			if(!(X.modPow(z, p)).equals(b.multiply(W.modPow(c, p)).mod(p)))
  				return "There is a cheater";
  			//closeSession(m);
  			W = W.modPow(lambda, p);
  