/// <summary> /// This function computes the public key from the private key. /// <para>The composition of F with L2 is computed, followed by applying L1 to the composition's result. /// The singular and scalar values constitute to the public key as is, the quadratic terms are compacted in CompactPublicKey.</para> /// </summary> private void ComputePublicKey() { ComputeInField cif = new ComputeInField(); int rows = _VI[_VI.Length - 1] - _VI[0]; int vars = _VI[_VI.Length - 1]; // Fpub short[][][] coeffQuadratic3d = ArrayUtils.CreateJagged<short[][][]>(rows, vars, vars); _pubSingular = ArrayUtils.CreateJagged<short[][]>(rows, vars); _pubScalar = new short[rows]; // Coefficients of layers of Private Key F short[][][] coeffAlpha; short[][][] coeffBeta; short[][] coeffGamma; short[] coeffEta; // Needed for counters; int oils = 0; int vins = 0; // current row (polynomial) int crntRow = 0; short[] vectTmp = new short[vars]; // vector tmp; short sclrTmp = 0; // Composition of F and L2: Insert L2 = A2*x+b2 in F for (int l = 0; l < _layers.Length; l++) { // get coefficients of current layer coeffAlpha = _layers[l].CoeffAlpha; coeffBeta = _layers[l].CoeffBeta; coeffGamma = _layers[l].CoeffGamma; coeffEta = _layers[l].CoeffEta; oils = coeffAlpha[0].Length; vins = coeffBeta[0].Length; // 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 vectTmp = cif.MultVect(coeffAlpha[p][x1][x2], _A2[x1 + vins]); coeffQuadratic3d[crntRow + p] = cif.AddSquareMatrix(coeffQuadratic3d[crntRow + p], cif.MultVects(vectTmp, _A2[x2])); // mul poly1 with scalar2 vectTmp = cif.MultVect(_B2[x2], vectTmp); _pubSingular[crntRow + p] = cif.AddVect(vectTmp, _pubSingular[crntRow + p]); // mul scalar1 with poly2 vectTmp = cif.MultVect(coeffAlpha[p][x1][x2], _A2[x2]); vectTmp = cif.MultVect(_B2[x1 + vins], vectTmp); _pubSingular[crntRow + p] = cif.AddVect(vectTmp, _pubSingular[crntRow + p]); // mul scalar1 with scalar2 sclrTmp = GF2Field.MultElem(coeffAlpha[p][x1][x2], _B2[x1 + vins]); _pubScalar[crntRow + p] = GF2Field.AddElem(_pubScalar[crntRow + p], GF2Field.MultElem(sclrTmp, _B2[x2])); } } // multiply betas for (int x1 = 0; x1 < vins; x1++) { for (int x2 = 0; x2 < vins; x2++) { // multiply polynomial1 with polynomial2 vectTmp = cif.MultVect(coeffBeta[p][x1][x2], _A2[x1]); coeffQuadratic3d[crntRow + p] = cif.AddSquareMatrix(coeffQuadratic3d[crntRow + p], cif.MultVects(vectTmp, _A2[x2])); // mul poly1 with scalar2 vectTmp = cif.MultVect(_B2[x2], vectTmp); _pubSingular[crntRow + p] = cif.AddVect(vectTmp, _pubSingular[crntRow + p]); // mul scalar1 with poly2 vectTmp = cif.MultVect(coeffBeta[p][x1][x2], _A2[x2]); vectTmp = cif.MultVect(_B2[x1], vectTmp); _pubSingular[crntRow + p] = cif.AddVect(vectTmp, _pubSingular[crntRow + p]); // mul scalar1 with scalar2 sclrTmp = GF2Field.MultElem(coeffBeta[p][x1][x2], _B2[x1]); _pubScalar[crntRow + p] = GF2Field.AddElem(_pubScalar[crntRow + p], GF2Field.MultElem(sclrTmp, _B2[x2])); } } // multiply gammas for (int n = 0; n < vins + oils; n++) { // mul poly with scalar vectTmp = cif.MultVect(coeffGamma[p][n], _A2[n]); _pubSingular[crntRow + p] = cif.AddVect(vectTmp, _pubSingular[crntRow + p]); // mul scalar with scalar _pubScalar[crntRow + p] = GF2Field.AddElem(_pubScalar[crntRow + p], GF2Field.MultElem(coeffGamma[p][n], _B2[n])); } // add eta _pubScalar[crntRow + p] = GF2Field.AddElem(_pubScalar[crntRow + p], coeffEta[p]); } crntRow = crntRow + oils; } // Apply L1 = A1*x+b1 to composition of F and L2 // temporary coefficient arrays short[][][] tmpQuad = ArrayUtils.CreateJagged<short[][][]>(rows, vars, vars); short[][] tmpSing = ArrayUtils.CreateJagged<short[][]>(rows, vars); short[] tmpScal = new short[rows]; for (int r = 0; r < rows; r++) { for (int q = 0; q < _A1.Length; q++) { tmpQuad[r] = cif.AddSquareMatrix(tmpQuad[r], cif.MultMatrix(_A1[r][q], coeffQuadratic3d[q])); tmpSing[r] = cif.AddVect(tmpSing[r], cif.MultVect(_A1[r][q], _pubSingular[q])); tmpScal[r] = GF2Field.AddElem(tmpScal[r], GF2Field.MultElem(_A1[r][q], _pubScalar[q])); } tmpScal[r] = GF2Field.AddElem(tmpScal[r], _B1[r]); } // set public key coeffQuadratic3d = tmpQuad; _pubSingular = tmpSing; _pubScalar = tmpScal; CompactPublicKey(coeffQuadratic3d); cif.Dispose(); }
/// <summary> /// This function generates the invertible affine linear map L2 = A2*x + b2. /// <para>The translation part b2, is stored in a separate array. /// The inverse of the matrix-part of L2 A2inv is also computed here. /// This linear map hides the output of the map F. It is on k^(n).</para> /// </summary> private void GenerateL2() { // dimension = n = vi[last] int dim = _VI[_VI.Length - 1]; _A2 = ArrayUtils.CreateJagged<short[][]>(dim, dim); _A2Inv = null; using (ComputeInField cif = new ComputeInField()) { // generation of A2 at random while (_A2Inv == null) { for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) _A2[i][j] = (short)(_rngEngine.Next() & GF2Field.MASK); } _A2Inv = cif.Inverse(_A2); } } // generation of the translation vector at random _B2 = new short[dim]; for (int i = 0; i < dim; i++) _B2[i] = (short)(_rngEngine.Next() & GF2Field.MASK); }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_dgtEngine != null) { _dgtEngine.Dispose(); _dgtEngine = null; } if (_rndEngine != null) { _rndEngine.Dispose(); _rndEngine = null; } if (_cptIf != null) { _cptIf.Dispose(); _cptIf = null; } if (_X != null) { Array.Clear(_X, 0, _X.Length); _X = null; } } catch { } _isDisposed = true; } }