/// <summary> /// Computes the inverse mod 2. /// <para>The algorithm is described in <a href="http://www.securityinnovation.com/uploads/Crypto/NTRUTech014.pdf"> /// Almost Inverses and Fast NTRU Key Generation</a>.</para> /// </summary> /// /// <returns>Returns <c>null</c> if the polynomial is not invertible.</returns> private IntegerPolynomial InvertF2() { int N = Coeffs.Length; int k = 0; IntegerPolynomial b = new IntegerPolynomial(N + 1); b.Coeffs[0] = 1; IntegerPolynomial c = new IntegerPolynomial(N + 1); IntegerPolynomial f = new IntegerPolynomial(Coeffs.CopyOf(N + 1)); f.Mod2(); // set g(x) = x^N − 1 IntegerPolynomial g = new IntegerPolynomial(N + 1); g.Coeffs[0] = 1; g.Coeffs[N] = 1; while (true) { while (f.Coeffs[0] == 0) { for (int i = 1; i <= N; i++) { f.Coeffs[i - 1] = f.Coeffs[i]; // f(x) = f(x) / x c.Coeffs[N + 1 - i] = c.Coeffs[N - i]; // c(x) = c(x) * x } f.Coeffs[N] = 0; c.Coeffs[0] = 0; k++; if (f.EqualsZero()) return null; // not invertible } if (f.EqualsOne()) break; if (f.Degree() < g.Degree()) { // exchange f and g IntegerPolynomial temp = f; f = g; g = temp; // exchange b and c temp = b; b = c; c = temp; } f.Add(g); f.Mod2(); b.Add(c); b.Mod2(); } if (b.Coeffs[N] != 0) return null; // Fq(x) = x^(N-k) * b(x) IntegerPolynomial Fq = new IntegerPolynomial(N); int j = 0; k %= N; for (int i = N - 1; i >= 0; i--) { j = i - k; if (j < 0) j += N; Fq.Coeffs[j] = b.Coeffs[i]; } return Fq; }
/// <summary> /// Computes the inverse mod 3. /// <para>Returns <c>null</c> if the polynomial is not invertible. /// The algorithm is described in <a href="http://www.securityinnovation.com/uploads/Crypto/NTRUTech014.pdf"> /// Almost Inverses and Fast NTRU Key Generation</a>.</para> /// </summary> /// /// <returns>A new polynomial, or <c>null</c> if no inverse exists</returns> public IntegerPolynomial InvertF3() { int N = Coeffs.Length; int k = 0; IntegerPolynomial b = new IntegerPolynomial(N + 1); b.Coeffs[0] = 1; IntegerPolynomial c = new IntegerPolynomial(N + 1); IntegerPolynomial f = new IntegerPolynomial(N + 1); f.Coeffs = Coeffs.CopyOf(N + 1); f.ModPositive(3); // set g(x) = x^N − 1 IntegerPolynomial g = new IntegerPolynomial(N + 1); g.Coeffs[0] = -1; g.Coeffs[N] = 1; while (true) { while (f.Coeffs[0] == 0) { for (int i = 1; i <= N; i++) { f.Coeffs[i - 1] = f.Coeffs[i]; // f(x) = f(x) / x c.Coeffs[N + 1 - i] = c.Coeffs[N - i]; // c(x) = c(x) * x } f.Coeffs[N] = 0; c.Coeffs[0] = 0; k++; if (f.EqualsZero()) return null; // not invertible } if (f.EqualsAbsOne()) break; if (f.Degree() < g.Degree()) { // exchange f and g IntegerPolynomial temp = f; f = g; g = temp; // exchange b and c temp = b; b = c; c = temp; } if (f.Coeffs[0] == g.Coeffs[0]) { f.Subtract(g, 3); b.Subtract(c, 3); } else { f.Add(g, 3); b.Add(c, 3); } } if (b.Coeffs[N] != 0) return null; // Fp(x) = [+-] x^(N-k) * b(x) IntegerPolynomial Fp = new IntegerPolynomial(N); int j = 0; k %= N; for (int i = N - 1; i >= 0; i--) { j = i - k; if (j < 0) j += N; Fp.Coeffs[j] = f.Coeffs[0] * b.Coeffs[i]; } Fp.EnsurePositive(3); return Fp; }
private IntegerPolynomial MultRecursive(IntegerPolynomial Factor) { int[] a = Coeffs; int[] b = Factor.Coeffs; int n = Factor.Coeffs.Length; if (n <= 32) { int cn = 2 * n - 1; IntegerPolynomial c = new IntegerPolynomial(new int[cn]); for (int k = 0; k < cn; k++) { for (int i = Math.Max(0, k - n + 1); i <= Math.Min(k, n - 1); i++) c.Coeffs[k] += b[i] * a[k - i]; } return c; } else { int n1 = n / 2; IntegerPolynomial a1 = new IntegerPolynomial(a.CopyOf(n1)); IntegerPolynomial a2 = new IntegerPolynomial(a.CopyOfRange(n1, n)); IntegerPolynomial b1 = new IntegerPolynomial(b.CopyOf(n1)); IntegerPolynomial b2 = new IntegerPolynomial(b.CopyOfRange(n1, n)); // make a copy of a1 that is the same length as a2 IntegerPolynomial A = new IntegerPolynomial(a1.Coeffs.CopyOf(a2.Coeffs.Length)); A.Add(a2); // make a copy of b1 that is the same length as b2 IntegerPolynomial B = new IntegerPolynomial(b1.Coeffs.CopyOf(b2.Coeffs.Length)); B.Add(b2); IntegerPolynomial c1 = a1.MultRecursive(b1); IntegerPolynomial c2 = a2.MultRecursive(b2); IntegerPolynomial c3 = A.MultRecursive(B); c3.Subtract(c1); c3.Subtract(c2); IntegerPolynomial c = new IntegerPolynomial(2 * n - 1); for (int i = 0; i < c1.Coeffs.Length; i++) c.Coeffs[i] = c1.Coeffs[i]; for (int i = 0; i < c3.Coeffs.Length; i++) c.Coeffs[n1 + i] += c3.Coeffs[i]; for (int i = 0; i < c2.Coeffs.Length; i++) c.Coeffs[2 * n1 + i] += c2.Coeffs[i]; return c; } }