* <tt>compactPublicKey()</tt>
*/
private void computePublicKey()
{
ComputeInField c = new ComputeInField();
int rows = this.vi[this.vi.length - 1] - this.vi[0];
int vars = this.vi[this.vi.length - 1];
// Fpub
short[][][] coeff_quadratic_3dim = new short[rows][vars][vars];
this.pub_singular = new short[rows][vars];
this.pub_scalar = new short[rows];
// Coefficients of layers of Private Key F
short[][][] coeff_alpha;
short[][][] coeff_beta;
short[][] coeff_gamma;
short[] coeff_eta;
// Needed for counters;
int oils = 0;
int vins = 0;
int crnt_row = 0; // current row (polynomial)
short vect_tmp[] = new short[vars]; // vector tmp;
short sclr_tmp = 0;
// Composition of F and L2: Insert L2 = A2*x+b2 in F
for (int l = 0; l < this.layers.length; l++)
{
// get coefficients of current layer
coeff_alpha = this.layers[l].getCoeffAlpha();
coeff_beta = this.layers[l].getCoeffBeta();
coeff_gamma = this.layers[l].getCoeffGamma();
coeff_eta = this.layers[l].getCoeffEta();
oils = coeff_alpha[0].length;// this.layers[l].getOi();
vins = coeff_beta[0].length;// this.layers[l].getVi();
// compute polynomials of layer
for (int p = 0; p < oils; p++)
{
// multiply alphas
for (int x1 = 0; x1 < oils; x1++)
{
for (int x2 = 0; x2 < vins; x2++)
{
// multiply polynomial1 with polynomial2
vect_tmp = c.multVect(coeff_alpha[p][x1][x2],
this.A2[x1 + vins]);
coeff_quadratic_3dim[crnt_row + p] = c.addSquareMatrix(
coeff_quadratic_3dim[crnt_row + p], c
.multVects(vect_tmp, this.A2[x2]));
// mul poly1 with scalar2
vect_tmp = c.multVect(this.b2[x2], vect_tmp);
this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
this.pub_singular[crnt_row + p]);
// mul scalar1 with poly2
vect_tmp = c.multVect(coeff_alpha[p][x1][x2],
this.A2[x2]);
vect_tmp = c.multVect(b2[x1 + vins], vect_tmp);
this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
this.pub_singular[crnt_row + p]);
// mul scalar1 with scalar2
sclr_tmp = GF2Field.multElem(coeff_alpha[p][x1][x2],
this.b2[x1 + vins]);
this.pub_scalar[crnt_row + p] = GF2Field.addElem(
this.pub_scalar[crnt_row + p], GF2Field
.multElem(sclr_tmp, this.b2[x2]));
}
}
// multiply betas
for (int x1 = 0; x1 < vins; x1++)
{
for (int x2 = 0; x2 < vins; x2++)
{
// multiply polynomial1 with polynomial2
vect_tmp = c.multVect(coeff_beta[p][x1][x2],
this.A2[x1]);
coeff_quadratic_3dim[crnt_row + p] = c.addSquareMatrix(
coeff_quadratic_3dim[crnt_row + p], c
.multVects(vect_tmp, this.A2[x2]));
// mul poly1 with scalar2
vect_tmp = c.multVect(this.b2[x2], vect_tmp);
this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
this.pub_singular[crnt_row + p]);
// mul scalar1 with poly2
vect_tmp = c.multVect(coeff_beta[p][x1][x2],
this.A2[x2]);
vect_tmp = c.multVect(this.b2[x1], vect_tmp);
this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
this.pub_singular[crnt_row + p]);
// mul scalar1 with scalar2
sclr_tmp = GF2Field.multElem(coeff_beta[p][x1][x2],
this.b2[x1]);
this.pub_scalar[crnt_row + p] = GF2Field.addElem(
this.pub_scalar[crnt_row + p], GF2Field
.multElem(sclr_tmp, this.b2[x2]));
}
}
// multiply gammas
for (int n = 0; n < vins + oils; n++)
{
// mul poly with scalar
vect_tmp = c.multVect(coeff_gamma[p][n], this.A2[n]);
this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
this.pub_singular[crnt_row + p]);
// mul scalar with scalar
this.pub_scalar[crnt_row + p] = GF2Field.addElem(
this.pub_scalar[crnt_row + p], GF2Field.multElem(
coeff_gamma[p][n], this.b2[n]));
}
// add eta
this.pub_scalar[crnt_row + p] = GF2Field.addElem(
this.pub_scalar[crnt_row + p], coeff_eta[p]);
}
crnt_row = crnt_row + oils;
}
// Apply L1 = A1*x+b1 to composition of F and L2
{
// temporary coefficient arrays
short[][][] tmp_c_quad = new short[rows][vars][vars];
short[][] tmp_c_sing = new short[rows][vars];
short[] tmp_c_scal = new short[rows];
for (int r = 0; r < rows; r++)
{
for (int q = 0; q < A1.length; q++)
{
tmp_c_quad[r] = c.addSquareMatrix(tmp_c_quad[r], c
.multMatrix(A1[r][q], coeff_quadratic_3dim[q]));
tmp_c_sing[r] = c.addVect(tmp_c_sing[r], c.multVect(
A1[r][q], this.pub_singular[q]));
tmp_c_scal[r] = GF2Field.addElem(tmp_c_scal[r], GF2Field
.multElem(A1[r][q], this.pub_scalar[q]));
}
tmp_c_scal[r] = GF2Field.addElem(tmp_c_scal[r], b1[r]);