这个学期我在研究生院学习了密码学课程,而我们涵盖的主题曾经是NTRU。我只是出于业余爱好,尝试使用纯Python编写此代码。当我试图找到多项式的逆模p(在本例中为p = 3)时,当我想要严格的正系数时,SymPy总是返回负系数。这是我的代码。我会解释我的意思。
import sympy as sym
from sympy import GF
def make_poly(N,coeffs):
"""Create a polynomial in x."""
x = sym.Symbol('x')
coeffs = list(reversed(coeffs))
y = 0
for i in range(N):
y += (x**i)*coeffs[i]
y = sym.poly(y)
return y
N = 7
p = 3
q = 41
f = [1,0,-1,1,1,0,-1]
f_poly = make_poly(N,f)
x = sym.Symbol('x')
Fp = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(p))
Fq = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(q))
print('\nf =',f_poly)
print('\nFp =',Fp)
print('\nFq =',Fq)
在此代码中,f_poly
是一个次数最多为6(其次数最多为N-1
)的多项式,其系数来自列表f
({ {1}}是f
的最高幂的系数,按降序连续。)
现在,我想在卷积多项式环x
中找到f_poly
的逆多项式(与Rp = (Z/pZ)[x]/(x^N - 1)(Z/pZ)[x]
类似)。底部的打印语句输出为:
q
这些多项式的模数是正确的,但是我想在各处都具有正系数,因为稍后在算法中涉及一些中心提升,因此我需要具有正系数。结果应该是
f = Poly(x**6 - x**4 + x**3 + x**2 - 1, x, domain='ZZ')
Fp = Poly(x**6 - x**5 + x**3 + x**2 + x + 1, x, modulus=3)
Fq = Poly(8*x**6 - 15*x**5 - 10*x**4 - 20*x**3 - x**2 + 2*x - 4, x, modulus=41)
我得到的答案在模数上是正确的,但我认为SymPy的Fp = x^6 + 2x^5 + x^3 + x^2 + x + 1
Fq = 8x^6 + 26x^5 + 31x^4 + 21x^3 + 40x^2 + 2x + 37
正在将某些系数更改为负变数,而不是停留在mod内。
有什么办法可以更新此多项式的系数,使其模数中只有正系数,或者这仅仅是SymPy函数的伪像?我想保留SymPy invert
的格式,以便稍后在行中使用其某些嵌入式功能。任何见识将不胜感激!
答案 0 :(得分:1)
这似乎取决于GF
中实现的有限域对象如何围绕给定模数“包装”整数。默认行为是symmetric
,这意味着x
映射到x % modulo <= modulo//2
,否则映射到x % modulo
的任何整数(x % modulo) - modulo
。因此GF(10)(5) == 5
,而GF(10)(6) == -4
。您可以通过传递GF
参数来使symmetric=False
始终映射为正数:
import sympy as sym
from sympy import GF
def make_poly(N, coeffs):
"""Create a polynomial in x."""
x = sym.Symbol('x')
coeffs = list(reversed(coeffs))
y = 0
for i in range(N):
y += (x**i)*coeffs[i]
y = sym.poly(y)
return y
N = 7
p = 3
q = 41
f = [1,0,-1,1,1,0,-1]
f_poly = make_poly(N,f)
x = sym.Symbol('x')
Fp = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(p, symmetric=False))
Fq = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(q, symmetric=False))
print('\nf =',f_poly)
print('\nFp =',Fp)
print('\nFq =',Fq)
现在,您将获得所需的多项式:
f = Poly(x**6 - x**4 + x**3 + x**2 - 1, x, domain='ZZ')
Fp = Poly(x**6 + 2*x**5 + x**3 + x**2 + x + 1, x, modulus=3)
Fq = Poly(8*x**6 + 26*x**5 + 31*x**4 + 21*x**3 + 40*x**2 + 2*x + 37, x, modulus=41)
主要是作为我自己参考的笔记,这是使用Mathematica获得Fp
的方法:
Fp = PolynomialMod[Algebra`PolynomialPowerMod`PolynomialPowerMod[x^6 - x^4 + x^3 + x^2 - 1, -1, x, x^7 - 1], 3]
输出:
1 + x + x^2 + x^3 + 2 x^5 + x^6