passagemath-modules 10.6.31rc3__cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +806 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgfortran-e1b7dfc8.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-e3525837.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-c5c421e1.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- sage/tensor/modules/tensor_with_indices.py +1043 -0
|
@@ -0,0 +1,776 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
# sage.doctest: needs sage.combinat
|
|
3
|
+
r"""
|
|
4
|
+
Blum-Goldwasser Probabilistic Encryption
|
|
5
|
+
|
|
6
|
+
The Blum-Goldwasser probabilistic public-key encryption scheme. This scheme
|
|
7
|
+
was originally described in [BG1985]_. See also section 8.7.2
|
|
8
|
+
of [MvOV1996]_ and the :wikipedia:`Blum-Goldwasser_cryptosystem`
|
|
9
|
+
on this scheme.
|
|
10
|
+
|
|
11
|
+
AUTHORS:
|
|
12
|
+
|
|
13
|
+
- Mike Hogan and David Joyner (2009-9-19): initial procedural version
|
|
14
|
+
released as public domain software.
|
|
15
|
+
|
|
16
|
+
- Minh Van Nguyen (2009-12): integrate into Sage as a class and relicense
|
|
17
|
+
under the GPLv2+. Complete rewrite of the original version to follow
|
|
18
|
+
the description contained in [MvOV1996]_.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# ****************************************************************************
|
|
22
|
+
# Copyright (c) 2009, 2010 Mike Hogan
|
|
23
|
+
# Copyright (c) 2009, 2010 David Joyner <wdjoyner@gmail.com>
|
|
24
|
+
# Copyright (c) 2009, 2010 Minh Van Nguyen <nguyenminh2@gmail.com>
|
|
25
|
+
#
|
|
26
|
+
# This program is free software: you can redistribute it and/or modify
|
|
27
|
+
# it under the terms of the GNU General Public License as published by
|
|
28
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
29
|
+
# (at your option) any later version.
|
|
30
|
+
# https://www.gnu.org/licenses/
|
|
31
|
+
# ****************************************************************************
|
|
32
|
+
|
|
33
|
+
from operator import xor
|
|
34
|
+
|
|
35
|
+
from sage.arith.misc import gcd, power_mod, xgcd
|
|
36
|
+
from sage.crypto.cryptosystem import PublicKeyCryptosystem
|
|
37
|
+
from sage.crypto.util import is_blum_prime, least_significant_bits, random_blum_prime
|
|
38
|
+
from sage.functions.log import log
|
|
39
|
+
from sage.functions.other import Function_floor
|
|
40
|
+
from sage.monoids.string_monoid import BinaryStrings
|
|
41
|
+
from sage.rings.finite_rings.integer_mod import Mod as mod
|
|
42
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModFactory
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
floor = Function_floor()
|
|
46
|
+
IntegerModRing = IntegerModFactory("IntegerModRing")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class BlumGoldwasser(PublicKeyCryptosystem):
|
|
50
|
+
r"""
|
|
51
|
+
The Blum-Goldwasser probabilistic public-key encryption scheme.
|
|
52
|
+
|
|
53
|
+
The Blum-Goldwasser encryption and decryption algorithms as described in
|
|
54
|
+
:func:`encrypt() <BlumGoldwasser.encrypt>` and
|
|
55
|
+
:func:`decrypt() <BlumGoldwasser.decrypt>`, respectively, make use of the
|
|
56
|
+
least significant bit of a binary string. A related concept is the `k`
|
|
57
|
+
least significant bits of a binary string. For example, given a positive
|
|
58
|
+
integer `n`, let `b = b_0 b_1 \cdots b_{m-1}` be the binary representation
|
|
59
|
+
of `n` so that `b` is a binary string of length `m`. Then the least
|
|
60
|
+
significant bit of `n` is `b_{m-1}`. If `0 < k \leq m`, then the `k` least
|
|
61
|
+
significant bits of `n` are `b_{m-1-k} b_{m-k} \cdots b_{m-1}`. The least
|
|
62
|
+
significant bit of an integer is also referred to as its parity bit,
|
|
63
|
+
because this bit determines whether the integer is even or odd. In the
|
|
64
|
+
following example, we obtain the least significant bit of an integer::
|
|
65
|
+
|
|
66
|
+
sage: n = 123
|
|
67
|
+
sage: b = n.binary(); b
|
|
68
|
+
'1111011'
|
|
69
|
+
sage: n % 2
|
|
70
|
+
1
|
|
71
|
+
sage: b[-1]
|
|
72
|
+
'1'
|
|
73
|
+
|
|
74
|
+
Now find the 4 least significant bits of the integer `n = 123`::
|
|
75
|
+
|
|
76
|
+
sage: b
|
|
77
|
+
'1111011'
|
|
78
|
+
sage: b[-4:]
|
|
79
|
+
'1011'
|
|
80
|
+
|
|
81
|
+
The last two examples could be worked through as follows::
|
|
82
|
+
|
|
83
|
+
sage: from sage.crypto.util import least_significant_bits
|
|
84
|
+
sage: least_significant_bits(123, 1)
|
|
85
|
+
[1]
|
|
86
|
+
sage: least_significant_bits(123, 4)
|
|
87
|
+
[1, 0, 1, 1]
|
|
88
|
+
|
|
89
|
+
EXAMPLES:
|
|
90
|
+
|
|
91
|
+
The following encryption/decryption example is taken from Example 8.57,
|
|
92
|
+
pages 309--310 of [MvOV1996]_::
|
|
93
|
+
|
|
94
|
+
sage: # needs sage.symbolic
|
|
95
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
96
|
+
sage: bg = BlumGoldwasser(); bg
|
|
97
|
+
The Blum-Goldwasser public-key encryption scheme.
|
|
98
|
+
sage: p = 499; q = 547
|
|
99
|
+
sage: pubkey = bg.public_key(p, q); pubkey
|
|
100
|
+
272953
|
|
101
|
+
sage: prikey = bg.private_key(p, q); prikey
|
|
102
|
+
(499, 547, -57, 52)
|
|
103
|
+
sage: P = "10011100000100001100"
|
|
104
|
+
sage: C = bg.encrypt(P, pubkey, seed=159201); C
|
|
105
|
+
([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680)
|
|
106
|
+
sage: M = bg.decrypt(C, prikey); M
|
|
107
|
+
[[1, 0, 0, 1], [1, 1, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [1, 1, 0, 0]]
|
|
108
|
+
sage: M = "".join(str(x) for x in flatten(M)); M
|
|
109
|
+
'10011100000100001100'
|
|
110
|
+
sage: M == P
|
|
111
|
+
True
|
|
112
|
+
|
|
113
|
+
Generate a pair of random public/private keys. Use the public key to
|
|
114
|
+
encrypt a plaintext. Then decrypt the resulting ciphertext using the
|
|
115
|
+
private key. Finally, compare the decrypted message with the original
|
|
116
|
+
plaintext. ::
|
|
117
|
+
|
|
118
|
+
sage: # needs sage.libs.pari sage.symbolic
|
|
119
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
120
|
+
sage: from sage.crypto.util import bin_to_ascii
|
|
121
|
+
sage: bg = BlumGoldwasser()
|
|
122
|
+
sage: pubkey, prikey = bg.random_key(10**4, 10**6)
|
|
123
|
+
sage: P = "A fixed plaintext."
|
|
124
|
+
sage: C = bg.encrypt(P, pubkey)
|
|
125
|
+
sage: M = bg.decrypt(C, prikey)
|
|
126
|
+
sage: bin_to_ascii(flatten(M)) == P
|
|
127
|
+
True
|
|
128
|
+
|
|
129
|
+
If `(p, q, a, b)` is a private key, then `n = pq` is the corresponding
|
|
130
|
+
public key. Furthermore, we have `\gcd(p, q) = ap + bq = 1`. ::
|
|
131
|
+
|
|
132
|
+
sage: p, q, a, b = prikey # needs sage.symbolic
|
|
133
|
+
sage: pubkey == p * q # needs sage.symbolic
|
|
134
|
+
True
|
|
135
|
+
sage: gcd(p, q) == a*p + b*q == 1 # needs sage.symbolic
|
|
136
|
+
True
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def __init__(self):
|
|
140
|
+
"""
|
|
141
|
+
Construct the Blum-Goldwasser public-key encryption scheme.
|
|
142
|
+
|
|
143
|
+
OUTPUT:
|
|
144
|
+
|
|
145
|
+
- A ``BlumGoldwasser`` object representing the Blum-Goldwasser
|
|
146
|
+
public-key encryption scheme.
|
|
147
|
+
|
|
148
|
+
See the class docstring of ``BlumGoldwasser`` for detailed
|
|
149
|
+
documentation.
|
|
150
|
+
|
|
151
|
+
EXAMPLES::
|
|
152
|
+
|
|
153
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
154
|
+
sage: bg = BlumGoldwasser()
|
|
155
|
+
sage: bg == loads(dumps(bg))
|
|
156
|
+
True
|
|
157
|
+
"""
|
|
158
|
+
# no internal data for now; nothing to initialize
|
|
159
|
+
pass
|
|
160
|
+
|
|
161
|
+
def __eq__(self, other):
|
|
162
|
+
"""
|
|
163
|
+
Compare this ``BlumGoldwasser`` object with ``other``.
|
|
164
|
+
|
|
165
|
+
INPUT:
|
|
166
|
+
|
|
167
|
+
- ``other`` -- a ``BlumGoldwasser`` object
|
|
168
|
+
|
|
169
|
+
OUTPUT: ``True`` if both ``self`` and ``other`` are ``BlumGoldwasser``
|
|
170
|
+
objects; ``False`` otherwise
|
|
171
|
+
|
|
172
|
+
Two objects are ``BlumGoldwasser`` objects if their string
|
|
173
|
+
representations are the same.
|
|
174
|
+
|
|
175
|
+
EXAMPLES::
|
|
176
|
+
|
|
177
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
178
|
+
sage: bg1 = BlumGoldwasser()
|
|
179
|
+
sage: bg2 = BlumGoldwasser()
|
|
180
|
+
sage: bg1 == bg2
|
|
181
|
+
True
|
|
182
|
+
"""
|
|
183
|
+
return repr(self) == repr(other)
|
|
184
|
+
|
|
185
|
+
def __repr__(self):
|
|
186
|
+
"""
|
|
187
|
+
A string representation of this Blum-Goldwasser public-key encryption
|
|
188
|
+
scheme.
|
|
189
|
+
|
|
190
|
+
OUTPUT:
|
|
191
|
+
|
|
192
|
+
- A string representation of this Blum-Goldwasser public-key
|
|
193
|
+
encryption scheme.
|
|
194
|
+
|
|
195
|
+
EXAMPLES::
|
|
196
|
+
|
|
197
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
198
|
+
sage: BlumGoldwasser()
|
|
199
|
+
The Blum-Goldwasser public-key encryption scheme.
|
|
200
|
+
"""
|
|
201
|
+
return "The Blum-Goldwasser public-key encryption scheme."
|
|
202
|
+
|
|
203
|
+
def decrypt(self, C, K):
|
|
204
|
+
r"""
|
|
205
|
+
Apply the Blum-Goldwasser scheme to decrypt the ciphertext ``C``
|
|
206
|
+
using the private key ``K``.
|
|
207
|
+
|
|
208
|
+
INPUT:
|
|
209
|
+
|
|
210
|
+
- ``C`` -- a ciphertext resulting from encrypting a plaintext using
|
|
211
|
+
the Blum-Goldwasser encryption algorithm. The ciphertext `C` must
|
|
212
|
+
be of the form `C = (c_1, c_2, \dots, c_t, x_{t+1})`. Each `c_i`
|
|
213
|
+
is a sub-block of binary string and `x_{t+1}` is the result of the
|
|
214
|
+
`t+1`-th iteration of the Blum-Blum-Shub algorithm.
|
|
215
|
+
|
|
216
|
+
- ``K`` -- a private key `(p, q, a, b)` where `p` and `q` are
|
|
217
|
+
distinct Blum primes and `\gcd(p, q) = ap + bq = 1`
|
|
218
|
+
|
|
219
|
+
OUTPUT:
|
|
220
|
+
|
|
221
|
+
- The plaintext resulting from decrypting the ciphertext ``C`` using
|
|
222
|
+
the Blum-Goldwasser decryption algorithm.
|
|
223
|
+
|
|
224
|
+
ALGORITHM:
|
|
225
|
+
|
|
226
|
+
The Blum-Goldwasser decryption algorithm is described in Algorithm
|
|
227
|
+
8.56, page 309 of [MvOV1996]_. The algorithm works as follows:
|
|
228
|
+
|
|
229
|
+
#. Let `C` be the ciphertext `C = (c_1, c_2, \dots, c_t, x_{t+1})`.
|
|
230
|
+
Then `t` is the number of ciphertext sub-blocks and `h` is the
|
|
231
|
+
length of each binary string sub-block `c_i`.
|
|
232
|
+
#. Let `(p, q, a, b)` be the private key whose corresponding
|
|
233
|
+
public key is `n = pq`. Note that `\gcd(p, q) = ap + bq = 1`.
|
|
234
|
+
#. Compute `d_1 = ((p + 1) / 4)^{t+1} \bmod{(p - 1)}`.
|
|
235
|
+
#. Compute `d_2 = ((q + 1) / 4)^{t+1} \bmod{(q - 1)}`.
|
|
236
|
+
#. Let `u = x_{t+1}^{d_1} \bmod p`.
|
|
237
|
+
#. Let `v = x_{t+1}^{d_2} \bmod q`.
|
|
238
|
+
#. Compute `x_0 = vap + ubq \bmod n`.
|
|
239
|
+
#. For `i` from 1 to `t`, do:
|
|
240
|
+
|
|
241
|
+
#. Compute `x_i = x_{t-1}^2 \bmod n`.
|
|
242
|
+
#. Let `p_i` be the `h` least significant bits of `x_i`.
|
|
243
|
+
#. Compute `m_i = p_i \oplus c_i`.
|
|
244
|
+
|
|
245
|
+
#. The plaintext is `m = m_1 m_2 \cdots m_t`.
|
|
246
|
+
|
|
247
|
+
EXAMPLES:
|
|
248
|
+
|
|
249
|
+
The following decryption example is taken from Example 8.57, pages
|
|
250
|
+
309--310 of [MvOV1996]_. Here we decrypt a binary string::
|
|
251
|
+
|
|
252
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
253
|
+
sage: bg = BlumGoldwasser()
|
|
254
|
+
sage: p = 499; q = 547
|
|
255
|
+
sage: C = ([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680)
|
|
256
|
+
sage: K = bg.private_key(p, q); K
|
|
257
|
+
(499, 547, -57, 52)
|
|
258
|
+
sage: P = bg.decrypt(C, K); P
|
|
259
|
+
[[1, 0, 0, 1], [1, 1, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [1, 1, 0, 0]]
|
|
260
|
+
|
|
261
|
+
Convert the plaintext sub-blocks into a binary string::
|
|
262
|
+
|
|
263
|
+
sage: bin = BinaryStrings()
|
|
264
|
+
sage: bin(flatten(P))
|
|
265
|
+
10011100000100001100
|
|
266
|
+
|
|
267
|
+
Decrypt a longer ciphertext and convert the resulting plaintext
|
|
268
|
+
into an ASCII string::
|
|
269
|
+
|
|
270
|
+
sage: # needs sage.libs.pari
|
|
271
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
272
|
+
sage: from sage.crypto.util import bin_to_ascii
|
|
273
|
+
sage: bg = BlumGoldwasser()
|
|
274
|
+
sage: p = 78307; q = 412487
|
|
275
|
+
sage: K = bg.private_key(p, q)
|
|
276
|
+
sage: C = ([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0],
|
|
277
|
+
....: [1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1],
|
|
278
|
+
....: [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
279
|
+
....: [0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1],
|
|
280
|
+
....: [1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0],
|
|
281
|
+
....: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1],
|
|
282
|
+
....: [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0],
|
|
283
|
+
....: [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1],
|
|
284
|
+
....: [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0],
|
|
285
|
+
....: [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1],
|
|
286
|
+
....: [1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
|
287
|
+
....: [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0],
|
|
288
|
+
....: [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]], 3479653279)
|
|
289
|
+
sage: P = bg.decrypt(C, K)
|
|
290
|
+
sage: bin_to_ascii(flatten(P))
|
|
291
|
+
'Blum-Goldwasser encryption'
|
|
292
|
+
|
|
293
|
+
TESTS:
|
|
294
|
+
|
|
295
|
+
The private key `K = (p, q, a, b)` must be such that `p` and `q` are
|
|
296
|
+
distinct Blum primes. Even if `p` and `q` pass this criterion, they
|
|
297
|
+
must also satisfy the requirement `\gcd(p, q) = ap + bq = 1`. ::
|
|
298
|
+
|
|
299
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
300
|
+
sage: bg = BlumGoldwasser()
|
|
301
|
+
sage: C = ([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680)
|
|
302
|
+
sage: K = (7, 7, 1, 2)
|
|
303
|
+
sage: bg.decrypt(C, K)
|
|
304
|
+
Traceback (most recent call last):
|
|
305
|
+
...
|
|
306
|
+
ValueError: p and q must be distinct Blum primes.
|
|
307
|
+
sage: K = (7, 23, 1, 2)
|
|
308
|
+
sage: bg.decrypt(C, K)
|
|
309
|
+
Traceback (most recent call last):
|
|
310
|
+
...
|
|
311
|
+
ValueError: a and b must satisfy gcd(p, q) = ap + bq = 1.
|
|
312
|
+
sage: K = (11, 29, 8, -3)
|
|
313
|
+
sage: bg.decrypt(C, K)
|
|
314
|
+
Traceback (most recent call last):
|
|
315
|
+
...
|
|
316
|
+
ValueError: p and q must be distinct Blum primes.
|
|
317
|
+
"""
|
|
318
|
+
# ciphertext
|
|
319
|
+
c = C[0]
|
|
320
|
+
xt1 = C[-1]
|
|
321
|
+
# number of ciphertext sub-blocks
|
|
322
|
+
t = len(c)
|
|
323
|
+
# length of each ciphertext sub-block
|
|
324
|
+
h = len(c[0])
|
|
325
|
+
# private key
|
|
326
|
+
p, q, a, b = K
|
|
327
|
+
# public key
|
|
328
|
+
n = p * q
|
|
329
|
+
# sanity checks
|
|
330
|
+
if p == q:
|
|
331
|
+
raise ValueError("p and q must be distinct Blum primes.")
|
|
332
|
+
if (a*p + b*q) != 1:
|
|
333
|
+
raise ValueError("a and b must satisfy gcd(p, q) = ap + bq = 1.")
|
|
334
|
+
if (not is_blum_prime(p)) or (not is_blum_prime(q)):
|
|
335
|
+
raise ValueError("p and q must be distinct Blum primes.")
|
|
336
|
+
# prepare to decrypt
|
|
337
|
+
d1 = power_mod((p + 1) // 4, t + 1, p - 1)
|
|
338
|
+
d2 = power_mod((q + 1) // 4, t + 1, q - 1)
|
|
339
|
+
u = power_mod(xt1, d1, p)
|
|
340
|
+
v = power_mod(xt1, d2, q)
|
|
341
|
+
x0 = mod(v*a*p + u*b*q, n).lift()
|
|
342
|
+
# perform the decryption
|
|
343
|
+
M = []
|
|
344
|
+
for i in range(t):
|
|
345
|
+
x1 = power_mod(x0, 2, n)
|
|
346
|
+
p = least_significant_bits(x1, h)
|
|
347
|
+
M.append(list(map(xor, p, c[i])))
|
|
348
|
+
x0 = x1
|
|
349
|
+
return M
|
|
350
|
+
|
|
351
|
+
def encrypt(self, P, K, seed=None):
|
|
352
|
+
r"""
|
|
353
|
+
Apply the Blum-Goldwasser scheme to encrypt the plaintext ``P`` using
|
|
354
|
+
the public key ``K``.
|
|
355
|
+
|
|
356
|
+
INPUT:
|
|
357
|
+
|
|
358
|
+
- ``P`` -- a non-empty string of plaintext. The string ``""`` is
|
|
359
|
+
an empty string, whereas ``" "`` is a string consisting of one
|
|
360
|
+
white space character. The plaintext can be a binary string or
|
|
361
|
+
a string of ASCII characters. Where ``P`` is an ASCII string, then
|
|
362
|
+
``P`` is first encoded as a binary string prior to encryption.
|
|
363
|
+
|
|
364
|
+
- ``K`` -- a public key, which is the product of two Blum primes
|
|
365
|
+
|
|
366
|
+
- ``seed`` -- (default: ``None``) if `p` and `q` are Blum primes and
|
|
367
|
+
`n = pq` is a public key, then ``seed`` is a quadratic residue in
|
|
368
|
+
the multiplicative group `(\ZZ/n\ZZ)^{\ast}`. If ``seed=None``,
|
|
369
|
+
then the function would generate its own random quadratic residue
|
|
370
|
+
in `(\ZZ/n\ZZ)^{\ast}`. Where a value for ``seed`` is provided,
|
|
371
|
+
it is your responsibility to ensure that the seed is a
|
|
372
|
+
quadratic residue in the multiplicative group `(\ZZ/n\ZZ)^{\ast}`.
|
|
373
|
+
|
|
374
|
+
OUTPUT:
|
|
375
|
+
|
|
376
|
+
- The ciphertext resulting from encrypting ``P`` using the public
|
|
377
|
+
key ``K``. The ciphertext `C` is of the form
|
|
378
|
+
`C = (c_1, c_2, \dots, c_t, x_{t+1})`. Each `c_i` is a
|
|
379
|
+
sub-block of binary string and `x_{t+1}` is the result of the
|
|
380
|
+
`t+1`-th iteration of the Blum-Blum-Shub algorithm.
|
|
381
|
+
|
|
382
|
+
ALGORITHM:
|
|
383
|
+
|
|
384
|
+
The Blum-Goldwasser encryption algorithm is described in Algorithm
|
|
385
|
+
8.56, page 309 of [MvOV1996]_. The algorithm works as follows:
|
|
386
|
+
|
|
387
|
+
#. Let `n` be a public key, where `n = pq` is the product of two
|
|
388
|
+
distinct Blum primes `p` and `q`.
|
|
389
|
+
#. Let `k = \lfloor \log_2(n) \rfloor` and
|
|
390
|
+
`h = \lfloor \log_2(k) \rfloor`.
|
|
391
|
+
#. Let `m = m_1 m_2 \cdots m_t` be the message (plaintext) where
|
|
392
|
+
each `m_i` is a binary string of length `h`.
|
|
393
|
+
#. Choose a random seed `x_0`, which is a quadratic residue in
|
|
394
|
+
the multiplicative group `(\ZZ/n\ZZ)^{\ast}`. That is, choose
|
|
395
|
+
a random `r \in (\ZZ/n\ZZ)^{\ast}` and compute
|
|
396
|
+
`x_0 = r^2 \bmod n`.
|
|
397
|
+
#. For `i` from 1 to `t`, do:
|
|
398
|
+
|
|
399
|
+
#. Let `x_i = x_{i-1}^2 \bmod n`.
|
|
400
|
+
#. Let `p_i` be the `h` least significant bits of `x_i`.
|
|
401
|
+
#. Let `c_i = p_i \oplus m_i`.
|
|
402
|
+
|
|
403
|
+
#. Compute `x_{t+1} = x_t^2 \bmod n`.
|
|
404
|
+
#. The ciphertext is `c = (c_1, c_2, \dots, c_t, x_{t+1})`.
|
|
405
|
+
|
|
406
|
+
The value `h` in the algorithm is the sub-block length. If the
|
|
407
|
+
binary string representing the message cannot be divided into blocks
|
|
408
|
+
of length `h` each, then other sub-block lengths would be used
|
|
409
|
+
instead. The sub-block lengths to fall back on are in the
|
|
410
|
+
following order: 16, 8, 4, 2, 1.
|
|
411
|
+
|
|
412
|
+
EXAMPLES:
|
|
413
|
+
|
|
414
|
+
The following encryption example is taken from Example 8.57,
|
|
415
|
+
pages 309--310 of [MvOV1996]_. Here, we encrypt a binary
|
|
416
|
+
string::
|
|
417
|
+
|
|
418
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
419
|
+
sage: bg = BlumGoldwasser()
|
|
420
|
+
sage: p = 499; q = 547; n = p * q
|
|
421
|
+
sage: P = "10011100000100001100"
|
|
422
|
+
sage: C = bg.encrypt(P, n, seed=159201); C # needs sage.symbolic
|
|
423
|
+
([[0, 0, 1, 0], [0, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0]], 139680)
|
|
424
|
+
|
|
425
|
+
Convert the ciphertext sub-blocks into a binary string::
|
|
426
|
+
|
|
427
|
+
sage: bin = BinaryStrings()
|
|
428
|
+
sage: bin(flatten(C[0])) # needs sage.symbolic
|
|
429
|
+
00100000110011100100
|
|
430
|
+
|
|
431
|
+
Now encrypt an ASCII string. The result is random; no seed is
|
|
432
|
+
provided to the encryption function so the function generates its
|
|
433
|
+
own random seed::
|
|
434
|
+
|
|
435
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
436
|
+
sage: bg = BlumGoldwasser()
|
|
437
|
+
sage: K = 32300619509
|
|
438
|
+
sage: P = "Blum-Goldwasser encryption"
|
|
439
|
+
sage: bg.encrypt(P, K) # random # needs sage.symbolic
|
|
440
|
+
([[1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], \
|
|
441
|
+
[1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1], \
|
|
442
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], \
|
|
443
|
+
[0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], \
|
|
444
|
+
[1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], \
|
|
445
|
+
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], \
|
|
446
|
+
[1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0], \
|
|
447
|
+
[1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1], \
|
|
448
|
+
[0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], \
|
|
449
|
+
[1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1], \
|
|
450
|
+
[1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1], \
|
|
451
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0], \
|
|
452
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]], 3479653279)
|
|
453
|
+
|
|
454
|
+
TESTS:
|
|
455
|
+
|
|
456
|
+
The plaintext cannot be an empty string. ::
|
|
457
|
+
|
|
458
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
459
|
+
sage: bg = BlumGoldwasser()
|
|
460
|
+
sage: bg.encrypt("", 3)
|
|
461
|
+
Traceback (most recent call last):
|
|
462
|
+
...
|
|
463
|
+
ValueError: The plaintext cannot be an empty string.
|
|
464
|
+
"""
|
|
465
|
+
# sanity check
|
|
466
|
+
if P == "":
|
|
467
|
+
raise ValueError("The plaintext cannot be an empty string.")
|
|
468
|
+
n = K
|
|
469
|
+
k = floor(log(n, base=2))
|
|
470
|
+
h = floor(log(k, base=2))
|
|
471
|
+
bin = BinaryStrings()
|
|
472
|
+
M = ""
|
|
473
|
+
try:
|
|
474
|
+
# the plaintext is a binary string
|
|
475
|
+
M = bin(P)
|
|
476
|
+
except TypeError:
|
|
477
|
+
# encode the plaintext as a binary string
|
|
478
|
+
# An exception might be raised here if P cannot be encoded as a
|
|
479
|
+
# binary string.
|
|
480
|
+
M = bin.encoding(P)
|
|
481
|
+
# the number of plaintext sub-blocks; each sub-block has length h
|
|
482
|
+
t = 0
|
|
483
|
+
try:
|
|
484
|
+
# Attempt to use t and h values from the algorithm described
|
|
485
|
+
# in [MvOV1996].
|
|
486
|
+
t = len(M) / h
|
|
487
|
+
# If the following raises an exception, then we can't use
|
|
488
|
+
# the t and h values specified by [MvOV1996].
|
|
489
|
+
mod(len(M), t)
|
|
490
|
+
# fall back to using other sub-block lengths
|
|
491
|
+
except TypeError:
|
|
492
|
+
# sub-blocks of length h = 16
|
|
493
|
+
if mod(len(M), 16) == 0:
|
|
494
|
+
h = 16
|
|
495
|
+
t = len(M) // h
|
|
496
|
+
# sub-blocks of length h = 8
|
|
497
|
+
elif mod(len(M), 8) == 0:
|
|
498
|
+
h = 8
|
|
499
|
+
t = len(M) // h
|
|
500
|
+
# sub-blocks of length h = 4
|
|
501
|
+
elif mod(len(M), 4) == 0:
|
|
502
|
+
h = 4
|
|
503
|
+
t = len(M) // h
|
|
504
|
+
# sub-blocks of length h = 2
|
|
505
|
+
elif mod(len(M), 2) == 0:
|
|
506
|
+
h = 2
|
|
507
|
+
t = len(M) // h
|
|
508
|
+
# sub-blocks of length h = 1
|
|
509
|
+
else:
|
|
510
|
+
h = 1
|
|
511
|
+
t = len(M) // h
|
|
512
|
+
# If no seed is provided, select a random seed.
|
|
513
|
+
x0 = seed
|
|
514
|
+
if seed is None:
|
|
515
|
+
zmod = IntegerModRing(n) # K = n = pq
|
|
516
|
+
r = zmod.random_element().lift()
|
|
517
|
+
while gcd(r, n) != 1:
|
|
518
|
+
r = zmod.random_element().lift()
|
|
519
|
+
x0 = power_mod(r, 2, n)
|
|
520
|
+
# perform the encryption
|
|
521
|
+
to_int = lambda x: int(str(x))
|
|
522
|
+
C = []
|
|
523
|
+
for i in range(t):
|
|
524
|
+
x1 = power_mod(x0, 2, n)
|
|
525
|
+
p = least_significant_bits(x1, h)
|
|
526
|
+
# xor p with a sub-block of length h. There are t sub-blocks of
|
|
527
|
+
# length h each.
|
|
528
|
+
C.append(list(map(xor, p, [to_int(_) for _ in M[i*h : (i+1)*h]])))
|
|
529
|
+
x0 = x1
|
|
530
|
+
x1 = power_mod(x0, 2, n)
|
|
531
|
+
return (C, x1)
|
|
532
|
+
|
|
533
|
+
def private_key(self, p, q):
|
|
534
|
+
r"""
|
|
535
|
+
Return the Blum-Goldwasser private key corresponding to the
|
|
536
|
+
distinct Blum primes ``p`` and ``q``.
|
|
537
|
+
|
|
538
|
+
INPUT:
|
|
539
|
+
|
|
540
|
+
- ``p`` -- a Blum prime
|
|
541
|
+
|
|
542
|
+
- ``q`` -- a Blum prime
|
|
543
|
+
|
|
544
|
+
OUTPUT: the Blum-Goldwasser private key `(p, q, a, b)` where
|
|
545
|
+
`\gcd(p, q) = ap + bq = 1`
|
|
546
|
+
|
|
547
|
+
Both ``p`` and ``q`` must be distinct Blum primes. Let `p` be a
|
|
548
|
+
positive prime. Then `p` is a Blum prime if `p` is congruent to 3
|
|
549
|
+
modulo 4, i.e. `p \equiv 3 \pmod{4}`.
|
|
550
|
+
|
|
551
|
+
EXAMPLES:
|
|
552
|
+
|
|
553
|
+
Obtain two distinct Blum primes and compute the Blum-Goldwasser
|
|
554
|
+
private key corresponding to those two Blum primes::
|
|
555
|
+
|
|
556
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
557
|
+
sage: from sage.crypto.util import is_blum_prime
|
|
558
|
+
sage: bg = BlumGoldwasser()
|
|
559
|
+
sage: P = primes_first_n(10); P # needs sage.libs.pari
|
|
560
|
+
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
|
|
561
|
+
sage: [is_blum_prime(_) for _ in P] # needs sage.libs.pari
|
|
562
|
+
[False, True, False, True, True, False, False, True, True, False]
|
|
563
|
+
sage: bg.private_key(19, 23)
|
|
564
|
+
(19, 23, -6, 5)
|
|
565
|
+
|
|
566
|
+
Choose two distinct random Blum primes, compute the Blum-Goldwasser
|
|
567
|
+
private key corresponding to those two primes, and test that the
|
|
568
|
+
resulting private key `(p, q, a, b)` satisfies
|
|
569
|
+
`\gcd(p, q) = ap + bq = 1`::
|
|
570
|
+
|
|
571
|
+
sage: # needs sage.libs.pari
|
|
572
|
+
sage: from sage.crypto.util import random_blum_prime
|
|
573
|
+
sage: p = random_blum_prime(10**4, 10**5)
|
|
574
|
+
sage: q = random_blum_prime(10**4, 10**5)
|
|
575
|
+
sage: while q == p:
|
|
576
|
+
....: q = random_blum_prime(10**4, 10**5)
|
|
577
|
+
sage: p, q, a, b = bg.private_key(p, q)
|
|
578
|
+
sage: gcd(p, q) == a*p + b*q == 1
|
|
579
|
+
True
|
|
580
|
+
|
|
581
|
+
TESTS:
|
|
582
|
+
|
|
583
|
+
Both of the input ``p`` and ``q`` must be distinct Blum primes. ::
|
|
584
|
+
|
|
585
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
586
|
+
sage: bg = BlumGoldwasser()
|
|
587
|
+
sage: bg.private_key(78307, 78307)
|
|
588
|
+
Traceback (most recent call last):
|
|
589
|
+
...
|
|
590
|
+
ValueError: p and q must be distinct Blum primes.
|
|
591
|
+
sage: bg.private_key(7, 4)
|
|
592
|
+
Traceback (most recent call last):
|
|
593
|
+
...
|
|
594
|
+
ValueError: p and q must be distinct Blum primes.
|
|
595
|
+
"""
|
|
596
|
+
if p == q:
|
|
597
|
+
raise ValueError("p and q must be distinct Blum primes.")
|
|
598
|
+
if is_blum_prime(p) and is_blum_prime(q):
|
|
599
|
+
# here gcd(p, q) = ap + bq = 1
|
|
600
|
+
bezout = xgcd(p, q)
|
|
601
|
+
a = bezout[1]
|
|
602
|
+
b = bezout[2]
|
|
603
|
+
return (p, q, a, b)
|
|
604
|
+
else:
|
|
605
|
+
raise ValueError("p and q must be distinct Blum primes.")
|
|
606
|
+
|
|
607
|
+
def public_key(self, p, q):
|
|
608
|
+
r"""
|
|
609
|
+
Return the Blum-Goldwasser public key corresponding to the
|
|
610
|
+
distinct Blum primes ``p`` and ``q``.
|
|
611
|
+
|
|
612
|
+
INPUT:
|
|
613
|
+
|
|
614
|
+
- ``p`` -- a Blum prime
|
|
615
|
+
|
|
616
|
+
- ``q`` -- a Blum prime
|
|
617
|
+
|
|
618
|
+
OUTPUT: the Blum-Goldwasser public key `n = pq`
|
|
619
|
+
|
|
620
|
+
Both ``p`` and ``q`` must be distinct Blum primes. Let `p` be a
|
|
621
|
+
positive prime. Then `p` is a Blum prime if `p` is congruent to 3
|
|
622
|
+
modulo 4, i.e. `p \equiv 3 \pmod{4}`.
|
|
623
|
+
|
|
624
|
+
EXAMPLES:
|
|
625
|
+
|
|
626
|
+
Obtain two distinct Blum primes and compute the Blum-Goldwasser
|
|
627
|
+
public key corresponding to those two Blum primes::
|
|
628
|
+
|
|
629
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
630
|
+
sage: from sage.crypto.util import is_blum_prime
|
|
631
|
+
sage: bg = BlumGoldwasser()
|
|
632
|
+
sage: P = primes_first_n(10); P # needs sage.libs.pari
|
|
633
|
+
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
|
|
634
|
+
sage: [is_blum_prime(_) for _ in P] # needs sage.libs.pari
|
|
635
|
+
[False, True, False, True, True, False, False, True, True, False]
|
|
636
|
+
sage: bg.public_key(3, 7)
|
|
637
|
+
21
|
|
638
|
+
|
|
639
|
+
Choose two distinct random Blum primes, compute the Blum-Goldwasser
|
|
640
|
+
public key corresponding to those two primes, and test that the
|
|
641
|
+
public key factorizes into Blum primes::
|
|
642
|
+
|
|
643
|
+
sage: # needs sage.libs.pari
|
|
644
|
+
sage: from sage.crypto.util import random_blum_prime
|
|
645
|
+
sage: p = random_blum_prime(10**4, 10**5)
|
|
646
|
+
sage: q = random_blum_prime(10**4, 10**5)
|
|
647
|
+
sage: while q == p:
|
|
648
|
+
....: q = random_blum_prime(10**4, 10**5)
|
|
649
|
+
...
|
|
650
|
+
sage: n = bg.public_key(p, q)
|
|
651
|
+
sage: f = factor(n)
|
|
652
|
+
sage: is_blum_prime(f[0][0]); is_blum_prime(f[1][0])
|
|
653
|
+
True
|
|
654
|
+
True
|
|
655
|
+
sage: p * q == f[0][0] * f[1][0]
|
|
656
|
+
True
|
|
657
|
+
|
|
658
|
+
TESTS:
|
|
659
|
+
|
|
660
|
+
The input ``p`` and ``q`` must be distinct Blum primes. ::
|
|
661
|
+
|
|
662
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
663
|
+
sage: bg = BlumGoldwasser()
|
|
664
|
+
sage: bg.public_key(3, 3)
|
|
665
|
+
Traceback (most recent call last):
|
|
666
|
+
...
|
|
667
|
+
ValueError: p and q must be distinct Blum primes.
|
|
668
|
+
sage: bg.public_key(23, 29)
|
|
669
|
+
Traceback (most recent call last):
|
|
670
|
+
...
|
|
671
|
+
ValueError: p and q must be distinct Blum primes.
|
|
672
|
+
"""
|
|
673
|
+
if p == q:
|
|
674
|
+
raise ValueError("p and q must be distinct Blum primes.")
|
|
675
|
+
if is_blum_prime(p) and is_blum_prime(q):
|
|
676
|
+
return p * q
|
|
677
|
+
else:
|
|
678
|
+
raise ValueError("p and q must be distinct Blum primes.")
|
|
679
|
+
|
|
680
|
+
def random_key(self, lbound, ubound, ntries=100):
|
|
681
|
+
r"""
|
|
682
|
+
Return a pair of random public and private keys.
|
|
683
|
+
|
|
684
|
+
INPUT:
|
|
685
|
+
|
|
686
|
+
- ``lbound`` -- positive integer; the lower bound on how small each
|
|
687
|
+
random Blum prime `p` and `q` can be. So we have
|
|
688
|
+
``0 < lower_bound <= p, q <= upper_bound``. The lower bound must
|
|
689
|
+
be distinct from the upper bound.
|
|
690
|
+
|
|
691
|
+
- ``ubound`` -- positive integer; the upper bound on how large each
|
|
692
|
+
random Blum prime `p` and `q` can be. So we have
|
|
693
|
+
``0 < lower_bound <= p, q <= upper_bound``. The lower bound must
|
|
694
|
+
be distinct from the upper bound.
|
|
695
|
+
|
|
696
|
+
- ``ntries`` -- (default: ``100``) the number of attempts to generate
|
|
697
|
+
a random public/private key pair. If ``ntries`` is a positive
|
|
698
|
+
integer, then perform that many attempts at generating a random
|
|
699
|
+
public/private key pair.
|
|
700
|
+
|
|
701
|
+
OUTPUT:
|
|
702
|
+
|
|
703
|
+
- A random public key and its corresponding private key. Each
|
|
704
|
+
randomly chosen `p` and `q` are guaranteed to be Blum primes. The
|
|
705
|
+
public key is `n = pq`, and the private key is `(p, q, a, b)` where
|
|
706
|
+
`\gcd(p, q) = ap + bq = 1`.
|
|
707
|
+
|
|
708
|
+
ALGORITHM:
|
|
709
|
+
|
|
710
|
+
The key generation algorithm is described in Algorithm 8.55,
|
|
711
|
+
page 308 of [MvOV1996]_. The algorithm works as follows:
|
|
712
|
+
|
|
713
|
+
#. Let `p` and `q` be distinct large random primes, each congruent
|
|
714
|
+
to 3 modulo 4. That is, `p` and `q` are Blum primes.
|
|
715
|
+
#. Let `n = pq` be the product of `p` and `q`.
|
|
716
|
+
#. Use the extended Euclidean algorithm to compute integers `a` and
|
|
717
|
+
`b` such that `\gcd(p, q) = ap + bq = 1`.
|
|
718
|
+
#. The public key is `n` and the corresponding private key is
|
|
719
|
+
`(p, q, a, b)`.
|
|
720
|
+
|
|
721
|
+
.. NOTE::
|
|
722
|
+
|
|
723
|
+
Beware that there might not be any primes between the lower and
|
|
724
|
+
upper bounds. So make sure that these two bounds are
|
|
725
|
+
"sufficiently" far apart from each other for there to be primes
|
|
726
|
+
congruent to 3 modulo 4. In particular, there should
|
|
727
|
+
be at least two distinct primes within these bounds, each prime
|
|
728
|
+
being congruent to 3 modulo 4.
|
|
729
|
+
|
|
730
|
+
EXAMPLES:
|
|
731
|
+
|
|
732
|
+
Choosing a random pair of public and private keys. We then test to see
|
|
733
|
+
if they satisfy the requirements of the Blum-Goldwasser scheme::
|
|
734
|
+
|
|
735
|
+
sage: # needs sage.libs.pari
|
|
736
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
737
|
+
sage: from sage.crypto.util import is_blum_prime
|
|
738
|
+
sage: bg = BlumGoldwasser()
|
|
739
|
+
sage: pubkey, prikey = bg.random_key(10**4, 10**5)
|
|
740
|
+
sage: p, q, a, b = prikey
|
|
741
|
+
sage: is_blum_prime(p); is_blum_prime(q)
|
|
742
|
+
True
|
|
743
|
+
True
|
|
744
|
+
sage: p == q
|
|
745
|
+
False
|
|
746
|
+
sage: pubkey == p*q
|
|
747
|
+
True
|
|
748
|
+
sage: gcd(p, q) == a*p + b*q == 1
|
|
749
|
+
True
|
|
750
|
+
|
|
751
|
+
TESTS:
|
|
752
|
+
|
|
753
|
+
Make sure that there is at least one Blum prime between the lower and
|
|
754
|
+
upper bounds. In the following example, we have ``lbound=24`` and
|
|
755
|
+
``ubound=30`` with 29 being the only prime within those bounds. But
|
|
756
|
+
29 is not a Blum prime. ::
|
|
757
|
+
|
|
758
|
+
sage: from sage.crypto.public_key.blum_goldwasser import BlumGoldwasser
|
|
759
|
+
sage: bg = BlumGoldwasser()
|
|
760
|
+
sage: pubkey, privkey = bg.random_key(24, 30) # needs sage.libs.pari
|
|
761
|
+
Traceback (most recent call last):
|
|
762
|
+
...
|
|
763
|
+
ValueError: No Blum primes within the specified closed interval.
|
|
764
|
+
"""
|
|
765
|
+
# choosing distinct random Blum primes
|
|
766
|
+
p = random_blum_prime(lbound=lbound, ubound=ubound, ntries=ntries)
|
|
767
|
+
q = random_blum_prime(lbound=lbound, ubound=ubound, ntries=ntries)
|
|
768
|
+
while p == q:
|
|
769
|
+
q = random_blum_prime(lbound=lbound, ubound=ubound, ntries=ntries)
|
|
770
|
+
# compute the public key
|
|
771
|
+
n = p * q
|
|
772
|
+
# compute the private key; here gcd(p, q) = 1 = a*p + b*q
|
|
773
|
+
bezout = xgcd(p, q)
|
|
774
|
+
a = bezout[1]
|
|
775
|
+
b = bezout[2]
|
|
776
|
+
return (n, (p, q, a, b))
|