passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_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 +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-503f0c35.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-aarch64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-aarch64-linux-musl.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-musl.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-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-aarch64-linux-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-aarch64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.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-musl.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-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-aarch64-linux-musl.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-musl.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,1527 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.rings.finite_rings
|
|
3
|
+
r"""
|
|
4
|
+
Simplified DES
|
|
5
|
+
|
|
6
|
+
A simplified variant of the Data Encryption Standard (DES). Note that
|
|
7
|
+
Simplified DES or S-DES is for educational purposes only. It is a
|
|
8
|
+
small-scale version of the DES designed to help beginners understand the
|
|
9
|
+
basic structure of DES.
|
|
10
|
+
|
|
11
|
+
AUTHORS:
|
|
12
|
+
|
|
13
|
+
- Minh Van Nguyen (2009-06): initial version
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# #########################################################################
|
|
17
|
+
# Copyright (c) 2009 Minh Van Nguyen <nguyenminh2@gmail.com>
|
|
18
|
+
#
|
|
19
|
+
# This program is free software; you can redistribute it and/or modify
|
|
20
|
+
# it under the terms of the GNU General Public License as published by
|
|
21
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
22
|
+
# (at your option) any later version.
|
|
23
|
+
#
|
|
24
|
+
# This program is distributed in the hope that it will be useful,
|
|
25
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
26
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
27
|
+
# GNU General Public License for more details.
|
|
28
|
+
#
|
|
29
|
+
# https://www.gnu.org/licenses/
|
|
30
|
+
# #########################################################################
|
|
31
|
+
|
|
32
|
+
from sage.monoids.string_monoid import BinaryStrings
|
|
33
|
+
from sage.structure.sage_object import SageObject
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SimplifiedDES(SageObject):
|
|
37
|
+
r"""
|
|
38
|
+
This class implements the Simplified Data Encryption Standard (S-DES)
|
|
39
|
+
described in [Sch1996]_. Schaefer's S-DES is for educational purposes
|
|
40
|
+
only and is not secure for practical purposes. S-DES is a version of
|
|
41
|
+
the DES with all parameters significantly reduced, but at the same time
|
|
42
|
+
preserving the structure of DES. The goal of S-DES is to allow a
|
|
43
|
+
beginner to understand the structure of DES, thus laying a foundation
|
|
44
|
+
for a thorough study of DES. Its goal is as a teaching tool in the same
|
|
45
|
+
spirit as Phan's
|
|
46
|
+
:mod:`Mini-AES <sage.crypto.block_cipher.miniaes>` [Pha2002]_.
|
|
47
|
+
|
|
48
|
+
EXAMPLES:
|
|
49
|
+
|
|
50
|
+
Encrypt a random block of 8-bit plaintext using a random key, decrypt
|
|
51
|
+
the ciphertext, and compare the result with the original plaintext::
|
|
52
|
+
|
|
53
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
54
|
+
sage: sdes = SimplifiedDES(); sdes
|
|
55
|
+
Simplified DES block cipher with 10-bit keys
|
|
56
|
+
sage: bin = BinaryStrings()
|
|
57
|
+
sage: P = [bin(str(randint(0, 1))) for i in range(8)]
|
|
58
|
+
sage: K = sdes.random_key()
|
|
59
|
+
sage: C = sdes.encrypt(P, K)
|
|
60
|
+
sage: plaintxt = sdes.decrypt(C, K)
|
|
61
|
+
sage: plaintxt == P
|
|
62
|
+
True
|
|
63
|
+
|
|
64
|
+
We can also encrypt binary strings that are larger than 8 bits in length.
|
|
65
|
+
However, the number of bits in that binary string must be positive
|
|
66
|
+
and a multiple of 8::
|
|
67
|
+
|
|
68
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
69
|
+
sage: sdes = SimplifiedDES()
|
|
70
|
+
sage: bin = BinaryStrings()
|
|
71
|
+
sage: P = bin.encoding("Encrypt this using S-DES!")
|
|
72
|
+
sage: Mod(len(P), 8) == 0
|
|
73
|
+
True
|
|
74
|
+
sage: K = sdes.list_to_string(sdes.random_key())
|
|
75
|
+
sage: C = sdes(P, K, algorithm='encrypt')
|
|
76
|
+
sage: plaintxt = sdes(C, K, algorithm='decrypt')
|
|
77
|
+
sage: plaintxt == P
|
|
78
|
+
True
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self):
|
|
82
|
+
r"""
|
|
83
|
+
A simplified variant of the Data Encryption Standard (DES).
|
|
84
|
+
|
|
85
|
+
EXAMPLES::
|
|
86
|
+
|
|
87
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
88
|
+
sage: sdes = SimplifiedDES(); sdes
|
|
89
|
+
Simplified DES block cipher with 10-bit keys
|
|
90
|
+
sage: B = BinaryStrings()
|
|
91
|
+
sage: P = [B(str(randint(0, 1))) for i in range(8)]
|
|
92
|
+
sage: K = sdes.random_key()
|
|
93
|
+
sage: C = sdes.encrypt(P, K)
|
|
94
|
+
sage: plaintxt = sdes.decrypt(C, K)
|
|
95
|
+
sage: plaintxt == P
|
|
96
|
+
True
|
|
97
|
+
"""
|
|
98
|
+
from sage.crypto.sbox import SBox
|
|
99
|
+
# the number of bits in a secret key
|
|
100
|
+
self._key_size = 10
|
|
101
|
+
# the S-box S_0
|
|
102
|
+
self._sbox0 = SBox(1, 0, 3, 2, 3, 2, 1, 0, 0, 2, 1, 3, 3, 1, 3, 2)
|
|
103
|
+
# the S-box S_1
|
|
104
|
+
self._sbox1 = SBox(0, 1, 2, 3, 2, 0, 1, 3, 3, 0, 1, 0, 2, 1, 0, 3)
|
|
105
|
+
|
|
106
|
+
def __call__(self, B, K, algorithm='encrypt'):
|
|
107
|
+
r"""
|
|
108
|
+
Apply S-DES encryption or decryption on the binary string ``B``
|
|
109
|
+
using the key ``K``. The flag ``algorithm`` controls what action is
|
|
110
|
+
to be performed on ``B``.
|
|
111
|
+
|
|
112
|
+
INPUT:
|
|
113
|
+
|
|
114
|
+
- ``B`` -- a binary string, where the number of bits is positive and
|
|
115
|
+
a multiple of 8
|
|
116
|
+
|
|
117
|
+
- ``K`` -- a secret key; this must be a 10-bit binary string
|
|
118
|
+
|
|
119
|
+
- ``algorithm`` -- (default: ``'encrypt'``) a string; a flag to signify
|
|
120
|
+
whether encryption or decryption is to be applied to the binary
|
|
121
|
+
string ``B``. The encryption flag is ``'encrypt'`` and the decryption
|
|
122
|
+
flag is ``'decrypt'``.
|
|
123
|
+
|
|
124
|
+
OUTPUT:
|
|
125
|
+
|
|
126
|
+
- The ciphertext (respectively plaintext) corresponding to the
|
|
127
|
+
binary string ``B``.
|
|
128
|
+
|
|
129
|
+
EXAMPLES:
|
|
130
|
+
|
|
131
|
+
Encrypt a plaintext, decrypt the ciphertext, and compare the
|
|
132
|
+
result with the original plaintext::
|
|
133
|
+
|
|
134
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
135
|
+
sage: sdes = SimplifiedDES()
|
|
136
|
+
sage: bin = BinaryStrings()
|
|
137
|
+
sage: P = bin.encoding("Encrypt this using DES!")
|
|
138
|
+
sage: K = sdes.random_key()
|
|
139
|
+
sage: K = sdes.list_to_string(K)
|
|
140
|
+
sage: C = sdes(P, K, algorithm='encrypt')
|
|
141
|
+
sage: plaintxt = sdes(C, K, algorithm='decrypt')
|
|
142
|
+
sage: plaintxt == P
|
|
143
|
+
True
|
|
144
|
+
|
|
145
|
+
TESTS:
|
|
146
|
+
|
|
147
|
+
The binary string ``B`` must be non-empty and the number of bits must
|
|
148
|
+
be a multiple of 8::
|
|
149
|
+
|
|
150
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
151
|
+
sage: sdes = SimplifiedDES()
|
|
152
|
+
sage: sdes("B", "K")
|
|
153
|
+
Traceback (most recent call last):
|
|
154
|
+
...
|
|
155
|
+
TypeError: input B must be a non-empty binary string with number of bits a multiple of 8
|
|
156
|
+
sage: bin = BinaryStrings()
|
|
157
|
+
sage: B = bin("101")
|
|
158
|
+
sage: sdes(B, "K")
|
|
159
|
+
Traceback (most recent call last):
|
|
160
|
+
...
|
|
161
|
+
ValueError: the number of bits in the binary string B must be positive and a multiple of 8
|
|
162
|
+
|
|
163
|
+
The secret key ``K`` must be a block of 10 bits::
|
|
164
|
+
|
|
165
|
+
sage: B = bin.encoding("abc")
|
|
166
|
+
sage: sdes(B, "K")
|
|
167
|
+
Traceback (most recent call last):
|
|
168
|
+
...
|
|
169
|
+
TypeError: secret key must be a 10-bit binary string
|
|
170
|
+
sage: K = bin("1010")
|
|
171
|
+
sage: sdes(B, K)
|
|
172
|
+
Traceback (most recent call last):
|
|
173
|
+
...
|
|
174
|
+
ValueError: secret key must be a 10-bit binary string
|
|
175
|
+
|
|
176
|
+
The value for ``algorithm`` must be either ``'encrypt'`` or
|
|
177
|
+
``'decrypt'``::
|
|
178
|
+
|
|
179
|
+
sage: B = bin.encoding("abc")
|
|
180
|
+
sage: K = sdes.list_to_string(sdes.random_key())
|
|
181
|
+
sage: sdes(B, K, algorithm='e')
|
|
182
|
+
Traceback (most recent call last):
|
|
183
|
+
...
|
|
184
|
+
ValueError: algorithm must be either 'encrypt' or 'decrypt'
|
|
185
|
+
sage: sdes(B, K, algorithm='d')
|
|
186
|
+
Traceback (most recent call last):
|
|
187
|
+
...
|
|
188
|
+
ValueError: algorithm must be either 'encrypt' or 'decrypt'
|
|
189
|
+
sage: sdes(B, K, algorithm='abc')
|
|
190
|
+
Traceback (most recent call last):
|
|
191
|
+
...
|
|
192
|
+
ValueError: algorithm must be either 'encrypt' or 'decrypt'
|
|
193
|
+
"""
|
|
194
|
+
from sage.monoids.string_monoid_element import StringMonoidElement
|
|
195
|
+
from sage.rings.finite_rings.integer_mod import Mod
|
|
196
|
+
# S-DES operates on 8-bit ciphertext/plaintext blocks
|
|
197
|
+
Blength = 8
|
|
198
|
+
|
|
199
|
+
if not isinstance(B, StringMonoidElement):
|
|
200
|
+
raise TypeError("input B must be a non-empty binary string with number of bits a multiple of 8")
|
|
201
|
+
if (len(B) == 0) or (Mod(len(B), Blength).lift() != 0):
|
|
202
|
+
raise ValueError("the number of bits in the binary string B must be positive and a multiple of 8")
|
|
203
|
+
if not isinstance(K, StringMonoidElement):
|
|
204
|
+
raise TypeError("secret key must be a 10-bit binary string")
|
|
205
|
+
if len(K) != self._key_size:
|
|
206
|
+
raise ValueError("secret key must be a 10-bit binary string")
|
|
207
|
+
|
|
208
|
+
N = len(B) // Blength # the number of 8-bit blocks
|
|
209
|
+
S = ""
|
|
210
|
+
bin = BinaryStrings()
|
|
211
|
+
# encrypt each 8-bit block in succession
|
|
212
|
+
if algorithm == "encrypt":
|
|
213
|
+
for i in range(N):
|
|
214
|
+
# get an 8-bit block
|
|
215
|
+
block = B[i*Blength : (i+1)*Blength]
|
|
216
|
+
block = self.string_to_list(str(block))
|
|
217
|
+
key = self.string_to_list(str(K))
|
|
218
|
+
# encrypt the block using key
|
|
219
|
+
C = self.encrypt(block, key)
|
|
220
|
+
C = self.list_to_string(C)
|
|
221
|
+
# append encrypted block to ciphertext string
|
|
222
|
+
S = "".join([S, str(C)])
|
|
223
|
+
return bin(S)
|
|
224
|
+
# decrypt each 8-bit block in succession
|
|
225
|
+
elif algorithm == "decrypt":
|
|
226
|
+
for i in range(N):
|
|
227
|
+
# get an 8-bit block
|
|
228
|
+
block = B[i*Blength : (i+1)*Blength]
|
|
229
|
+
block = self.string_to_list(str(block))
|
|
230
|
+
key = self.string_to_list(str(K))
|
|
231
|
+
# decrypt the block using key
|
|
232
|
+
P = self.decrypt(block, key)
|
|
233
|
+
P = self.list_to_string(P)
|
|
234
|
+
# append decrypted block to plaintext string
|
|
235
|
+
S = "".join([S, str(P)])
|
|
236
|
+
return bin(S)
|
|
237
|
+
# invalid value for algorithm option
|
|
238
|
+
else:
|
|
239
|
+
raise ValueError("algorithm must be either 'encrypt' or 'decrypt'")
|
|
240
|
+
|
|
241
|
+
def __eq__(self, other):
|
|
242
|
+
r"""
|
|
243
|
+
Compare ``self`` with ``other``.
|
|
244
|
+
|
|
245
|
+
Simplified DES objects are the same if they have the same key size
|
|
246
|
+
and S-boxes.
|
|
247
|
+
|
|
248
|
+
EXAMPLES::
|
|
249
|
+
|
|
250
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
251
|
+
sage: s = SimplifiedDES()
|
|
252
|
+
sage: s == loads(dumps(s))
|
|
253
|
+
True
|
|
254
|
+
"""
|
|
255
|
+
return ( (self._key_size == other._key_size) and
|
|
256
|
+
(self._sbox0 == other._sbox0) and
|
|
257
|
+
(self._sbox1 == other._sbox1) )
|
|
258
|
+
|
|
259
|
+
def __repr__(self):
|
|
260
|
+
r"""
|
|
261
|
+
A string representation of this Simplified DES.
|
|
262
|
+
|
|
263
|
+
EXAMPLES::
|
|
264
|
+
|
|
265
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
266
|
+
sage: SimplifiedDES()
|
|
267
|
+
Simplified DES block cipher with 10-bit keys
|
|
268
|
+
"""
|
|
269
|
+
return "Simplified DES block cipher with 10-bit keys"
|
|
270
|
+
|
|
271
|
+
def block_length(self):
|
|
272
|
+
r"""
|
|
273
|
+
Return the block length of Schaefer's S-DES block cipher. A key in
|
|
274
|
+
Schaefer's S-DES is a block of 10 bits.
|
|
275
|
+
|
|
276
|
+
OUTPUT:
|
|
277
|
+
|
|
278
|
+
- The block (or key) length in number of bits.
|
|
279
|
+
|
|
280
|
+
EXAMPLES::
|
|
281
|
+
|
|
282
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
283
|
+
sage: sdes = SimplifiedDES()
|
|
284
|
+
sage: sdes.block_length()
|
|
285
|
+
10
|
|
286
|
+
"""
|
|
287
|
+
return self._key_size
|
|
288
|
+
|
|
289
|
+
def decrypt(self, C, K):
|
|
290
|
+
r"""
|
|
291
|
+
Return an 8-bit plaintext corresponding to the ciphertext ``C``,
|
|
292
|
+
using S-DES decryption with key ``K``. The decryption process of
|
|
293
|
+
S-DES is as follows. Let `P` be the initial permutation function,
|
|
294
|
+
`P^{-1}` the corresponding inverse permutation, `\Pi_F` the
|
|
295
|
+
permutation/substitution function, and `\sigma` the switch function.
|
|
296
|
+
The ciphertext block ``C`` first goes through `P`, the output of
|
|
297
|
+
which goes through `\Pi_F` using the second subkey. Then we apply
|
|
298
|
+
the switch function to the output of the last function, and the
|
|
299
|
+
result is then fed into `\Pi_F` using the first subkey. Finally,
|
|
300
|
+
run the output through `P^{-1}` to get the plaintext.
|
|
301
|
+
|
|
302
|
+
INPUT:
|
|
303
|
+
|
|
304
|
+
- ``C`` -- an 8-bit ciphertext; a block of 8 bits
|
|
305
|
+
|
|
306
|
+
- ``K`` -- a 10-bit key; a block of 10 bits
|
|
307
|
+
|
|
308
|
+
OUTPUT:
|
|
309
|
+
|
|
310
|
+
The 8-bit plaintext corresponding to ``C``, obtained using the
|
|
311
|
+
key ``K``.
|
|
312
|
+
|
|
313
|
+
EXAMPLES:
|
|
314
|
+
|
|
315
|
+
Decrypt an 8-bit ciphertext block::
|
|
316
|
+
|
|
317
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
318
|
+
sage: sdes = SimplifiedDES()
|
|
319
|
+
sage: C = [0, 1, 0, 1, 0, 1, 0, 1]
|
|
320
|
+
sage: K = [1, 0, 1, 0, 0, 0, 0, 0, 1, 0]
|
|
321
|
+
sage: sdes.decrypt(C, K)
|
|
322
|
+
[0, 0, 0, 1, 0, 1, 0, 1]
|
|
323
|
+
|
|
324
|
+
We can also work with strings of bits::
|
|
325
|
+
|
|
326
|
+
sage: C = "01010101"
|
|
327
|
+
sage: K = "1010000010"
|
|
328
|
+
sage: sdes.decrypt(sdes.string_to_list(C), sdes.string_to_list(K))
|
|
329
|
+
[0, 0, 0, 1, 0, 1, 0, 1]
|
|
330
|
+
|
|
331
|
+
TESTS:
|
|
332
|
+
|
|
333
|
+
The ciphertext must be a block of 8 bits::
|
|
334
|
+
|
|
335
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
336
|
+
sage: sdes = SimplifiedDES()
|
|
337
|
+
sage: sdes.decrypt("C", "K")
|
|
338
|
+
Traceback (most recent call last):
|
|
339
|
+
...
|
|
340
|
+
TypeError: ciphertext must be a list of 8 bits
|
|
341
|
+
sage: sdes.decrypt([], "K")
|
|
342
|
+
Traceback (most recent call last):
|
|
343
|
+
...
|
|
344
|
+
ValueError: ciphertext must be a list of 8 bits
|
|
345
|
+
sage: sdes.decrypt([1, 2, 3, 4], "K")
|
|
346
|
+
Traceback (most recent call last):
|
|
347
|
+
...
|
|
348
|
+
ValueError: ciphertext must be a list of 8 bits
|
|
349
|
+
|
|
350
|
+
The key must be a block of 10 bits::
|
|
351
|
+
|
|
352
|
+
sage: sdes.decrypt([1, 0, 1, 0, 1, 1, 0, 1], "K")
|
|
353
|
+
Traceback (most recent call last):
|
|
354
|
+
...
|
|
355
|
+
TypeError: the key must be a list of 10 bits
|
|
356
|
+
sage: sdes.decrypt([1, 0, 1, 0, 1, 1, 0, 1], [])
|
|
357
|
+
Traceback (most recent call last):
|
|
358
|
+
...
|
|
359
|
+
TypeError: the key must be a list of 10 bits
|
|
360
|
+
sage: sdes.decrypt([1, 0, 1, 0, 1, 1, 0, 1], [1, 2, 3, 4, 5])
|
|
361
|
+
Traceback (most recent call last):
|
|
362
|
+
...
|
|
363
|
+
TypeError: the key must be a list of 10 bits
|
|
364
|
+
|
|
365
|
+
The value of each element of ``C`` or ``K`` must be either 0 or 1::
|
|
366
|
+
|
|
367
|
+
sage: C = [1, 2, 3, 4, 5, 6, 7, 8]
|
|
368
|
+
sage: K = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
|
369
|
+
sage: sdes.decrypt(C, K)
|
|
370
|
+
Traceback (most recent call last):
|
|
371
|
+
...
|
|
372
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
373
|
+
sage: C = [0, 1, 0, 0, 1, 1, 1, 0]
|
|
374
|
+
sage: K = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
|
375
|
+
sage: sdes.decrypt(C, K)
|
|
376
|
+
Traceback (most recent call last):
|
|
377
|
+
...
|
|
378
|
+
TypeError: Argument x (= 13) is not a valid string.
|
|
379
|
+
"""
|
|
380
|
+
# sanity check
|
|
381
|
+
if not isinstance(C, list):
|
|
382
|
+
raise TypeError("ciphertext must be a list of 8 bits")
|
|
383
|
+
if len(C) != 8:
|
|
384
|
+
raise ValueError("ciphertext must be a list of 8 bits")
|
|
385
|
+
if not isinstance(K, list):
|
|
386
|
+
raise TypeError("the key must be a list of 10 bits")
|
|
387
|
+
if len(K) != 10:
|
|
388
|
+
raise TypeError("the key must be a list of 10 bits")
|
|
389
|
+
|
|
390
|
+
# run through initial permutation
|
|
391
|
+
P = self.initial_permutation(C, inverse=False)
|
|
392
|
+
# run through Pi_F with subkey 2
|
|
393
|
+
P = self.permute_substitute(P, self.subkey(K, n=2))
|
|
394
|
+
# run through switch function
|
|
395
|
+
P = self.switch(P)
|
|
396
|
+
# run through Pi_F with subkey 1
|
|
397
|
+
P = self.permute_substitute(P, self.subkey(K, n=1))
|
|
398
|
+
# run through inverse permutation
|
|
399
|
+
P = self.initial_permutation(P, inverse=True)
|
|
400
|
+
# output the plaintext
|
|
401
|
+
return P
|
|
402
|
+
|
|
403
|
+
def encrypt(self, P, K):
|
|
404
|
+
r"""
|
|
405
|
+
Return an 8-bit ciphertext corresponding to the plaintext ``P``,
|
|
406
|
+
using S-DES encryption with key ``K``. The encryption process of
|
|
407
|
+
S-DES is as follows. Let `P` be the initial permutation function,
|
|
408
|
+
`P^{-1}` the corresponding inverse permutation, `\Pi_F` the
|
|
409
|
+
permutation/substitution function, and `\sigma` the switch function.
|
|
410
|
+
The plaintext block ``P`` first goes through `P`, the output of
|
|
411
|
+
which goes through `\Pi_F` using the first subkey. Then we apply
|
|
412
|
+
the switch function to the output of the last function, and the
|
|
413
|
+
result is then fed into `\Pi_F` using the second subkey. Finally,
|
|
414
|
+
run the output through `P^{-1}` to get the ciphertext.
|
|
415
|
+
|
|
416
|
+
INPUT:
|
|
417
|
+
|
|
418
|
+
- ``P`` -- an 8-bit plaintext; a block of 8 bits
|
|
419
|
+
|
|
420
|
+
- ``K`` -- a 10-bit key; a block of 10 bits
|
|
421
|
+
|
|
422
|
+
OUTPUT:
|
|
423
|
+
|
|
424
|
+
The 8-bit ciphertext corresponding to ``P``, obtained using the
|
|
425
|
+
key ``K``.
|
|
426
|
+
|
|
427
|
+
EXAMPLES:
|
|
428
|
+
|
|
429
|
+
Encrypt an 8-bit plaintext block::
|
|
430
|
+
|
|
431
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
432
|
+
sage: sdes = SimplifiedDES()
|
|
433
|
+
sage: P = [0, 1, 0, 1, 0, 1, 0, 1]
|
|
434
|
+
sage: K = [1, 0, 1, 0, 0, 0, 0, 0, 1, 0]
|
|
435
|
+
sage: sdes.encrypt(P, K)
|
|
436
|
+
[1, 1, 0, 0, 0, 0, 0, 1]
|
|
437
|
+
|
|
438
|
+
We can also work with strings of bits::
|
|
439
|
+
|
|
440
|
+
sage: P = "01010101"
|
|
441
|
+
sage: K = "1010000010"
|
|
442
|
+
sage: sdes.encrypt(sdes.string_to_list(P), sdes.string_to_list(K))
|
|
443
|
+
[1, 1, 0, 0, 0, 0, 0, 1]
|
|
444
|
+
|
|
445
|
+
TESTS:
|
|
446
|
+
|
|
447
|
+
The plaintext must be a block of 8 bits::
|
|
448
|
+
|
|
449
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
450
|
+
sage: sdes = SimplifiedDES()
|
|
451
|
+
sage: sdes.encrypt("P", "K")
|
|
452
|
+
Traceback (most recent call last):
|
|
453
|
+
...
|
|
454
|
+
TypeError: plaintext must be a list of 8 bits
|
|
455
|
+
sage: sdes.encrypt([], "K")
|
|
456
|
+
Traceback (most recent call last):
|
|
457
|
+
...
|
|
458
|
+
ValueError: plaintext must be a list of 8 bits
|
|
459
|
+
sage: sdes.encrypt([1, 2, 3, 4], "K")
|
|
460
|
+
Traceback (most recent call last):
|
|
461
|
+
...
|
|
462
|
+
ValueError: plaintext must be a list of 8 bits
|
|
463
|
+
|
|
464
|
+
The key must be a block of 10 bits::
|
|
465
|
+
|
|
466
|
+
sage: sdes.encrypt([1, 0, 1, 0, 1, 1, 0, 1], "K")
|
|
467
|
+
Traceback (most recent call last):
|
|
468
|
+
...
|
|
469
|
+
TypeError: the key must be a list of 10 bits
|
|
470
|
+
sage: sdes.encrypt([1, 0, 1, 0, 1, 1, 0, 1], [])
|
|
471
|
+
Traceback (most recent call last):
|
|
472
|
+
...
|
|
473
|
+
TypeError: the key must be a list of 10 bits
|
|
474
|
+
sage: sdes.encrypt([1, 0, 1, 0, 1, 1, 0, 1], [1, 2, 3, 4, 5])
|
|
475
|
+
Traceback (most recent call last):
|
|
476
|
+
...
|
|
477
|
+
TypeError: the key must be a list of 10 bits
|
|
478
|
+
|
|
479
|
+
The value of each element of ``P`` or ``K`` must be either 0 or 1::
|
|
480
|
+
|
|
481
|
+
sage: P = [1, 2, 3, 4, 5, 6, 7, 8]
|
|
482
|
+
sage: K = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
|
483
|
+
sage: sdes.encrypt(P, K)
|
|
484
|
+
Traceback (most recent call last):
|
|
485
|
+
...
|
|
486
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
487
|
+
sage: P = [0, 1, 0, 0, 1, 1, 1, 0]
|
|
488
|
+
sage: K = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
|
489
|
+
sage: sdes.encrypt(P, K)
|
|
490
|
+
Traceback (most recent call last):
|
|
491
|
+
...
|
|
492
|
+
TypeError: Argument x (= 13) is not a valid string.
|
|
493
|
+
"""
|
|
494
|
+
# sanity check
|
|
495
|
+
if not isinstance(P, list):
|
|
496
|
+
raise TypeError("plaintext must be a list of 8 bits")
|
|
497
|
+
if len(P) != 8:
|
|
498
|
+
raise ValueError("plaintext must be a list of 8 bits")
|
|
499
|
+
if not isinstance(K, list):
|
|
500
|
+
raise TypeError("the key must be a list of 10 bits")
|
|
501
|
+
if len(K) != 10:
|
|
502
|
+
raise TypeError("the key must be a list of 10 bits")
|
|
503
|
+
|
|
504
|
+
# run through initial permutation
|
|
505
|
+
C = self.initial_permutation(P, inverse=False)
|
|
506
|
+
# run through Pi_F with subkey 1
|
|
507
|
+
C = self.permute_substitute(C, self.subkey(K, n=1))
|
|
508
|
+
# run through switch function
|
|
509
|
+
C = self.switch(C)
|
|
510
|
+
# run through Pi_F with subkey 2
|
|
511
|
+
C = self.permute_substitute(C, self.subkey(K, n=2))
|
|
512
|
+
# run through inverse permutation
|
|
513
|
+
C = self.initial_permutation(C, inverse=True)
|
|
514
|
+
# output the ciphertext
|
|
515
|
+
return C
|
|
516
|
+
|
|
517
|
+
def initial_permutation(self, B, inverse=False):
|
|
518
|
+
r"""
|
|
519
|
+
Return the initial permutation of ``B``. Denote the initial
|
|
520
|
+
permutation function by `P` and let `(b_0, b_1, b_2, \dots, b_7)`
|
|
521
|
+
be a vector of 8 bits, where each `b_i \in \{ 0, 1 \}`. Then
|
|
522
|
+
|
|
523
|
+
.. MATH::
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
P(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7)
|
|
527
|
+
= (b_1, b_5, b_2, b_0, b_3, b_7, b_4, b_6)
|
|
528
|
+
|
|
529
|
+
The inverse permutation is `P^{-1}`:
|
|
530
|
+
|
|
531
|
+
.. MATH::
|
|
532
|
+
|
|
533
|
+
P^{-1}(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7)
|
|
534
|
+
= (b_3, b_0, b_2, b_4, b_6, b_1, b_7, b_5)
|
|
535
|
+
|
|
536
|
+
INPUT:
|
|
537
|
+
|
|
538
|
+
- ``B`` -- list; a block of 8 bits
|
|
539
|
+
|
|
540
|
+
- ``inverse`` -- boolean (default: ``False``); if ``True`` then use the
|
|
541
|
+
inverse permutation `P^{-1}`. If ``False`` then use the initial
|
|
542
|
+
permutation `P`.
|
|
543
|
+
|
|
544
|
+
OUTPUT:
|
|
545
|
+
|
|
546
|
+
The initial permutation of ``B`` if ``inverse=False``, or the
|
|
547
|
+
inverse permutation of ``B`` if ``inverse=True``.
|
|
548
|
+
|
|
549
|
+
EXAMPLES:
|
|
550
|
+
|
|
551
|
+
The initial permutation of a list of 8 bits::
|
|
552
|
+
|
|
553
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
554
|
+
sage: sdes = SimplifiedDES()
|
|
555
|
+
sage: B = [1, 0, 1, 1, 0, 1, 0, 0]
|
|
556
|
+
sage: P = sdes.initial_permutation(B); P
|
|
557
|
+
[0, 1, 1, 1, 1, 0, 0, 0]
|
|
558
|
+
|
|
559
|
+
Recovering the original list of 8 bits from the permutation::
|
|
560
|
+
|
|
561
|
+
sage: Pinv = sdes.initial_permutation(P, inverse=True)
|
|
562
|
+
sage: Pinv; B
|
|
563
|
+
[1, 0, 1, 1, 0, 1, 0, 0]
|
|
564
|
+
[1, 0, 1, 1, 0, 1, 0, 0]
|
|
565
|
+
|
|
566
|
+
We can also work with a string of bits::
|
|
567
|
+
|
|
568
|
+
sage: S = "10110100"
|
|
569
|
+
sage: L = sdes.string_to_list(S)
|
|
570
|
+
sage: P = sdes.initial_permutation(L); P
|
|
571
|
+
[0, 1, 1, 1, 1, 0, 0, 0]
|
|
572
|
+
sage: sdes.initial_permutation(sdes.string_to_list("01111000"), inverse=True)
|
|
573
|
+
[1, 0, 1, 1, 0, 1, 0, 0]
|
|
574
|
+
|
|
575
|
+
TESTS:
|
|
576
|
+
|
|
577
|
+
The input block must be a list::
|
|
578
|
+
|
|
579
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
580
|
+
sage: sdes = SimplifiedDES()
|
|
581
|
+
sage: sdes.initial_permutation("B")
|
|
582
|
+
Traceback (most recent call last):
|
|
583
|
+
...
|
|
584
|
+
TypeError: input block must be a list of 8 bits
|
|
585
|
+
sage: sdes.initial_permutation(())
|
|
586
|
+
Traceback (most recent call last):
|
|
587
|
+
...
|
|
588
|
+
TypeError: input block must be a list of 8 bits
|
|
589
|
+
|
|
590
|
+
The input block must be a list of 8 bits::
|
|
591
|
+
|
|
592
|
+
sage: sdes.initial_permutation([])
|
|
593
|
+
Traceback (most recent call last):
|
|
594
|
+
...
|
|
595
|
+
ValueError: input block must be a list of 8 bits
|
|
596
|
+
sage: sdes.initial_permutation([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
|
597
|
+
Traceback (most recent call last):
|
|
598
|
+
...
|
|
599
|
+
ValueError: input block must be a list of 8 bits
|
|
600
|
+
|
|
601
|
+
The value of each element of the list must be either 0 or 1::
|
|
602
|
+
|
|
603
|
+
sage: sdes.initial_permutation([1, 2, 3, 4, 5, 6, 7, 8])
|
|
604
|
+
Traceback (most recent call last):
|
|
605
|
+
...
|
|
606
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
607
|
+
"""
|
|
608
|
+
# sanity check
|
|
609
|
+
if not isinstance(B, list):
|
|
610
|
+
raise TypeError("input block must be a list of 8 bits")
|
|
611
|
+
if len(B) != 8:
|
|
612
|
+
raise ValueError("input block must be a list of 8 bits")
|
|
613
|
+
|
|
614
|
+
bin = BinaryStrings()
|
|
615
|
+
|
|
616
|
+
# use the initial permutation P
|
|
617
|
+
if not inverse:
|
|
618
|
+
return [ bin(str(B[1])), bin(str(B[5])),
|
|
619
|
+
bin(str(B[2])), bin(str(B[0])),
|
|
620
|
+
bin(str(B[3])), bin(str(B[7])),
|
|
621
|
+
bin(str(B[4])), bin(str(B[6])) ]
|
|
622
|
+
|
|
623
|
+
# use the inverse permutation P^-1
|
|
624
|
+
if inverse:
|
|
625
|
+
return [ bin(str(B[3])), bin(str(B[0])),
|
|
626
|
+
bin(str(B[2])), bin(str(B[4])),
|
|
627
|
+
bin(str(B[6])), bin(str(B[1])),
|
|
628
|
+
bin(str(B[7])), bin(str(B[5])) ]
|
|
629
|
+
|
|
630
|
+
def left_shift(self, B, n=1):
|
|
631
|
+
r"""
|
|
632
|
+
Return a circular left shift of ``B`` by ``n`` positions. Let
|
|
633
|
+
`B = (b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)` be a vector
|
|
634
|
+
of 10 bits. Then the left shift operation `L_n` is performed on the
|
|
635
|
+
first 5 bits and the last 5 bits of `B` separately. That is, if the
|
|
636
|
+
number of shift positions is ``n=1``, then `L_1` is defined as
|
|
637
|
+
|
|
638
|
+
.. MATH::
|
|
639
|
+
|
|
640
|
+
L_1(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)
|
|
641
|
+
= (b_1, b_2, b_3, b_4, b_0, b_6, b_7, b_8, b_9, b_5)
|
|
642
|
+
|
|
643
|
+
If the number of shift positions is ``n=2``, then `L_2` is given by
|
|
644
|
+
|
|
645
|
+
.. MATH::
|
|
646
|
+
|
|
647
|
+
L_2(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)
|
|
648
|
+
= (b_2, b_3, b_4, b_0, b_1, b_7, b_8, b_9, b_5, b_6)
|
|
649
|
+
|
|
650
|
+
INPUT:
|
|
651
|
+
|
|
652
|
+
- ``B`` -- list of 10 bits
|
|
653
|
+
|
|
654
|
+
- ``n`` -- (default: 1) if ``n=1`` then perform left shift by 1
|
|
655
|
+
position; if ``n=2`` then perform left shift by 2 positions. The
|
|
656
|
+
valid values for ``n`` are 1 and 2, since only up to 2 positions
|
|
657
|
+
are defined for this circular left shift operation.
|
|
658
|
+
|
|
659
|
+
OUTPUT: the circular left shift of each half of ``B``
|
|
660
|
+
|
|
661
|
+
EXAMPLES:
|
|
662
|
+
|
|
663
|
+
Circular left shift by 1 position of a 10-bit string::
|
|
664
|
+
|
|
665
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
666
|
+
sage: sdes = SimplifiedDES()
|
|
667
|
+
sage: B = [1, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
|
668
|
+
sage: sdes.left_shift(B)
|
|
669
|
+
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
|
|
670
|
+
sage: sdes.left_shift([1, 0, 1, 0, 0, 0, 0, 0, 1, 0])
|
|
671
|
+
[0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
|
|
672
|
+
|
|
673
|
+
Circular left shift by 2 positions of a 10-bit string::
|
|
674
|
+
|
|
675
|
+
sage: B = [0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
|
|
676
|
+
sage: sdes.left_shift(B, n=2)
|
|
677
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 1, 1]
|
|
678
|
+
|
|
679
|
+
Here we work with a string of bits::
|
|
680
|
+
|
|
681
|
+
sage: S = "1000001100"
|
|
682
|
+
sage: L = sdes.string_to_list(S)
|
|
683
|
+
sage: sdes.left_shift(L)
|
|
684
|
+
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
|
|
685
|
+
sage: sdes.left_shift(sdes.string_to_list("1010000010"), n=2)
|
|
686
|
+
[1, 0, 0, 1, 0, 0, 1, 0, 0, 0]
|
|
687
|
+
|
|
688
|
+
TESTS:
|
|
689
|
+
|
|
690
|
+
The input block must be a list::
|
|
691
|
+
|
|
692
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
693
|
+
sage: sdes = SimplifiedDES()
|
|
694
|
+
sage: sdes.left_shift("B")
|
|
695
|
+
Traceback (most recent call last):
|
|
696
|
+
...
|
|
697
|
+
TypeError: input block must be a list of 10 bits
|
|
698
|
+
sage: sdes.left_shift(())
|
|
699
|
+
Traceback (most recent call last):
|
|
700
|
+
...
|
|
701
|
+
TypeError: input block must be a list of 10 bits
|
|
702
|
+
|
|
703
|
+
The input block must be a list of 10 bits::
|
|
704
|
+
|
|
705
|
+
sage: sdes.left_shift([])
|
|
706
|
+
Traceback (most recent call last):
|
|
707
|
+
...
|
|
708
|
+
ValueError: input block must be a list of 10 bits
|
|
709
|
+
sage: sdes.left_shift([1, 2, 3, 4, 5])
|
|
710
|
+
Traceback (most recent call last):
|
|
711
|
+
...
|
|
712
|
+
ValueError: input block must be a list of 10 bits
|
|
713
|
+
|
|
714
|
+
The value of each element of the list must be either 0 or 1::
|
|
715
|
+
|
|
716
|
+
sage: sdes.left_shift([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
717
|
+
Traceback (most recent call last):
|
|
718
|
+
...
|
|
719
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
720
|
+
|
|
721
|
+
The number of shift positions must be either 1 or 2::
|
|
722
|
+
|
|
723
|
+
sage: B = [0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
|
|
724
|
+
sage: sdes.left_shift(B, n=-1)
|
|
725
|
+
Traceback (most recent call last):
|
|
726
|
+
...
|
|
727
|
+
ValueError: input n must be either 1 or 2
|
|
728
|
+
sage: sdes.left_shift(B, n=3)
|
|
729
|
+
Traceback (most recent call last):
|
|
730
|
+
...
|
|
731
|
+
ValueError: input n must be either 1 or 2
|
|
732
|
+
"""
|
|
733
|
+
# sanity check
|
|
734
|
+
if not isinstance(B, list):
|
|
735
|
+
raise TypeError("input block must be a list of 10 bits")
|
|
736
|
+
if len(B) != 10:
|
|
737
|
+
raise ValueError("input block must be a list of 10 bits")
|
|
738
|
+
|
|
739
|
+
bin = BinaryStrings()
|
|
740
|
+
# circular left shift by 1 position
|
|
741
|
+
if n == 1:
|
|
742
|
+
return [ bin(str(B[1])), bin(str(B[2])),
|
|
743
|
+
bin(str(B[3])), bin(str(B[4])),
|
|
744
|
+
bin(str(B[0])), bin(str(B[6])),
|
|
745
|
+
bin(str(B[7])), bin(str(B[8])),
|
|
746
|
+
bin(str(B[9])), bin(str(B[5])) ]
|
|
747
|
+
# circular left shift by 2 positions
|
|
748
|
+
elif n == 2:
|
|
749
|
+
return [ bin(str(B[2])), bin(str(B[3])),
|
|
750
|
+
bin(str(B[4])), bin(str(B[0])),
|
|
751
|
+
bin(str(B[1])), bin(str(B[7])),
|
|
752
|
+
bin(str(B[8])), bin(str(B[9])),
|
|
753
|
+
bin(str(B[5])), bin(str(B[6])) ]
|
|
754
|
+
# an invalid number of shift positions
|
|
755
|
+
else:
|
|
756
|
+
raise ValueError("input n must be either 1 or 2")
|
|
757
|
+
|
|
758
|
+
def list_to_string(self, B):
|
|
759
|
+
r"""
|
|
760
|
+
Return a binary string representation of the list ``B``.
|
|
761
|
+
|
|
762
|
+
INPUT:
|
|
763
|
+
|
|
764
|
+
- ``B`` -- a non-empty list of bits
|
|
765
|
+
|
|
766
|
+
OUTPUT: the binary string representation of ``B``
|
|
767
|
+
|
|
768
|
+
EXAMPLES:
|
|
769
|
+
|
|
770
|
+
A binary string representation of a list of bits::
|
|
771
|
+
|
|
772
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
773
|
+
sage: sdes = SimplifiedDES()
|
|
774
|
+
sage: L = [0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
|
|
775
|
+
sage: sdes.list_to_string(L)
|
|
776
|
+
0000110100
|
|
777
|
+
|
|
778
|
+
TESTS:
|
|
779
|
+
|
|
780
|
+
Input ``B`` must be a non-empty list::
|
|
781
|
+
|
|
782
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
783
|
+
sage: sdes = SimplifiedDES()
|
|
784
|
+
sage: sdes.list_to_string("L")
|
|
785
|
+
Traceback (most recent call last):
|
|
786
|
+
...
|
|
787
|
+
TypeError: input B must be a non-empty list of bits
|
|
788
|
+
sage: sdes.list_to_string([])
|
|
789
|
+
Traceback (most recent call last):
|
|
790
|
+
...
|
|
791
|
+
ValueError: input B must be a non-empty list of bits
|
|
792
|
+
|
|
793
|
+
Input must be a non-empty list of bits::
|
|
794
|
+
|
|
795
|
+
sage: sdes.list_to_string([0, 1, 2])
|
|
796
|
+
<repr(<sage.monoids.string_monoid_element.StringMonoidElement at 0x...>) failed: IndexError: tuple index out of range>
|
|
797
|
+
"""
|
|
798
|
+
# sanity check
|
|
799
|
+
if not isinstance(B, list):
|
|
800
|
+
raise TypeError("input B must be a non-empty list of bits")
|
|
801
|
+
if len(B) == 0:
|
|
802
|
+
raise ValueError("input B must be a non-empty list of bits")
|
|
803
|
+
|
|
804
|
+
# perform the conversion from list to binary string
|
|
805
|
+
from sage.rings.integer import Integer
|
|
806
|
+
bin = BinaryStrings()
|
|
807
|
+
return bin([Integer(str(b)) for b in B])
|
|
808
|
+
|
|
809
|
+
def permutation4(self, B):
|
|
810
|
+
r"""
|
|
811
|
+
Return a permutation of a 4-bit string. This permutation is called
|
|
812
|
+
`P_4` and is specified as follows. Let
|
|
813
|
+
`(b_0, b_1, b_2, b_3)` be a vector of 4 bits where each
|
|
814
|
+
`b_i \in \{ 0, 1 \}`. Then `P_4` is defined by
|
|
815
|
+
|
|
816
|
+
.. MATH::
|
|
817
|
+
|
|
818
|
+
P_4(b_0, b_1, b_2, b_3) = (b_1, b_3, b_2, b_0)
|
|
819
|
+
|
|
820
|
+
INPUT:
|
|
821
|
+
|
|
822
|
+
- ``B`` -- a block of 4-bit string
|
|
823
|
+
|
|
824
|
+
OUTPUT: a permutation of ``B``
|
|
825
|
+
|
|
826
|
+
EXAMPLES:
|
|
827
|
+
|
|
828
|
+
Permute a 4-bit string::
|
|
829
|
+
|
|
830
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
831
|
+
sage: sdes = SimplifiedDES()
|
|
832
|
+
sage: B = [1, 1, 0, 0]
|
|
833
|
+
sage: sdes.permutation4(B)
|
|
834
|
+
[1, 0, 0, 1]
|
|
835
|
+
sage: sdes.permutation4([0, 1, 0, 1])
|
|
836
|
+
[1, 1, 0, 0]
|
|
837
|
+
|
|
838
|
+
We can also work with a string of bits::
|
|
839
|
+
|
|
840
|
+
sage: S = "1100"
|
|
841
|
+
sage: L = sdes.string_to_list(S)
|
|
842
|
+
sage: sdes.permutation4(L)
|
|
843
|
+
[1, 0, 0, 1]
|
|
844
|
+
sage: sdes.permutation4(sdes.string_to_list("0101"))
|
|
845
|
+
[1, 1, 0, 0]
|
|
846
|
+
|
|
847
|
+
TESTS:
|
|
848
|
+
|
|
849
|
+
The input block must be a list::
|
|
850
|
+
|
|
851
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
852
|
+
sage: sdes = SimplifiedDES()
|
|
853
|
+
sage: sdes.permutation4("B")
|
|
854
|
+
Traceback (most recent call last):
|
|
855
|
+
...
|
|
856
|
+
TypeError: input block must be a list of 4 bits
|
|
857
|
+
sage: sdes.permutation4(())
|
|
858
|
+
Traceback (most recent call last):
|
|
859
|
+
...
|
|
860
|
+
TypeError: input block must be a list of 4 bits
|
|
861
|
+
|
|
862
|
+
The input block must be a list of 4 bits::
|
|
863
|
+
|
|
864
|
+
sage: sdes.permutation4([])
|
|
865
|
+
Traceback (most recent call last):
|
|
866
|
+
...
|
|
867
|
+
ValueError: input block must be a list of 4 bits
|
|
868
|
+
sage: sdes.permutation4([1, 2, 3, 4, 5])
|
|
869
|
+
Traceback (most recent call last):
|
|
870
|
+
...
|
|
871
|
+
ValueError: input block must be a list of 4 bits
|
|
872
|
+
|
|
873
|
+
The value of each element of the list must be either 0 or 1::
|
|
874
|
+
|
|
875
|
+
sage: sdes.permutation4([1, 2, 3, 4])
|
|
876
|
+
Traceback (most recent call last):
|
|
877
|
+
...
|
|
878
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
879
|
+
"""
|
|
880
|
+
# sanity check
|
|
881
|
+
if not isinstance(B, list):
|
|
882
|
+
raise TypeError("input block must be a list of 4 bits")
|
|
883
|
+
if len(B) != 4:
|
|
884
|
+
raise ValueError("input block must be a list of 4 bits")
|
|
885
|
+
|
|
886
|
+
# perform the permutation
|
|
887
|
+
bin = BinaryStrings()
|
|
888
|
+
return [ bin(str(B[1])), bin(str(B[3])),
|
|
889
|
+
bin(str(B[2])), bin(str(B[0])) ]
|
|
890
|
+
|
|
891
|
+
def permutation8(self, B):
|
|
892
|
+
r"""
|
|
893
|
+
Return a permutation of an 8-bit string. This permutation is called
|
|
894
|
+
`P_8` and is specified as follows. Let
|
|
895
|
+
`(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)` be a vector of
|
|
896
|
+
10 bits where each `b_i \in \{ 0, 1 \}`. Then `P_8` picks out 8 of
|
|
897
|
+
those 10 bits and permutes those 8 bits:
|
|
898
|
+
|
|
899
|
+
.. MATH::
|
|
900
|
+
|
|
901
|
+
P_8(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)
|
|
902
|
+
=
|
|
903
|
+
(b_5, b_2, b_6, b_3, b_7, b_4, b_9, b_8)
|
|
904
|
+
|
|
905
|
+
INPUT:
|
|
906
|
+
|
|
907
|
+
- ``B`` -- a block of 10-bit string
|
|
908
|
+
|
|
909
|
+
OUTPUT: pick out 8 of the 10 bits of ``B`` and permute those 8 bits
|
|
910
|
+
|
|
911
|
+
EXAMPLES:
|
|
912
|
+
|
|
913
|
+
Permute a 10-bit string::
|
|
914
|
+
|
|
915
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
916
|
+
sage: sdes = SimplifiedDES()
|
|
917
|
+
sage: B = [1, 1, 0, 0, 1, 0, 0, 1, 0, 1]
|
|
918
|
+
sage: sdes.permutation8(B)
|
|
919
|
+
[0, 0, 0, 0, 1, 1, 1, 0]
|
|
920
|
+
sage: sdes.permutation8([0, 1, 1, 0, 1, 0, 0, 1, 0, 1])
|
|
921
|
+
[0, 1, 0, 0, 1, 1, 1, 0]
|
|
922
|
+
sage: sdes.permutation8([0, 0, 0, 0, 1, 1, 1, 0, 0, 0])
|
|
923
|
+
[1, 0, 1, 0, 0, 1, 0, 0]
|
|
924
|
+
|
|
925
|
+
We can also work with a string of bits::
|
|
926
|
+
|
|
927
|
+
sage: S = "1100100101"
|
|
928
|
+
sage: L = sdes.string_to_list(S)
|
|
929
|
+
sage: sdes.permutation8(L)
|
|
930
|
+
[0, 0, 0, 0, 1, 1, 1, 0]
|
|
931
|
+
sage: sdes.permutation8(sdes.string_to_list("0110100101"))
|
|
932
|
+
[0, 1, 0, 0, 1, 1, 1, 0]
|
|
933
|
+
|
|
934
|
+
TESTS:
|
|
935
|
+
|
|
936
|
+
The input block must be a list::
|
|
937
|
+
|
|
938
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
939
|
+
sage: sdes = SimplifiedDES()
|
|
940
|
+
sage: sdes.permutation8("B")
|
|
941
|
+
Traceback (most recent call last):
|
|
942
|
+
...
|
|
943
|
+
TypeError: input block must be a list of 10 bits
|
|
944
|
+
sage: sdes.permutation8(())
|
|
945
|
+
Traceback (most recent call last):
|
|
946
|
+
...
|
|
947
|
+
TypeError: input block must be a list of 10 bits
|
|
948
|
+
|
|
949
|
+
The input block must be a list of 10 bits::
|
|
950
|
+
|
|
951
|
+
sage: sdes.permutation8([])
|
|
952
|
+
Traceback (most recent call last):
|
|
953
|
+
...
|
|
954
|
+
ValueError: input block must be a list of 10 bits
|
|
955
|
+
sage: sdes.permutation8([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
|
|
956
|
+
Traceback (most recent call last):
|
|
957
|
+
...
|
|
958
|
+
ValueError: input block must be a list of 10 bits
|
|
959
|
+
|
|
960
|
+
The value of each element of the list must be either 0 or 1::
|
|
961
|
+
|
|
962
|
+
sage: sdes.permutation8([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
963
|
+
Traceback (most recent call last):
|
|
964
|
+
...
|
|
965
|
+
TypeError: Argument x (= 6) is not a valid string.
|
|
966
|
+
"""
|
|
967
|
+
# sanity check
|
|
968
|
+
if not isinstance(B, list):
|
|
969
|
+
raise TypeError("input block must be a list of 10 bits")
|
|
970
|
+
if len(B) != 10:
|
|
971
|
+
raise ValueError("input block must be a list of 10 bits")
|
|
972
|
+
|
|
973
|
+
# perform the permutation
|
|
974
|
+
bin = BinaryStrings()
|
|
975
|
+
return [ bin(str(B[5])), bin(str(B[2])),
|
|
976
|
+
bin(str(B[6])), bin(str(B[3])),
|
|
977
|
+
bin(str(B[7])), bin(str(B[4])),
|
|
978
|
+
bin(str(B[9])), bin(str(B[8])) ]
|
|
979
|
+
|
|
980
|
+
def permutation10(self, B):
|
|
981
|
+
r"""
|
|
982
|
+
Return a permutation of a 10-bit string. This permutation is called
|
|
983
|
+
`P_{10}` and is specified as follows. Let
|
|
984
|
+
`(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)` be a vector of
|
|
985
|
+
10 bits where each `b_i \in \{ 0, 1 \}`. Then `P_{10}` is given by
|
|
986
|
+
|
|
987
|
+
.. MATH::
|
|
988
|
+
|
|
989
|
+
P_{10}(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7, b_8, b_9)
|
|
990
|
+
=
|
|
991
|
+
(b_2, b_4, b_1, b_6, b_3, b_9, b_0, b_8, b_7, b_5)
|
|
992
|
+
|
|
993
|
+
INPUT:
|
|
994
|
+
|
|
995
|
+
- ``B`` -- a block of 10-bit string
|
|
996
|
+
|
|
997
|
+
OUTPUT: a permutation of ``B``
|
|
998
|
+
|
|
999
|
+
EXAMPLES:
|
|
1000
|
+
|
|
1001
|
+
Permute a 10-bit string::
|
|
1002
|
+
|
|
1003
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1004
|
+
sage: sdes = SimplifiedDES()
|
|
1005
|
+
sage: B = [1, 1, 0, 0, 1, 0, 0, 1, 0, 1]
|
|
1006
|
+
sage: sdes.permutation10(B)
|
|
1007
|
+
[0, 1, 1, 0, 0, 1, 1, 0, 1, 0]
|
|
1008
|
+
sage: sdes.permutation10([0, 1, 1, 0, 1, 0, 0, 1, 0, 1])
|
|
1009
|
+
[1, 1, 1, 0, 0, 1, 0, 0, 1, 0]
|
|
1010
|
+
sage: sdes.permutation10([1, 0, 1, 0, 0, 0, 0, 0, 1, 0])
|
|
1011
|
+
[1, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
|
1012
|
+
|
|
1013
|
+
Here we work with a string of bits::
|
|
1014
|
+
|
|
1015
|
+
sage: S = "1100100101"
|
|
1016
|
+
sage: L = sdes.string_to_list(S)
|
|
1017
|
+
sage: sdes.permutation10(L)
|
|
1018
|
+
[0, 1, 1, 0, 0, 1, 1, 0, 1, 0]
|
|
1019
|
+
sage: sdes.permutation10(sdes.string_to_list("0110100101"))
|
|
1020
|
+
[1, 1, 1, 0, 0, 1, 0, 0, 1, 0]
|
|
1021
|
+
|
|
1022
|
+
TESTS:
|
|
1023
|
+
|
|
1024
|
+
The input block must be a list::
|
|
1025
|
+
|
|
1026
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1027
|
+
sage: sdes = SimplifiedDES()
|
|
1028
|
+
sage: sdes.permutation10("B")
|
|
1029
|
+
Traceback (most recent call last):
|
|
1030
|
+
...
|
|
1031
|
+
TypeError: input block must be a list of 10 bits
|
|
1032
|
+
sage: sdes.permutation10(())
|
|
1033
|
+
Traceback (most recent call last):
|
|
1034
|
+
...
|
|
1035
|
+
TypeError: input block must be a list of 10 bits
|
|
1036
|
+
|
|
1037
|
+
The input block must be a list of 10 bits::
|
|
1038
|
+
|
|
1039
|
+
sage: sdes.permutation10([])
|
|
1040
|
+
Traceback (most recent call last):
|
|
1041
|
+
...
|
|
1042
|
+
ValueError: input block must be a list of 10 bits
|
|
1043
|
+
sage: sdes.permutation10([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
|
|
1044
|
+
Traceback (most recent call last):
|
|
1045
|
+
...
|
|
1046
|
+
ValueError: input block must be a list of 10 bits
|
|
1047
|
+
|
|
1048
|
+
The value of each element of the list must be either 0 or 1::
|
|
1049
|
+
|
|
1050
|
+
sage: sdes.permutation10([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
1051
|
+
Traceback (most recent call last):
|
|
1052
|
+
...
|
|
1053
|
+
TypeError: Argument x (= 3) is not a valid string.
|
|
1054
|
+
"""
|
|
1055
|
+
# sanity check
|
|
1056
|
+
if not isinstance(B, list):
|
|
1057
|
+
raise TypeError("input block must be a list of 10 bits")
|
|
1058
|
+
if len(B) != 10:
|
|
1059
|
+
raise ValueError("input block must be a list of 10 bits")
|
|
1060
|
+
|
|
1061
|
+
# perform the permutation
|
|
1062
|
+
bin = BinaryStrings()
|
|
1063
|
+
return [ bin(str(B[2])), bin(str(B[4])),
|
|
1064
|
+
bin(str(B[1])), bin(str(B[6])),
|
|
1065
|
+
bin(str(B[3])), bin(str(B[9])),
|
|
1066
|
+
bin(str(B[0])), bin(str(B[8])),
|
|
1067
|
+
bin(str(B[7])), bin(str(B[5])) ]
|
|
1068
|
+
|
|
1069
|
+
def permute_substitute(self, B, key):
|
|
1070
|
+
r"""
|
|
1071
|
+
Apply the function `\Pi_F` on the block ``B`` using subkey ``key``.
|
|
1072
|
+
Let `(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7)`
|
|
1073
|
+
be a vector of 8 bits where each `b_i \in \{ 0, 1 \}`, let `L` and
|
|
1074
|
+
`R` be the leftmost 4 bits and rightmost 4 bits of ``B``
|
|
1075
|
+
respectively, and let `F` be a function mapping 4-bit strings to
|
|
1076
|
+
4-bit strings. Then
|
|
1077
|
+
|
|
1078
|
+
.. MATH::
|
|
1079
|
+
|
|
1080
|
+
\Pi_F(L, R) = (L \oplus F(R, S), R)
|
|
1081
|
+
|
|
1082
|
+
where `S` is a subkey and `\oplus` denotes the bit-wise
|
|
1083
|
+
exclusive-OR function.
|
|
1084
|
+
|
|
1085
|
+
The function `F` can be described as follows. Its 4-bit input block
|
|
1086
|
+
`(n_0, n_1, n_2, n_3)` is first expanded into an 8-bit block
|
|
1087
|
+
to become `(n_3, n_0, n_1, n_2, n_1, n_2, n_3, n_0)`. This is
|
|
1088
|
+
usually represented as follows
|
|
1089
|
+
|
|
1090
|
+
.. MATH::
|
|
1091
|
+
|
|
1092
|
+
\begin{tabular}{c|cc|c}
|
|
1093
|
+
$n_3$ & $n_0$ & $n_1$ & $n_2$ \\
|
|
1094
|
+
$n_1$ & $n_2$ & $n_3$ & $n_0$
|
|
1095
|
+
\end{tabular}
|
|
1096
|
+
|
|
1097
|
+
Let `K = (k_0, k_1, k_2, k_3, k_4, k_5, k_6, k_7)` be an 8-bit
|
|
1098
|
+
subkey. Then `K` is added to the above expanded input block using
|
|
1099
|
+
exclusive-OR to produce
|
|
1100
|
+
|
|
1101
|
+
.. MATH::
|
|
1102
|
+
|
|
1103
|
+
\begin{tabular}{c|cc|c}
|
|
1104
|
+
$n_3 + k_0$ & $n_0 + k_1$ & $n_1 + k_2$ & $n_2 + k_3$ \\
|
|
1105
|
+
$n_1 + k_4$ & $n_2 + k_5$ & $n_3 + k_6$ & $n_0 + k_7$
|
|
1106
|
+
\end{tabular}
|
|
1107
|
+
=
|
|
1108
|
+
\begin{tabular}{c|cc|c}
|
|
1109
|
+
$p_{0,0}$ & $p_{0,1}$ & $p_{0,2}$ & $p_{0,3}$ \\
|
|
1110
|
+
$p_{1,0}$ & $p_{1,1}$ & $p_{1,2}$ & $p_{1,3}$
|
|
1111
|
+
\end{tabular}
|
|
1112
|
+
|
|
1113
|
+
Now read the first row as the 4-bit string
|
|
1114
|
+
`p_{0,0} p_{0,3} p_{0,1} p_{0,2}` and input this 4-bit string through
|
|
1115
|
+
S-box `S_0` to get a 2-bit output.
|
|
1116
|
+
|
|
1117
|
+
.. MATH::
|
|
1118
|
+
|
|
1119
|
+
S_0
|
|
1120
|
+
=
|
|
1121
|
+
\begin{tabular}{cc|cc} \hline
|
|
1122
|
+
Input & Output & Input & Output \\\hline
|
|
1123
|
+
0000 & 01 & 1000 & 00 \\
|
|
1124
|
+
0001 & 00 & 1001 & 10 \\
|
|
1125
|
+
0010 & 11 & 1010 & 01 \\
|
|
1126
|
+
0011 & 10 & 1011 & 11 \\
|
|
1127
|
+
0100 & 11 & 1100 & 11 \\
|
|
1128
|
+
0101 & 10 & 1101 & 01 \\
|
|
1129
|
+
0110 & 01 & 1110 & 11 \\
|
|
1130
|
+
0111 & 00 & 1111 & 10 \\\hline
|
|
1131
|
+
\end{tabular}
|
|
1132
|
+
|
|
1133
|
+
Next read the second row as the 4-bit string
|
|
1134
|
+
`p_{1,0} p_{1,3} p_{1,1} p_{1,2}` and input this 4-bit string through
|
|
1135
|
+
S-box `S_1` to get another 2-bit output.
|
|
1136
|
+
|
|
1137
|
+
.. MATH::
|
|
1138
|
+
|
|
1139
|
+
S_1
|
|
1140
|
+
=
|
|
1141
|
+
\begin{tabular}{cc|cc} \hline
|
|
1142
|
+
Input & Output & Input & Output \\\hline
|
|
1143
|
+
0000 & 00 & 1000 & 11 \\
|
|
1144
|
+
0001 & 01 & 1001 & 00 \\
|
|
1145
|
+
0010 & 10 & 1010 & 01 \\
|
|
1146
|
+
0011 & 11 & 1011 & 00 \\
|
|
1147
|
+
0100 & 10 & 1100 & 10 \\
|
|
1148
|
+
0101 & 00 & 1101 & 01 \\
|
|
1149
|
+
0110 & 01 & 1110 & 00 \\
|
|
1150
|
+
0111 & 11 & 1111 & 11 \\\hline
|
|
1151
|
+
\end{tabular}
|
|
1152
|
+
|
|
1153
|
+
Denote the 4 bits produced by `S_0` and `S_1` as `b_0 b_1 b_2 b_3`.
|
|
1154
|
+
This 4-bit string undergoes another permutation called `P_4` as
|
|
1155
|
+
follows:
|
|
1156
|
+
|
|
1157
|
+
.. MATH::
|
|
1158
|
+
|
|
1159
|
+
P_4(b_0, b_1, b_2, b_3) = (b_1, b_3, b_2, b_0)
|
|
1160
|
+
|
|
1161
|
+
The output of `P_4` is the output of the function `F`.
|
|
1162
|
+
|
|
1163
|
+
INPUT:
|
|
1164
|
+
|
|
1165
|
+
- ``B`` -- list of 8 bits
|
|
1166
|
+
|
|
1167
|
+
- ``key`` -- an 8-bit subkey
|
|
1168
|
+
|
|
1169
|
+
OUTPUT: the result of applying the function `\Pi_F` to ``B``
|
|
1170
|
+
|
|
1171
|
+
EXAMPLES:
|
|
1172
|
+
|
|
1173
|
+
Applying the function `\Pi_F` to an 8-bit block and an 8-bit subkey::
|
|
1174
|
+
|
|
1175
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1176
|
+
sage: sdes = SimplifiedDES()
|
|
1177
|
+
sage: B = [1, 0, 1, 1, 1, 1, 0, 1]
|
|
1178
|
+
sage: K = [1, 1, 0, 1, 0, 1, 0, 1]
|
|
1179
|
+
sage: sdes.permute_substitute(B, K)
|
|
1180
|
+
[1, 0, 1, 0, 1, 1, 0, 1]
|
|
1181
|
+
|
|
1182
|
+
We can also work with strings of bits::
|
|
1183
|
+
|
|
1184
|
+
sage: B = "10111101"
|
|
1185
|
+
sage: K = "11010101"
|
|
1186
|
+
sage: B = sdes.string_to_list(B); K = sdes.string_to_list(K)
|
|
1187
|
+
sage: sdes.permute_substitute(B, K)
|
|
1188
|
+
[1, 0, 1, 0, 1, 1, 0, 1]
|
|
1189
|
+
|
|
1190
|
+
TESTS:
|
|
1191
|
+
|
|
1192
|
+
The input ``B`` must be a block of 8 bits::
|
|
1193
|
+
|
|
1194
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1195
|
+
sage: sdes = SimplifiedDES()
|
|
1196
|
+
sage: sdes.permute_substitute("B", "K")
|
|
1197
|
+
Traceback (most recent call last):
|
|
1198
|
+
...
|
|
1199
|
+
TypeError: input B must be an 8-bit string
|
|
1200
|
+
sage: sdes.permute_substitute([], "K")
|
|
1201
|
+
Traceback (most recent call last):
|
|
1202
|
+
...
|
|
1203
|
+
ValueError: input B must be an 8-bit string
|
|
1204
|
+
|
|
1205
|
+
The input ``key`` must be an 8-bit subkey::
|
|
1206
|
+
|
|
1207
|
+
sage: sdes.permute_substitute([0, 1, 0, 0, 1, 1, 1, 0], "K")
|
|
1208
|
+
Traceback (most recent call last):
|
|
1209
|
+
...
|
|
1210
|
+
TypeError: input key must be an 8-bit subkey
|
|
1211
|
+
sage: sdes.permute_substitute([0, 1, 0, 0, 1, 1, 1, 0], [])
|
|
1212
|
+
Traceback (most recent call last):
|
|
1213
|
+
...
|
|
1214
|
+
ValueError: input key must be an 8-bit subkey
|
|
1215
|
+
|
|
1216
|
+
The value of each element of ``B`` or ``key`` must be either 0 or 1::
|
|
1217
|
+
|
|
1218
|
+
sage: B = [1, 2, 3, 4, 5, 6, 7, 8]
|
|
1219
|
+
sage: K = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
1220
|
+
sage: sdes.permute_substitute(B, K)
|
|
1221
|
+
Traceback (most recent call last):
|
|
1222
|
+
...
|
|
1223
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
1224
|
+
sage: B = [0, 1, 0, 0, 1, 1, 1, 0]
|
|
1225
|
+
sage: K = [1, 2, 3, 4, 5, 6, 7, 8]
|
|
1226
|
+
sage: sdes.permute_substitute(B, K)
|
|
1227
|
+
Traceback (most recent call last):
|
|
1228
|
+
...
|
|
1229
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
1230
|
+
"""
|
|
1231
|
+
# sanity check
|
|
1232
|
+
if not isinstance(B, list):
|
|
1233
|
+
raise TypeError("input B must be an 8-bit string")
|
|
1234
|
+
if len(B) != 8:
|
|
1235
|
+
raise ValueError("input B must be an 8-bit string")
|
|
1236
|
+
if not isinstance(key, list):
|
|
1237
|
+
raise TypeError("input key must be an 8-bit subkey")
|
|
1238
|
+
if len(key) != 8:
|
|
1239
|
+
raise ValueError("input key must be an 8-bit subkey")
|
|
1240
|
+
|
|
1241
|
+
from sage.rings.finite_rings.finite_field_constructor import FiniteField
|
|
1242
|
+
GF = FiniteField(2, "x")
|
|
1243
|
+
bin = BinaryStrings()
|
|
1244
|
+
bin_to_GF2 = {bin("0"): GF(0), bin("1"): GF(1)}
|
|
1245
|
+
|
|
1246
|
+
# the leftmost 4 bits of B
|
|
1247
|
+
L = [ bin_to_GF2[bin(str(B[i]))] for i in range(4) ]
|
|
1248
|
+
# the rightmost 4 bits of B
|
|
1249
|
+
R = [ bin_to_GF2[bin(str(B[i]))] for i in range(4, len(B)) ]
|
|
1250
|
+
# get the GF(2) representation of the subkey
|
|
1251
|
+
K = [ bin_to_GF2[bin(str(key[i]))] for i in range(len(key)) ]
|
|
1252
|
+
# expand the rightmost 4 bits into an 8-bit block
|
|
1253
|
+
RX = [ R[3], R[0], R[1], R[2], R[1], R[2], R[3], R[0] ]
|
|
1254
|
+
# add the subkey to the expanded 8-bit block using exclusive-OR
|
|
1255
|
+
P = [ RX[i] + K[i] for i in range(len(K)) ]
|
|
1256
|
+
# run each half of P separately through the S-boxes
|
|
1257
|
+
left = self._sbox0([ P[0], P[3], P[1], P[2] ])
|
|
1258
|
+
right = self._sbox1([ P[4], P[7], P[5], P[6] ])
|
|
1259
|
+
# First concatenate the left and right parts, then get the
|
|
1260
|
+
# output of the function F.
|
|
1261
|
+
F = self.permutation4(left + right)
|
|
1262
|
+
F = [ bin_to_GF2[F[i]] for i in range(len(F)) ]
|
|
1263
|
+
# Add L to F using exclusive-OR. Then concatenate the result with
|
|
1264
|
+
# the rightmost 4 bits of B. This is the output of the function Pi_F.
|
|
1265
|
+
L = [ L[i] + F[i] for i in range(len(F)) ]
|
|
1266
|
+
return L + R
|
|
1267
|
+
|
|
1268
|
+
def random_key(self):
|
|
1269
|
+
r"""
|
|
1270
|
+
Return a random 10-bit key.
|
|
1271
|
+
|
|
1272
|
+
EXAMPLES:
|
|
1273
|
+
|
|
1274
|
+
The size of each key is the same as the block size::
|
|
1275
|
+
|
|
1276
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1277
|
+
sage: sdes = SimplifiedDES()
|
|
1278
|
+
sage: key = sdes.random_key()
|
|
1279
|
+
sage: len(key) == sdes.block_length()
|
|
1280
|
+
True
|
|
1281
|
+
"""
|
|
1282
|
+
from sage.misc.prandom import randint
|
|
1283
|
+
bin = BinaryStrings()
|
|
1284
|
+
return [bin(str(randint(0, 1))) for i in range(self._key_size)]
|
|
1285
|
+
|
|
1286
|
+
def sbox(self):
|
|
1287
|
+
r"""
|
|
1288
|
+
Return the S-boxes of simplified DES.
|
|
1289
|
+
|
|
1290
|
+
EXAMPLES::
|
|
1291
|
+
|
|
1292
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1293
|
+
sage: sdes = SimplifiedDES()
|
|
1294
|
+
sage: sbox = sdes.sbox()
|
|
1295
|
+
sage: sbox[0]; sbox[1]
|
|
1296
|
+
(1, 0, 3, 2, 3, 2, 1, 0, 0, 2, 1, 3, 3, 1, 3, 2)
|
|
1297
|
+
(0, 1, 2, 3, 2, 0, 1, 3, 3, 0, 1, 0, 2, 1, 0, 3)
|
|
1298
|
+
"""
|
|
1299
|
+
return [self._sbox0, self._sbox1]
|
|
1300
|
+
|
|
1301
|
+
def string_to_list(self, S):
|
|
1302
|
+
r"""
|
|
1303
|
+
Return a list representation of the binary string ``S``.
|
|
1304
|
+
|
|
1305
|
+
INPUT:
|
|
1306
|
+
|
|
1307
|
+
- ``S`` -- string of bits
|
|
1308
|
+
|
|
1309
|
+
OUTPUT: list representation of the string ``S``
|
|
1310
|
+
|
|
1311
|
+
EXAMPLES:
|
|
1312
|
+
|
|
1313
|
+
A list representation of a string of bits::
|
|
1314
|
+
|
|
1315
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1316
|
+
sage: sdes = SimplifiedDES()
|
|
1317
|
+
sage: S = "0101010110"
|
|
1318
|
+
sage: sdes.string_to_list(S)
|
|
1319
|
+
[0, 1, 0, 1, 0, 1, 0, 1, 1, 0]
|
|
1320
|
+
|
|
1321
|
+
TESTS:
|
|
1322
|
+
|
|
1323
|
+
Input must be a non-empty string::
|
|
1324
|
+
|
|
1325
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1326
|
+
sage: sdes = SimplifiedDES()
|
|
1327
|
+
sage: sdes.string_to_list("")
|
|
1328
|
+
Traceback (most recent call last):
|
|
1329
|
+
...
|
|
1330
|
+
ValueError: input S must be a non-empty string of bits
|
|
1331
|
+
sage: sdes.string_to_list(1)
|
|
1332
|
+
Traceback (most recent call last):
|
|
1333
|
+
...
|
|
1334
|
+
TypeError: input S must be a non-empty string of bits
|
|
1335
|
+
|
|
1336
|
+
Input must be a non-empty string of bits::
|
|
1337
|
+
|
|
1338
|
+
sage: sdes.string_to_list("0123")
|
|
1339
|
+
Traceback (most recent call last):
|
|
1340
|
+
...
|
|
1341
|
+
TypeError: Argument x (= 2) is not a valid string.
|
|
1342
|
+
"""
|
|
1343
|
+
# sanity check
|
|
1344
|
+
if not isinstance(S, str):
|
|
1345
|
+
raise TypeError("input S must be a non-empty string of bits")
|
|
1346
|
+
if len(S) == 0:
|
|
1347
|
+
raise ValueError("input S must be a non-empty string of bits")
|
|
1348
|
+
|
|
1349
|
+
# perform the conversion from string to list
|
|
1350
|
+
bin = BinaryStrings()
|
|
1351
|
+
return [bin(s) for s in S]
|
|
1352
|
+
|
|
1353
|
+
def subkey(self, K, n=1):
|
|
1354
|
+
r"""
|
|
1355
|
+
Return the `n`-th subkey based on the key ``K``.
|
|
1356
|
+
|
|
1357
|
+
INPUT:
|
|
1358
|
+
|
|
1359
|
+
- ``K`` -- a 10-bit secret key of this Simplified DES
|
|
1360
|
+
|
|
1361
|
+
- ``n`` -- (default: 1) if ``n=1`` then return the first subkey based
|
|
1362
|
+
on ``K``; if ``n=2`` then return the second subkey. The valid
|
|
1363
|
+
values for ``n`` are 1 and 2, since only two subkeys are defined
|
|
1364
|
+
for each secret key in Schaefer's S-DES.
|
|
1365
|
+
|
|
1366
|
+
OUTPUT: the `n`-th subkey based on the secret key ``K``
|
|
1367
|
+
|
|
1368
|
+
EXAMPLES:
|
|
1369
|
+
|
|
1370
|
+
Obtain the first subkey from a secret key::
|
|
1371
|
+
|
|
1372
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1373
|
+
sage: sdes = SimplifiedDES()
|
|
1374
|
+
sage: key = [1, 0, 1, 0, 0, 0, 0, 0, 1, 0]
|
|
1375
|
+
sage: sdes.subkey(key, n=1)
|
|
1376
|
+
[1, 0, 1, 0, 0, 1, 0, 0]
|
|
1377
|
+
|
|
1378
|
+
Obtain the second subkey from a secret key::
|
|
1379
|
+
|
|
1380
|
+
sage: key = [1, 0, 1, 0, 0, 0, 0, 0, 1, 0]
|
|
1381
|
+
sage: sdes.subkey(key, n=2)
|
|
1382
|
+
[0, 1, 0, 0, 0, 0, 1, 1]
|
|
1383
|
+
|
|
1384
|
+
We can also work with strings of bits::
|
|
1385
|
+
|
|
1386
|
+
sage: K = "1010010010"
|
|
1387
|
+
sage: L = sdes.string_to_list(K)
|
|
1388
|
+
sage: sdes.subkey(L, n=1)
|
|
1389
|
+
[1, 0, 1, 0, 0, 1, 0, 1]
|
|
1390
|
+
sage: sdes.subkey(sdes.string_to_list("0010010011"), n=2)
|
|
1391
|
+
[0, 1, 1, 0, 1, 0, 1, 0]
|
|
1392
|
+
|
|
1393
|
+
TESTS:
|
|
1394
|
+
|
|
1395
|
+
Input ``K`` must be a 10-bit key::
|
|
1396
|
+
|
|
1397
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1398
|
+
sage: sdes = SimplifiedDES()
|
|
1399
|
+
sage: sdes.subkey("K")
|
|
1400
|
+
Traceback (most recent call last):
|
|
1401
|
+
...
|
|
1402
|
+
TypeError: input K must be a 10-bit key
|
|
1403
|
+
sage: sdes.subkey([])
|
|
1404
|
+
Traceback (most recent call last):
|
|
1405
|
+
...
|
|
1406
|
+
ValueError: input K must be a 10-bit key
|
|
1407
|
+
|
|
1408
|
+
There are only two subkeys::
|
|
1409
|
+
|
|
1410
|
+
sage: key = [1, 0, 1, 0, 0, 0, 0, 0, 1, 0]
|
|
1411
|
+
sage: sdes.subkey(key, n=0)
|
|
1412
|
+
Traceback (most recent call last):
|
|
1413
|
+
...
|
|
1414
|
+
ValueError: input n must be either 1 or 2
|
|
1415
|
+
sage: sdes.subkey(key, n=3)
|
|
1416
|
+
Traceback (most recent call last):
|
|
1417
|
+
...
|
|
1418
|
+
ValueError: input n must be either 1 or 2
|
|
1419
|
+
"""
|
|
1420
|
+
# sanity check
|
|
1421
|
+
if not isinstance(K, list):
|
|
1422
|
+
raise TypeError("input K must be a 10-bit key")
|
|
1423
|
+
if len(K) != self._key_size:
|
|
1424
|
+
raise ValueError("input K must be a 10-bit key")
|
|
1425
|
+
|
|
1426
|
+
# get the first subkey
|
|
1427
|
+
if n == 1:
|
|
1428
|
+
key1 = self.permutation10(K)
|
|
1429
|
+
key1 = self.left_shift(key1, n=1)
|
|
1430
|
+
return self.permutation8(key1)
|
|
1431
|
+
# get the second subkey
|
|
1432
|
+
elif n == 2:
|
|
1433
|
+
key2 = self.permutation10(K)
|
|
1434
|
+
key2 = self.left_shift(key2, n=1)
|
|
1435
|
+
key2 = self.left_shift(key2, n=2)
|
|
1436
|
+
return self.permutation8(key2)
|
|
1437
|
+
# an invalid subkey number
|
|
1438
|
+
else:
|
|
1439
|
+
raise ValueError("input n must be either 1 or 2")
|
|
1440
|
+
|
|
1441
|
+
def switch(self, B):
|
|
1442
|
+
r"""
|
|
1443
|
+
Interchange the first 4 bits with the last 4 bits in the list ``B``
|
|
1444
|
+
of 8 bits. Let `(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7)`
|
|
1445
|
+
be a vector of 8 bits, where each `b_i \in \{ 0, 1 \}`. Then the
|
|
1446
|
+
switch function `\sigma` is given by
|
|
1447
|
+
|
|
1448
|
+
.. MATH::
|
|
1449
|
+
|
|
1450
|
+
\sigma(b_0, b_1, b_2, b_3, b_4, b_5, b_6, b_7)
|
|
1451
|
+
= (b_4, b_5, b_6, b_7, b_0, b_1, b_2, b_3)
|
|
1452
|
+
|
|
1453
|
+
INPUT:
|
|
1454
|
+
|
|
1455
|
+
- ``B`` -- list; a block of 8 bits
|
|
1456
|
+
|
|
1457
|
+
OUTPUT:
|
|
1458
|
+
|
|
1459
|
+
A block of the same dimension, but in which the first 4 bits from
|
|
1460
|
+
``B`` has been switched for the last 4 bits in ``B``.
|
|
1461
|
+
|
|
1462
|
+
EXAMPLES:
|
|
1463
|
+
|
|
1464
|
+
Interchange the first 4 bits with the last 4 bits::
|
|
1465
|
+
|
|
1466
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1467
|
+
sage: sdes = SimplifiedDES()
|
|
1468
|
+
sage: B = [1, 1, 1, 0, 1, 0, 0, 0]
|
|
1469
|
+
sage: sdes.switch(B)
|
|
1470
|
+
[1, 0, 0, 0, 1, 1, 1, 0]
|
|
1471
|
+
sage: sdes.switch([1, 1, 1, 1, 0, 0, 0, 0])
|
|
1472
|
+
[0, 0, 0, 0, 1, 1, 1, 1]
|
|
1473
|
+
|
|
1474
|
+
We can also work with a string of bits::
|
|
1475
|
+
|
|
1476
|
+
sage: S = "11101000"
|
|
1477
|
+
sage: L = sdes.string_to_list(S)
|
|
1478
|
+
sage: sdes.switch(L)
|
|
1479
|
+
[1, 0, 0, 0, 1, 1, 1, 0]
|
|
1480
|
+
sage: sdes.switch(sdes.string_to_list("11110000"))
|
|
1481
|
+
[0, 0, 0, 0, 1, 1, 1, 1]
|
|
1482
|
+
|
|
1483
|
+
TESTS:
|
|
1484
|
+
|
|
1485
|
+
The input block must be a list::
|
|
1486
|
+
|
|
1487
|
+
sage: from sage.crypto.block_cipher.sdes import SimplifiedDES
|
|
1488
|
+
sage: sdes = SimplifiedDES()
|
|
1489
|
+
sage: sdes.switch("B")
|
|
1490
|
+
Traceback (most recent call last):
|
|
1491
|
+
...
|
|
1492
|
+
TypeError: input block must be a list of 8 bits
|
|
1493
|
+
sage: sdes.switch(())
|
|
1494
|
+
Traceback (most recent call last):
|
|
1495
|
+
...
|
|
1496
|
+
TypeError: input block must be a list of 8 bits
|
|
1497
|
+
|
|
1498
|
+
The input block must be a list of 8 bits::
|
|
1499
|
+
|
|
1500
|
+
sage: sdes.switch([])
|
|
1501
|
+
Traceback (most recent call last):
|
|
1502
|
+
...
|
|
1503
|
+
ValueError: input block must be a list of 8 bits
|
|
1504
|
+
sage: sdes.switch([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
|
1505
|
+
Traceback (most recent call last):
|
|
1506
|
+
...
|
|
1507
|
+
ValueError: input block must be a list of 8 bits
|
|
1508
|
+
|
|
1509
|
+
The value of each element of the list must be either 0 or 1::
|
|
1510
|
+
|
|
1511
|
+
sage: sdes.switch([1, 2, 3, 4, 5, 6, 7, 8])
|
|
1512
|
+
Traceback (most recent call last):
|
|
1513
|
+
...
|
|
1514
|
+
TypeError: Argument x (= 5) is not a valid string.
|
|
1515
|
+
"""
|
|
1516
|
+
# sanity check
|
|
1517
|
+
if not isinstance(B, list):
|
|
1518
|
+
raise TypeError("input block must be a list of 8 bits")
|
|
1519
|
+
if len(B) != 8:
|
|
1520
|
+
raise ValueError("input block must be a list of 8 bits")
|
|
1521
|
+
|
|
1522
|
+
# perform the switch
|
|
1523
|
+
bin = BinaryStrings()
|
|
1524
|
+
return [ bin(str(B[4])), bin(str(B[5])),
|
|
1525
|
+
bin(str(B[6])), bin(str(B[7])),
|
|
1526
|
+
bin(str(B[0])), bin(str(B[1])),
|
|
1527
|
+
bin(str(B[2])), bin(str(B[3])) ]
|