/// <summary> /// Signature verification using public key /// </summary> /// /// <param name="Signature">The signature vector of dimension n</param> /// <returns>Returns document hash of length n - v1</returns> private short[] VerifySignatureIntern(short[] Signature) { short[][] coeffQuadratic = ((RNBWPublicKey)this.m_asmKey).CoeffQuadratic; short[][] coeffSingular = ((RNBWPublicKey)this.m_asmKey).CoeffSingular; short[] coeffScalar = ((RNBWPublicKey)this.m_asmKey).CoeffScalar; short[] rslt = new short[coeffQuadratic.Length]; // n - v1 int n = coeffSingular[0].Length; int offset = 0; // array position short tmp = 0; // for scalar for (int p = 0; p < coeffQuadratic.Length; p++) { offset = 0; for (int x = 0; x < n; x++) { // calculate quadratic terms for (int y = x; y < n; y++) { tmp = GF2Field.MultElem(coeffQuadratic[p][offset], GF2Field.MultElem(Signature[x], Signature[y])); rslt[p] = GF2Field.AddElem(rslt[p], tmp); offset++; } // calculate singular terms tmp = GF2Field.MultElem(coeffSingular[p][x], Signature[x]); rslt[p] = GF2Field.AddElem(rslt[p], tmp); } // add scalar rslt[p] = GF2Field.AddElem(rslt[p], coeffScalar[p]); } return(rslt); }
/// <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(); }