def cyclic_convolution(F, G, n): result = F.multiply(G) t = Zx([]) t.coeffs = [0] * n for i in range(result.degree() + 1): t.coeffs[i % n] += result.coeffs[i] return t
def invertmodprime(F, N, p): Fp = Zx([]) f = F.coeffs[::-1] f_poly = make_poly(f) x = sym.Symbol('x') t = sym.polys.polytools.invert(f_poly, x**N - 1, domain=GF(p, symmetric=False)) Fp.coeffs = t.all_coeffs()[::-1] return Fp
def invertmodpowerof2(F, N, q): g = Zx([]) if isPowerOfTwo(q) == False: print('q has to be a power of 2') return None g = invertmodprime(F, N, 2) while True: r = balancedmodulus(cyclic_convolution(F, g, N), q, N) flag = 0 for i in range(1, len(r.coeffs)): if r.coeffs[i] != 0: flag = 1 break if r.coeffs[0] == 1 and flag == 0: break e = Zx([2]) l = e.add(r.multiply_single_term(-1, 0)) g = balancedmodulus(cyclic_convolution(g, l, N), q, N) return g
def poly_divmod(X, Y): num = X.coeffs[:] normalize(num) den = Y.coeffs[:] normalize(den) if len(num) >= len(den): shiftlen = len(num) - len(den) den = [0] * shiftlen + den else: return [0], num quot = [] divisor = float(den[-1]) for i in range(shiftlen + 1): mult = num[-1] / divisor quot = [mult] + quot if mult != 0: d = [mult * u for u in den] num = [u - v for u, v in zip(num, d)] num.pop() den.pop(0) normalize(num) quotient = Zx([]) remainder = Zx([]) quotient.coeffs = quot[:] remainder.coeffs = num[:] return quotient, remainder
def generate_keypair(p, q, d, N): while True: try: F = Zx([]) F.randompoly(d, N) F_inverse = invertmodprime(F, N, p) Fq = invertmodpowerof2(F, N, q) break except: pass g = Zx([]) g.randompoly(d, N) r = Zx([p]) t = cyclic_convolution(Fq, g, N).multiply(r) public_key = balancedmodulus(t, q, N) secret_key = F, F_inverse return public_key, secret_key
def koblitz_encoder(plainText,elliptic_a,elliptic_b): ord_lst = [ord(ch) for ch in plainText] k=20 p=751 x_coords = [] y_coords = [] encoded_points = [] for m in ord_lst: for j in range(1,k): x_m = m*k+j n = pow(x_m,3) + elliptic_a * x_m + elliptic_b y_m = sq_root_mod_n(n,p) if (y_m != 0): x_coords.append(x_m) y_coords.append(y_m) encoded_points.append((x_m,y_m)) break encoded_message = [] #print('koblitz encoding:') for i in range(len(encoded_points)): x = x_coords[i] y = y_coords[i] #print(x,y) encoded_message.append(dec_ternary(cantor_pair(x,y))) #print(x,y) n = 0 for i in encoded_message: if len(i)>=n: n = len(i) for j in range(len(i)): i[j] = int(i[j]) ntru_input = [] for element in encoded_message: ntru_input.append(Zx(padder(introduce_negative_one(element),n))) return ntru_input,n
def balancedmodulus(F, q, N): result = Zx([]) for i in range(N): result.coeffs.append(((F.coeffs[i] + q // 2) % q) - q // 2) return result
def encrypt(message, public_key, d, N, q): r = Zx([]) r.randompoly(d, N) # r is the binding value cipher_text = balancedmodulus( cyclic_convolution(public_key, r, N).add(message), q, N) return cipher_text