def integer_mod_ring(): """ Return a random ring of integers modulo n with n at most 50000. EXAMPLES: sage: sage.rings.tests.integer_mod_ring() Ring of integers modulo 30029 """ from sage.all import ZZ, IntegerModRing n = ZZ.random_element(x=2, y=50000) return IntegerModRing(n)
def rn_from_Dn(N, sgn, l): r""" compute (n,r) from (D,r) with D=4Nn+sgn*(r^2 mod 4N) """ [D, r] = l N4 = 4 * N ZR = IntegerModRing(4 * N) x = ZR(D - sgn * r * r) if x != 0: raise ValueError( " Need D=sgn*r^2 mod 4N got N={0}, r={1} D={2}".format(N, r, D)) n = (D - sgn * r * r) / ZZ(4 * N) return [n, r]
def integer_mod_ring(): """ Return a random ring of integers modulo n with n at most 50000. EXAMPLES:: sage: import sage.rings.tests sage: R = sage.rings.tests.integer_mod_ring(); R Ring of integers modulo ... sage: R.cardinality() <= 50000 True """ from sage.all import ZZ, IntegerModRing n = ZZ.random_element(x=2, y=50000) return IntegerModRing(n)
def from_discriminant(self,D): r""" Return the (r,n) s.t. D=n+-q(r). """ ZI=IntegerModRing(self._level) if(self.is_dual()): x=ZI(-D) else: x=ZI(D) for j in self._D: x=self.Qv[j] n=QQ(D)/QQ(self._level)-QQ(x) if(n % self._level == 0): print("D/4N-q(v)={0}".format(n)) return (self._D[j],ZZ(QQ(n)/QQ(self._level)))
def rn_from_D(N, sgn, D): r""" compute (n,r) from (D,r) with D=4Nn+sgn*(r^2 mod 4N) """ N4 = 4 * N ZR = IntegerModRing(4 * N) DD = sgn * ZR(D) if not DD.is_square(): raise ValueError(" Need D square mod 4N got N={0}, D={1}".format( N, D)) for j in range(N): x = ZR(D - sgn * j * j) if x == 0: r = j n = (D - sgn * r * r) / ZZ(4 * N) break return [n, r]
def recover_secret_key(pk, messages, signatures): Zn = IntegerModRing(pk.n) aggregate_signatures = map(Zn, signatures) signatures = [] prev = 1 sig_scheme = SignatureScheme(None, pk) for i in xrange(0, len(aggregate_signatures)): signatures.append(aggregate_signatures[i] / prev) prev = aggregate_signatures[i] hash_function = pk.hash_function hash_length = pk.hash_length hashes = [[1] + sig_scheme._hash(hash_function, m, i, pk.y) for i, m in enumerate(messages, 1)] M = matrix(hashes) print("Computing transform...") H, T = M.hermite_form(transformation=True) assert (T * M == H) assert (is_identity(H)) rows = T.rows() no_rows = len(rows) print("Projecting all signatures into the target epoch...") for i, s in enumerate(signatures): signatures[i] = pow(signatures[i], 2**(no_rows - i - 1), pk.n) print("Reconstructing the secret key values...") r = product( [pow(signatures[j], rows[0][j]) for j in xrange(len(signatures))], pk.n) s = [] for i in xrange(1, hash_length + 1): print(i) row = rows[i] h = product( [pow(signatures[j], row[j]) for j in xrange(len(signatures))], pk.n) s.append(h) secret_key = SignatureScheme.SecretKey(int(pk.n), int(pk.max_version), hash_length, int(r), [int(e) for e in s]) secret_key.version = len(signatures) return secret_key
def characteristic_polynomial_mod(self, f, N): r""" Return the absolute characteristic polynomial of the root of a given polynomial, modulo `p^N`. INPUT: - ``f`` -- a monic `p`-integral and irreducible polynomial over the underlying number field `K` - ``N`` -- a positive integer OUTPUT: the absolute characteristic polynomial of a root of `f`, modulo `p^N`. """ # construct the rational representation of a(formal) root alpha of f m = f.degree() K = self.number_field() vK = self.valuation() B = matrix(K, m) for i in range(m-1): B[i+1, i] = K(1) for i in range(m): B[i, m-1] = -f[i] # construct BB as the matrix representing alpha as endo of L/QQ, modulo p^N # note the the function self.matrix gives the representation with respect # to a p-integral basis of L/QQ, hence BB should be p-integral n = K.absolute_degree() R = IntegerModRing(self.p()**N) BB = matrix(R, n*m) for i in range(m): for j in range(m): B_ij = self.matrix(B[i,j], "mixed") # this had been changed, and it is not sufficiently tested for k in range(n): for l in range(n): if vK(B_ij[k,l]) < 0: print("B[i,j] = ", B[i,j]) print("vK(..) = ", vK(B[i,j])) print("B_ij[k,l] = ", B_ij[k,l]) raise ValueError BB[i*n+k, j*n+l] = R(B_ij[k,l]) return BB.charpoly()
def get_discs(N, dmax, sgn): r""" Computes a list of pairs (D,r) where D is a discriminant with D=sgn*r^2 mod 4N and |D|<=dmax """ ZR = IntegerModRing(4 * N) lp = list() ln = list() for j in range(1, dmax): D = j for r in range(1, N): if (ZR(D - r * r) == 0): #print D,r lp.append((D, r)) for j in range(1, dmax): D = -j for r in range(1, N): if (ZR(D - r * r) == 0): #print D,r ln.append((D, r)) return lp, ln
def _splitting_classes_gens_(K, m, d): r""" Given a number field `K` of conductor `m` and degree `d`, this returns a set of multiplicative generators of the subgroup of `(\mathbb{Z}/m\mathbb{Z})^{\times}/(\mathbb{Z}/m\mathbb{Z})^{\times d}` containing exactly the classes that contain the primes splitting completely in `K`. EXAMPLES:: sage: from sage.rings.number_field.number_field import _splitting_classes_gens_ sage: K = CyclotomicField(101) sage: L = K.subfields(20)[0][0] sage: L.conductor() 101 sage: _splitting_classes_gens_(L,101,20) [95] sage: K = CyclotomicField(44) sage: L = K.subfields(4)[0][0] sage: _splitting_classes_gens_(L,44,4) [37] sage: K = CyclotomicField(44) sage: L = K.subfields(5)[0][0] sage: K.degree() 20 sage: L Number Field in zeta44_0 with defining polynomial x^5 - 2*x^4 - 16*x^3 + 24*x^2 + 48*x - 32 with zeta44_0 = 3.837971894457990? sage: L.conductor() 11 sage: _splitting_classes_gens_(L,11,5) [10] """ R = K.ring_of_integers() Zm = IntegerModRing(m) unit_gens = Zm.unit_gens() ZZunits = ZZ**len(unit_gens) unit_relations = [gcd(d, x.multiplicative_order()) for x in unit_gens] # sparse=False can be removed if the code below doesn't raise the following # AttributeError: 'Matrix_integer_sparse' object has no attribute '_clear_denom' D = diagonal_matrix(unit_relations, sparse=False) Zmstar = ZZunits / D.row_module() def map_Zmstar_to_Zm(h): li = h.lift().list() return prod(unit_gens[i]**li[i] for i in range(len(unit_gens))) Hgens = [] H = Zmstar.submodule([]) Horder = Zmstar.cardinality() / d for g in Zmstar: if H.cardinality() == Horder: break if g not in H: u = map_Zmstar_to_Zm(g) p = u.lift() while not p.is_prime(): p += m f = R.ideal(p).prime_factors()[0].residue_class_degree() h = g * f if h not in H: Hgens += [h] H = Zmstar.submodule(Hgens) return [map_Zmstar_to_Zm(h) for h in Hgens]
def list_of_basis(N, weight, prec=501, tol=1e-20, sv_min=1E-1, sv_max=1E15, set_dim=None): r""" Returns a list of pairs (r,D) forming a basis """ # First we find the smallest Discriminant for each of the components if set_dim != None and set_dim > 0: dim = set_dim else: dim = dimension_jac_cusp_forms(int(weight + 0.5), N, -1) basislist = dict() num_gotten = 0 co_tmp = dict() num_gotten = 0 C0 = 1 RF = RealField(prec) if (silent > 1): print("N={0}".format(N)) print("dim={0}".format(dim)) print("sv_min={0}".format(sv_min)) print("sv_max={0}".format(sv_max)) Aold = Matrix(RF, 1) tol0 = 1E-20 #tol # we start with the first discriminant, then the second etc. Z2N = IntegerModRing(2 * N) ZZ4N = IntegerModRing(4 * N) for Dp in [1..max(1000, 100 * dim)]: D = -Dp # we use the dual of the Weil representation D4N = ZZ4N(D) if (not (is_square(D4N))): continue for r in my_modsqrt(D4N, N): # I want to make sure that P_{(D,r)} is independent from the previously computed functions # The only sure way to do this is to compute all submatrices (to a much smaller precision than what we want at the end) # The candidate is [D,r] and we need to compute the vector of [D,r,D',r'] # for all D',r' already in the list ltmp1 = dict() ltmp2 = dict() j = 0 for [Dp, rp] in basislist.values(): ltmp1[j] = [D, r, Dp, rp] ltmp2[j] = [Dp, rp, D, r] j = j + 1 ltmp1[j] = [D, r, D, r] #print "Checking: D,r,D,r=",ltmp1 ctmp1 = ps_coefficients_holomorphic_vec(N, weight, ltmp1, tol0) # print "ctmp1=",ctmp1 if (j > 0): #print "Checking: D,r,Dp,rp=",ltmp2 # Data is ok?: {0: True} ctmp2 = ps_coefficients_holomorphic_vec(N, weight, ltmp2, tol0) # print "ctmp2=",ctmp2 #print "num_gotten=",num_gotten A = matrix(RF, num_gotten + 1) # The old matrixc with the elements that are already added to the basis # print "Aold=\n",A,"\n" # print "num_gotten=",num_gotten # print "Aold=\n",Aold,"\n" for k in range(Aold.nrows()): for l in range(Aold.ncols()): A[k, l] = Aold[k, l] # endfor # print "A set by old=\n",A,"\n" # Add the (D',r',D,r) for each D',r' in the list tmp = RF(1.0) for l in range(num_gotten): # we do not use the scaling factor when # determining linear independence # mm=RF(abs(ltmp2[l][0]))/N4 # tmp=RF(mm**(weight-one)) A[num_gotten, l] = ctmp2['data'][l] * tmp # Add the (D,r,D',r') for each D',r' in the list # print "ctmp1.keys()=",ctmp1.keys() for l in range(num_gotten + 1): #mm=RF(abs(ltmp1[l][2]))/4N #tmp=RF(mm**(weight-one)) # print "scaled with=",tmp.n(200) A[l, num_gotten] = ctmp1['data'][l] * tmp #[d,B]=mat_inverse(A) # d=det(A) #if(silent>1): #d=det(A) #print "det A = ",d # Now we have to determine whether we have a linearly independent set or not dold = mpmath.mp.dps mpmath.mp.dps = int(prec / 3.3) AInt = mpmath.matrix(int(A.nrows()), int(A.ncols())) AMp = mpmath.matrix(int(A.nrows()), int(A.ncols())) if (silent > 0): print("tol0={0}".format(tol0)) for ir in range(A.nrows()): for ik in range(A.ncols()): AInt[ir, ik] = mpmath.mp.mpi(A[ir, ik] - tol0, A[ir, ik] + tol0) AMp[ir, ik] = mpmath.mpf(A[ir, ik]) d = mpmath.det(AMp) di = mpmath.mp.mpi(mpmath.mp.det(AInt)) #for ir in range(A.nrows()): # for ik in range(A.ncols()): # #print "A.d=",AInt[ir,ik].delta if (silent > 0): print("mpmath.mp.dps={0}".format(mpmath.mp.dps)) print("det(A)={0}".format(d)) print("det(A-as-interval)={0}".format(di)) print("d.delta={0}".format(di.delta)) #if(not mpmath.mpi(d) in di): # raise ArithmeticError," Interval determinant not ok?" #ANP=A.numpy() #try: # u,s,vnp=svd(ANP) # s are the singular values # sl=s.tolist() # mins=min(sl) # the smallest singular value # maxs=max(sl) # if(silent>1): # print "singular values = ",s #except LinAlgError: # if(silent>0): # print "could not compute SVD!" # print "using abs(det) instead" # mins=abs(d) # maxs=abs(d) #if((mins>sv_min and maxs< sv_max)): zero = mpmath.mpi(0) if (zero not in di): if (silent > 1): print("Adding D,r={0}, {1}".format(D, r)) basislist[num_gotten] = [D, r] num_gotten = num_gotten + 1 if (num_gotten >= dim): return basislist else: #print "setting Aold to A" Aold = A else: if (silent > 1): print(" do not use D,r={0}, {1}".format(D, r)) # endif mpmath.mp.dps = dold # endfor if (num_gotten < dim): raise ValueError( " did not find enough good elements for a basis list!")