예제 #1
0
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)
예제 #2
0
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]
예제 #3
0
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)
예제 #4
0
 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)))
예제 #5
0
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]
예제 #6
0
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
예제 #7
0
    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()
예제 #8
0
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
예제 #9
0
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]
예제 #10
0
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!")