passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.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.

Files changed (808) hide show
  1. passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31rc3.dist-info/RECORD +808 -0
  3. passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_modules.libs/libgcc_s-0cd532bd.so.1 +0 -0
  6. passagemath_modules.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  7. passagemath_modules.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  8. passagemath_modules.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  9. passagemath_modules.libs/libmpc-d8ebe4b5.so.3.3.1 +0 -0
  10. passagemath_modules.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  11. passagemath_modules.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  12. passagemath_modules.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  13. sage/algebras/all__sagemath_modules.py +20 -0
  14. sage/algebras/catalog.py +148 -0
  15. sage/algebras/clifford_algebra.py +3107 -0
  16. sage/algebras/clifford_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  17. sage/algebras/clifford_algebra_element.pxd +16 -0
  18. sage/algebras/clifford_algebra_element.pyx +997 -0
  19. sage/algebras/commutative_dga.py +4252 -0
  20. sage/algebras/exterior_algebra_groebner.cpython-314-x86_64-linux-musl.so +0 -0
  21. sage/algebras/exterior_algebra_groebner.pxd +55 -0
  22. sage/algebras/exterior_algebra_groebner.pyx +727 -0
  23. sage/algebras/finite_dimensional_algebras/all.py +2 -0
  24. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
  25. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  26. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
  27. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
  28. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
  29. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
  30. sage/algebras/finite_gca.py +528 -0
  31. sage/algebras/group_algebra.py +232 -0
  32. sage/algebras/lie_algebras/abelian.py +197 -0
  33. sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
  34. sage/algebras/lie_algebras/all.py +25 -0
  35. sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
  36. sage/algebras/lie_algebras/bch.py +177 -0
  37. sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
  38. sage/algebras/lie_algebras/bgg_resolution.py +232 -0
  39. sage/algebras/lie_algebras/center_uea.py +767 -0
  40. sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
  41. sage/algebras/lie_algebras/examples.py +683 -0
  42. sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
  43. sage/algebras/lie_algebras/heisenberg.py +820 -0
  44. sage/algebras/lie_algebras/lie_algebra.py +1562 -0
  45. sage/algebras/lie_algebras/lie_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  46. sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
  47. sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
  48. sage/algebras/lie_algebras/morphism.py +661 -0
  49. sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
  50. sage/algebras/lie_algebras/onsager.py +1324 -0
  51. sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
  52. sage/algebras/lie_algebras/quotient.py +462 -0
  53. sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
  54. sage/algebras/lie_algebras/representation.py +1040 -0
  55. sage/algebras/lie_algebras/structure_coefficients.py +459 -0
  56. sage/algebras/lie_algebras/subalgebra.py +967 -0
  57. sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
  58. sage/algebras/lie_algebras/verma_module.py +1630 -0
  59. sage/algebras/lie_algebras/virasoro.py +1186 -0
  60. sage/algebras/octonion_algebra.cpython-314-x86_64-linux-musl.so +0 -0
  61. sage/algebras/octonion_algebra.pxd +20 -0
  62. sage/algebras/octonion_algebra.pyx +987 -0
  63. sage/algebras/orlik_solomon.py +907 -0
  64. sage/algebras/orlik_terao.py +779 -0
  65. sage/algebras/steenrod/all.py +7 -0
  66. sage/algebras/steenrod/steenrod_algebra.py +4258 -0
  67. sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
  68. sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
  69. sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
  70. sage/algebras/weyl_algebra.py +1126 -0
  71. sage/all__sagemath_modules.py +62 -0
  72. sage/calculus/all__sagemath_modules.py +19 -0
  73. sage/calculus/expr.py +205 -0
  74. sage/calculus/integration.cpython-314-x86_64-linux-musl.so +0 -0
  75. sage/calculus/integration.pyx +698 -0
  76. sage/calculus/interpolation.cpython-314-x86_64-linux-musl.so +0 -0
  77. sage/calculus/interpolation.pxd +13 -0
  78. sage/calculus/interpolation.pyx +387 -0
  79. sage/calculus/interpolators.cpython-314-x86_64-linux-musl.so +0 -0
  80. sage/calculus/interpolators.pyx +326 -0
  81. sage/calculus/ode.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/calculus/ode.pxd +5 -0
  83. sage/calculus/ode.pyx +610 -0
  84. sage/calculus/riemann.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/calculus/riemann.pyx +1521 -0
  86. sage/calculus/test_sympy.py +201 -0
  87. sage/calculus/transforms/all.py +7 -0
  88. sage/calculus/transforms/dft.py +844 -0
  89. sage/calculus/transforms/dwt.cpython-314-x86_64-linux-musl.so +0 -0
  90. sage/calculus/transforms/dwt.pxd +7 -0
  91. sage/calculus/transforms/dwt.pyx +160 -0
  92. sage/calculus/transforms/fft.cpython-314-x86_64-linux-musl.so +0 -0
  93. sage/calculus/transforms/fft.pxd +12 -0
  94. sage/calculus/transforms/fft.pyx +487 -0
  95. sage/calculus/wester.py +662 -0
  96. sage/coding/abstract_code.py +1108 -0
  97. sage/coding/ag_code.py +868 -0
  98. sage/coding/ag_code_decoders.cpython-314-x86_64-linux-musl.so +0 -0
  99. sage/coding/ag_code_decoders.pyx +2639 -0
  100. sage/coding/all.py +15 -0
  101. sage/coding/bch_code.py +494 -0
  102. sage/coding/binary_code.cpython-314-x86_64-linux-musl.so +0 -0
  103. sage/coding/binary_code.pxd +124 -0
  104. sage/coding/binary_code.pyx +4139 -0
  105. sage/coding/bounds_catalog.py +43 -0
  106. sage/coding/channel.py +819 -0
  107. sage/coding/channels_catalog.py +29 -0
  108. sage/coding/code_bounds.py +755 -0
  109. sage/coding/code_constructions.py +804 -0
  110. sage/coding/codes_catalog.py +111 -0
  111. sage/coding/cyclic_code.py +1329 -0
  112. sage/coding/databases.py +316 -0
  113. sage/coding/decoder.py +373 -0
  114. sage/coding/decoders_catalog.py +88 -0
  115. sage/coding/delsarte_bounds.py +709 -0
  116. sage/coding/encoder.py +390 -0
  117. sage/coding/encoders_catalog.py +64 -0
  118. sage/coding/extended_code.py +468 -0
  119. sage/coding/gabidulin_code.py +1058 -0
  120. sage/coding/golay_code.py +404 -0
  121. sage/coding/goppa_code.py +441 -0
  122. sage/coding/grs_code.py +2371 -0
  123. sage/coding/guava.py +107 -0
  124. sage/coding/guruswami_sudan/all.py +1 -0
  125. sage/coding/guruswami_sudan/gs_decoder.py +897 -0
  126. sage/coding/guruswami_sudan/interpolation.py +409 -0
  127. sage/coding/guruswami_sudan/utils.py +176 -0
  128. sage/coding/hamming_code.py +176 -0
  129. sage/coding/information_set_decoder.py +1032 -0
  130. sage/coding/kasami_codes.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/coding/kasami_codes.pyx +351 -0
  132. sage/coding/linear_code.py +3067 -0
  133. sage/coding/linear_code_no_metric.py +1354 -0
  134. sage/coding/linear_rank_metric.py +961 -0
  135. sage/coding/parity_check_code.py +353 -0
  136. sage/coding/punctured_code.py +719 -0
  137. sage/coding/reed_muller_code.py +999 -0
  138. sage/coding/self_dual_codes.py +942 -0
  139. sage/coding/source_coding/all.py +2 -0
  140. sage/coding/source_coding/huffman.py +553 -0
  141. sage/coding/subfield_subcode.py +423 -0
  142. sage/coding/two_weight_db.py +399 -0
  143. sage/combinat/all__sagemath_modules.py +7 -0
  144. sage/combinat/cartesian_product.py +347 -0
  145. sage/combinat/family.py +11 -0
  146. sage/combinat/free_module.py +1977 -0
  147. sage/combinat/root_system/all.py +147 -0
  148. sage/combinat/root_system/ambient_space.py +527 -0
  149. sage/combinat/root_system/associahedron.py +471 -0
  150. sage/combinat/root_system/braid_move_calculator.py +143 -0
  151. sage/combinat/root_system/braid_orbit.cpython-314-x86_64-linux-musl.so +0 -0
  152. sage/combinat/root_system/braid_orbit.pyx +144 -0
  153. sage/combinat/root_system/branching_rules.py +2301 -0
  154. sage/combinat/root_system/cartan_matrix.py +1245 -0
  155. sage/combinat/root_system/cartan_type.py +3069 -0
  156. sage/combinat/root_system/coxeter_group.py +162 -0
  157. sage/combinat/root_system/coxeter_matrix.py +1261 -0
  158. sage/combinat/root_system/coxeter_type.py +681 -0
  159. sage/combinat/root_system/dynkin_diagram.py +900 -0
  160. sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
  161. sage/combinat/root_system/fundamental_group.py +795 -0
  162. sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
  163. sage/combinat/root_system/integrable_representations.py +1227 -0
  164. sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
  165. sage/combinat/root_system/pieri_factors.py +1147 -0
  166. sage/combinat/root_system/plot.py +1615 -0
  167. sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
  168. sage/combinat/root_system/root_lattice_realizations.py +4628 -0
  169. sage/combinat/root_system/root_space.py +487 -0
  170. sage/combinat/root_system/root_system.py +882 -0
  171. sage/combinat/root_system/type_A.py +348 -0
  172. sage/combinat/root_system/type_A_affine.py +227 -0
  173. sage/combinat/root_system/type_A_infinity.py +241 -0
  174. sage/combinat/root_system/type_B.py +347 -0
  175. sage/combinat/root_system/type_BC_affine.py +287 -0
  176. sage/combinat/root_system/type_B_affine.py +216 -0
  177. sage/combinat/root_system/type_C.py +317 -0
  178. sage/combinat/root_system/type_C_affine.py +188 -0
  179. sage/combinat/root_system/type_D.py +357 -0
  180. sage/combinat/root_system/type_D_affine.py +208 -0
  181. sage/combinat/root_system/type_E.py +641 -0
  182. sage/combinat/root_system/type_E_affine.py +231 -0
  183. sage/combinat/root_system/type_F.py +387 -0
  184. sage/combinat/root_system/type_F_affine.py +137 -0
  185. sage/combinat/root_system/type_G.py +293 -0
  186. sage/combinat/root_system/type_G_affine.py +132 -0
  187. sage/combinat/root_system/type_H.py +105 -0
  188. sage/combinat/root_system/type_I.py +110 -0
  189. sage/combinat/root_system/type_Q.py +150 -0
  190. sage/combinat/root_system/type_affine.py +509 -0
  191. sage/combinat/root_system/type_dual.py +704 -0
  192. sage/combinat/root_system/type_folded.py +301 -0
  193. sage/combinat/root_system/type_marked.py +748 -0
  194. sage/combinat/root_system/type_reducible.py +601 -0
  195. sage/combinat/root_system/type_relabel.py +730 -0
  196. sage/combinat/root_system/type_super_A.py +837 -0
  197. sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
  198. sage/combinat/root_system/weight_space.py +639 -0
  199. sage/combinat/root_system/weyl_characters.py +2238 -0
  200. sage/crypto/__init__.py +4 -0
  201. sage/crypto/all.py +28 -0
  202. sage/crypto/block_cipher/all.py +7 -0
  203. sage/crypto/block_cipher/des.py +1065 -0
  204. sage/crypto/block_cipher/miniaes.py +2171 -0
  205. sage/crypto/block_cipher/present.py +909 -0
  206. sage/crypto/block_cipher/sdes.py +1527 -0
  207. sage/crypto/boolean_function.cpython-314-x86_64-linux-musl.so +0 -0
  208. sage/crypto/boolean_function.pxd +10 -0
  209. sage/crypto/boolean_function.pyx +1487 -0
  210. sage/crypto/cipher.py +78 -0
  211. sage/crypto/classical.py +3668 -0
  212. sage/crypto/classical_cipher.py +569 -0
  213. sage/crypto/cryptosystem.py +387 -0
  214. sage/crypto/key_exchange/all.py +7 -0
  215. sage/crypto/key_exchange/catalog.py +24 -0
  216. sage/crypto/key_exchange/diffie_hellman.py +323 -0
  217. sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
  218. sage/crypto/lattice.py +312 -0
  219. sage/crypto/lfsr.py +295 -0
  220. sage/crypto/lwe.py +840 -0
  221. sage/crypto/mq/__init__.py +4 -0
  222. sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
  223. sage/crypto/mq/rijndael_gf.py +2345 -0
  224. sage/crypto/mq/sbox.py +7 -0
  225. sage/crypto/mq/sr.py +3344 -0
  226. sage/crypto/public_key/all.py +5 -0
  227. sage/crypto/public_key/blum_goldwasser.py +776 -0
  228. sage/crypto/sbox.cpython-314-x86_64-linux-musl.so +0 -0
  229. sage/crypto/sbox.pyx +2090 -0
  230. sage/crypto/sboxes.py +2090 -0
  231. sage/crypto/stream.py +390 -0
  232. sage/crypto/stream_cipher.py +297 -0
  233. sage/crypto/util.py +519 -0
  234. sage/ext/all__sagemath_modules.py +1 -0
  235. sage/ext/interpreters/__init__.py +1 -0
  236. sage/ext/interpreters/all__sagemath_modules.py +2 -0
  237. sage/ext/interpreters/wrapper_cc.cpython-314-x86_64-linux-musl.so +0 -0
  238. sage/ext/interpreters/wrapper_cc.pxd +30 -0
  239. sage/ext/interpreters/wrapper_cc.pyx +252 -0
  240. sage/ext/interpreters/wrapper_cdf.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/ext/interpreters/wrapper_cdf.pxd +26 -0
  242. sage/ext/interpreters/wrapper_cdf.pyx +245 -0
  243. sage/ext/interpreters/wrapper_rdf.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/ext/interpreters/wrapper_rdf.pxd +23 -0
  245. sage/ext/interpreters/wrapper_rdf.pyx +221 -0
  246. sage/ext/interpreters/wrapper_rr.cpython-314-x86_64-linux-musl.so +0 -0
  247. sage/ext/interpreters/wrapper_rr.pxd +28 -0
  248. sage/ext/interpreters/wrapper_rr.pyx +335 -0
  249. sage/geometry/all__sagemath_modules.py +5 -0
  250. sage/geometry/toric_lattice.py +1745 -0
  251. sage/geometry/toric_lattice_element.cpython-314-x86_64-linux-musl.so +0 -0
  252. sage/geometry/toric_lattice_element.pyx +432 -0
  253. sage/groups/abelian_gps/abelian_group.py +1925 -0
  254. sage/groups/abelian_gps/abelian_group_element.py +164 -0
  255. sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
  256. sage/groups/abelian_gps/dual_abelian_group.py +421 -0
  257. sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
  258. sage/groups/abelian_gps/element_base.py +341 -0
  259. sage/groups/abelian_gps/values.py +488 -0
  260. sage/groups/additive_abelian/additive_abelian_group.py +476 -0
  261. sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
  262. sage/groups/additive_abelian/all.py +4 -0
  263. sage/groups/additive_abelian/qmodnz.py +231 -0
  264. sage/groups/additive_abelian/qmodnz_element.py +349 -0
  265. sage/groups/affine_gps/affine_group.py +535 -0
  266. sage/groups/affine_gps/all.py +1 -0
  267. sage/groups/affine_gps/catalog.py +17 -0
  268. sage/groups/affine_gps/euclidean_group.py +246 -0
  269. sage/groups/affine_gps/group_element.py +562 -0
  270. sage/groups/all__sagemath_modules.py +12 -0
  271. sage/groups/galois_group.py +479 -0
  272. sage/groups/matrix_gps/all.py +4 -0
  273. sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
  274. sage/groups/matrix_gps/catalog.py +26 -0
  275. sage/groups/matrix_gps/coxeter_group.py +927 -0
  276. sage/groups/matrix_gps/finitely_generated.py +487 -0
  277. sage/groups/matrix_gps/group_element.cpython-314-x86_64-linux-musl.so +0 -0
  278. sage/groups/matrix_gps/group_element.pxd +11 -0
  279. sage/groups/matrix_gps/group_element.pyx +431 -0
  280. sage/groups/matrix_gps/linear.py +440 -0
  281. sage/groups/matrix_gps/matrix_group.py +617 -0
  282. sage/groups/matrix_gps/named_group.py +296 -0
  283. sage/groups/matrix_gps/orthogonal.py +544 -0
  284. sage/groups/matrix_gps/symplectic.py +251 -0
  285. sage/groups/matrix_gps/unitary.py +436 -0
  286. sage/groups/misc_gps/all__sagemath_modules.py +1 -0
  287. sage/groups/misc_gps/argument_groups.py +1905 -0
  288. sage/groups/misc_gps/imaginary_groups.py +479 -0
  289. sage/groups/perm_gps/all__sagemath_modules.py +1 -0
  290. sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
  291. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-x86_64-linux-musl.so +0 -0
  292. sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
  293. sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
  294. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-x86_64-linux-musl.so +0 -0
  295. sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
  296. sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
  297. sage/homology/algebraic_topological_model.py +595 -0
  298. sage/homology/all.py +2 -0
  299. sage/homology/all__sagemath_modules.py +8 -0
  300. sage/homology/chain_complex.py +2148 -0
  301. sage/homology/chain_complex_homspace.py +165 -0
  302. sage/homology/chain_complex_morphism.py +629 -0
  303. sage/homology/chain_homotopy.py +604 -0
  304. sage/homology/chains.py +653 -0
  305. sage/homology/free_resolution.py +923 -0
  306. sage/homology/graded_resolution.py +567 -0
  307. sage/homology/hochschild_complex.py +756 -0
  308. sage/homology/homology_group.py +188 -0
  309. sage/homology/homology_morphism.py +422 -0
  310. sage/homology/homology_vector_space_with_basis.py +1454 -0
  311. sage/homology/koszul_complex.py +169 -0
  312. sage/homology/matrix_utils.py +205 -0
  313. sage/libs/all__sagemath_modules.py +1 -0
  314. sage/libs/gsl/__init__.py +1 -0
  315. sage/libs/gsl/airy.pxd +56 -0
  316. sage/libs/gsl/all.pxd +66 -0
  317. sage/libs/gsl/array.cpython-314-x86_64-linux-musl.so +0 -0
  318. sage/libs/gsl/array.pxd +5 -0
  319. sage/libs/gsl/array.pyx +102 -0
  320. sage/libs/gsl/bessel.pxd +208 -0
  321. sage/libs/gsl/blas.pxd +116 -0
  322. sage/libs/gsl/blas_types.pxd +34 -0
  323. sage/libs/gsl/block.pxd +52 -0
  324. sage/libs/gsl/chebyshev.pxd +37 -0
  325. sage/libs/gsl/clausen.pxd +12 -0
  326. sage/libs/gsl/combination.pxd +47 -0
  327. sage/libs/gsl/complex.pxd +151 -0
  328. sage/libs/gsl/coulomb.pxd +30 -0
  329. sage/libs/gsl/coupling.pxd +21 -0
  330. sage/libs/gsl/dawson.pxd +12 -0
  331. sage/libs/gsl/debye.pxd +24 -0
  332. sage/libs/gsl/dilog.pxd +14 -0
  333. sage/libs/gsl/eigen.pxd +46 -0
  334. sage/libs/gsl/elementary.pxd +12 -0
  335. sage/libs/gsl/ellint.pxd +48 -0
  336. sage/libs/gsl/elljac.pxd +8 -0
  337. sage/libs/gsl/erf.pxd +32 -0
  338. sage/libs/gsl/errno.pxd +26 -0
  339. sage/libs/gsl/exp.pxd +44 -0
  340. sage/libs/gsl/expint.pxd +44 -0
  341. sage/libs/gsl/fermi_dirac.pxd +44 -0
  342. sage/libs/gsl/fft.pxd +121 -0
  343. sage/libs/gsl/fit.pxd +50 -0
  344. sage/libs/gsl/gamma.pxd +94 -0
  345. sage/libs/gsl/gegenbauer.pxd +26 -0
  346. sage/libs/gsl/histogram.pxd +176 -0
  347. sage/libs/gsl/hyperg.pxd +52 -0
  348. sage/libs/gsl/integration.pxd +69 -0
  349. sage/libs/gsl/interp.pxd +109 -0
  350. sage/libs/gsl/laguerre.pxd +24 -0
  351. sage/libs/gsl/lambert.pxd +16 -0
  352. sage/libs/gsl/legendre.pxd +90 -0
  353. sage/libs/gsl/linalg.pxd +185 -0
  354. sage/libs/gsl/log.pxd +26 -0
  355. sage/libs/gsl/math.pxd +43 -0
  356. sage/libs/gsl/matrix.pxd +143 -0
  357. sage/libs/gsl/matrix_complex.pxd +130 -0
  358. sage/libs/gsl/min.pxd +67 -0
  359. sage/libs/gsl/monte.pxd +56 -0
  360. sage/libs/gsl/ntuple.pxd +32 -0
  361. sage/libs/gsl/odeiv.pxd +70 -0
  362. sage/libs/gsl/permutation.pxd +78 -0
  363. sage/libs/gsl/poly.pxd +40 -0
  364. sage/libs/gsl/pow_int.pxd +12 -0
  365. sage/libs/gsl/psi.pxd +28 -0
  366. sage/libs/gsl/qrng.pxd +29 -0
  367. sage/libs/gsl/random.pxd +257 -0
  368. sage/libs/gsl/rng.pxd +100 -0
  369. sage/libs/gsl/roots.pxd +72 -0
  370. sage/libs/gsl/sort.pxd +36 -0
  371. sage/libs/gsl/statistics.pxd +59 -0
  372. sage/libs/gsl/sum.pxd +55 -0
  373. sage/libs/gsl/synchrotron.pxd +16 -0
  374. sage/libs/gsl/transport.pxd +24 -0
  375. sage/libs/gsl/trig.pxd +58 -0
  376. sage/libs/gsl/types.pxd +137 -0
  377. sage/libs/gsl/vector.pxd +101 -0
  378. sage/libs/gsl/vector_complex.pxd +83 -0
  379. sage/libs/gsl/wavelet.pxd +49 -0
  380. sage/libs/gsl/zeta.pxd +28 -0
  381. sage/libs/mpc/__init__.pxd +114 -0
  382. sage/libs/mpc/types.pxd +28 -0
  383. sage/libs/mpfr/__init__.pxd +299 -0
  384. sage/libs/mpfr/types.pxd +26 -0
  385. sage/libs/mpmath/__init__.py +1 -0
  386. sage/libs/mpmath/all.py +27 -0
  387. sage/libs/mpmath/all__sagemath_modules.py +1 -0
  388. sage/libs/mpmath/utils.cpython-314-x86_64-linux-musl.so +0 -0
  389. sage/libs/mpmath/utils.pxd +4 -0
  390. sage/libs/mpmath/utils.pyx +319 -0
  391. sage/matrix/action.cpython-314-x86_64-linux-musl.so +0 -0
  392. sage/matrix/action.pxd +26 -0
  393. sage/matrix/action.pyx +596 -0
  394. sage/matrix/all.py +9 -0
  395. sage/matrix/args.cpython-314-x86_64-linux-musl.so +0 -0
  396. sage/matrix/args.pxd +144 -0
  397. sage/matrix/args.pyx +1668 -0
  398. sage/matrix/benchmark.py +1258 -0
  399. sage/matrix/berlekamp_massey.py +95 -0
  400. sage/matrix/compute_J_ideal.py +926 -0
  401. sage/matrix/constructor.cpython-314-x86_64-linux-musl.so +0 -0
  402. sage/matrix/constructor.pyx +750 -0
  403. sage/matrix/docs.py +430 -0
  404. sage/matrix/echelon_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  405. sage/matrix/echelon_matrix.pyx +155 -0
  406. sage/matrix/matrix.pxd +2 -0
  407. sage/matrix/matrix0.cpython-314-x86_64-linux-musl.so +0 -0
  408. sage/matrix/matrix0.pxd +68 -0
  409. sage/matrix/matrix0.pyx +6324 -0
  410. sage/matrix/matrix1.cpython-314-x86_64-linux-musl.so +0 -0
  411. sage/matrix/matrix1.pxd +8 -0
  412. sage/matrix/matrix1.pyx +2851 -0
  413. sage/matrix/matrix2.cpython-314-x86_64-linux-musl.so +0 -0
  414. sage/matrix/matrix2.pxd +25 -0
  415. sage/matrix/matrix2.pyx +20181 -0
  416. sage/matrix/matrix_cdv.cpython-314-x86_64-linux-musl.so +0 -0
  417. sage/matrix/matrix_cdv.pxd +4 -0
  418. sage/matrix/matrix_cdv.pyx +93 -0
  419. sage/matrix/matrix_complex_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  420. sage/matrix/matrix_complex_double_dense.pxd +5 -0
  421. sage/matrix/matrix_complex_double_dense.pyx +98 -0
  422. sage/matrix/matrix_dense.cpython-314-x86_64-linux-musl.so +0 -0
  423. sage/matrix/matrix_dense.pxd +5 -0
  424. sage/matrix/matrix_dense.pyx +343 -0
  425. sage/matrix/matrix_domain_dense.pxd +5 -0
  426. sage/matrix/matrix_domain_sparse.pxd +5 -0
  427. sage/matrix/matrix_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  428. sage/matrix/matrix_double_dense.pxd +7 -0
  429. sage/matrix/matrix_double_dense.pyx +3906 -0
  430. sage/matrix/matrix_double_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  431. sage/matrix/matrix_double_sparse.pxd +6 -0
  432. sage/matrix/matrix_double_sparse.pyx +248 -0
  433. sage/matrix/matrix_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
  434. sage/matrix/matrix_generic_dense.pxd +7 -0
  435. sage/matrix/matrix_generic_dense.pyx +354 -0
  436. sage/matrix/matrix_generic_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  437. sage/matrix/matrix_generic_sparse.pxd +7 -0
  438. sage/matrix/matrix_generic_sparse.pyx +461 -0
  439. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  440. sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
  441. sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
  442. sage/matrix/matrix_misc.py +313 -0
  443. sage/matrix/matrix_numpy_dense.cpython-314-x86_64-linux-musl.so +0 -0
  444. sage/matrix/matrix_numpy_dense.pxd +14 -0
  445. sage/matrix/matrix_numpy_dense.pyx +450 -0
  446. sage/matrix/matrix_numpy_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  447. sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
  448. sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
  449. sage/matrix/matrix_polynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  450. sage/matrix/matrix_polynomial_dense.pxd +5 -0
  451. sage/matrix/matrix_polynomial_dense.pyx +5341 -0
  452. sage/matrix/matrix_real_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  453. sage/matrix/matrix_real_double_dense.pxd +7 -0
  454. sage/matrix/matrix_real_double_dense.pyx +122 -0
  455. sage/matrix/matrix_space.py +2848 -0
  456. sage/matrix/matrix_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  457. sage/matrix/matrix_sparse.pxd +5 -0
  458. sage/matrix/matrix_sparse.pyx +1222 -0
  459. sage/matrix/matrix_window.cpython-314-x86_64-linux-musl.so +0 -0
  460. sage/matrix/matrix_window.pxd +37 -0
  461. sage/matrix/matrix_window.pyx +242 -0
  462. sage/matrix/misc_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  463. sage/matrix/misc_mpfr.pyx +80 -0
  464. sage/matrix/operation_table.py +1182 -0
  465. sage/matrix/special.py +3666 -0
  466. sage/matrix/strassen.cpython-314-x86_64-linux-musl.so +0 -0
  467. sage/matrix/strassen.pyx +851 -0
  468. sage/matrix/symplectic_basis.py +541 -0
  469. sage/matrix/template.pxd +6 -0
  470. sage/matrix/tests.py +71 -0
  471. sage/matroids/advanced.py +77 -0
  472. sage/matroids/all.py +13 -0
  473. sage/matroids/basis_exchange_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  474. sage/matroids/basis_exchange_matroid.pxd +96 -0
  475. sage/matroids/basis_exchange_matroid.pyx +2344 -0
  476. sage/matroids/basis_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  477. sage/matroids/basis_matroid.pxd +45 -0
  478. sage/matroids/basis_matroid.pyx +1217 -0
  479. sage/matroids/catalog.py +44 -0
  480. sage/matroids/chow_ring.py +473 -0
  481. sage/matroids/chow_ring_ideal.py +849 -0
  482. sage/matroids/circuit_closures_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  483. sage/matroids/circuit_closures_matroid.pxd +16 -0
  484. sage/matroids/circuit_closures_matroid.pyx +559 -0
  485. sage/matroids/circuits_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  486. sage/matroids/circuits_matroid.pxd +38 -0
  487. sage/matroids/circuits_matroid.pyx +947 -0
  488. sage/matroids/constructor.py +1086 -0
  489. sage/matroids/database_collections.py +365 -0
  490. sage/matroids/database_matroids.py +5338 -0
  491. sage/matroids/dual_matroid.py +583 -0
  492. sage/matroids/extension.cpython-314-x86_64-linux-musl.so +0 -0
  493. sage/matroids/extension.pxd +34 -0
  494. sage/matroids/extension.pyx +519 -0
  495. sage/matroids/flats_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  496. sage/matroids/flats_matroid.pxd +28 -0
  497. sage/matroids/flats_matroid.pyx +715 -0
  498. sage/matroids/gammoid.py +600 -0
  499. sage/matroids/graphic_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  500. sage/matroids/graphic_matroid.pxd +39 -0
  501. sage/matroids/graphic_matroid.pyx +2024 -0
  502. sage/matroids/lean_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  503. sage/matroids/lean_matrix.pxd +126 -0
  504. sage/matroids/lean_matrix.pyx +3667 -0
  505. sage/matroids/linear_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  506. sage/matroids/linear_matroid.pxd +180 -0
  507. sage/matroids/linear_matroid.pyx +6649 -0
  508. sage/matroids/matroid.cpython-314-x86_64-linux-musl.so +0 -0
  509. sage/matroids/matroid.pxd +243 -0
  510. sage/matroids/matroid.pyx +8759 -0
  511. sage/matroids/matroids_catalog.py +190 -0
  512. sage/matroids/matroids_plot_helpers.py +890 -0
  513. sage/matroids/minor_matroid.py +480 -0
  514. sage/matroids/minorfix.h +9 -0
  515. sage/matroids/named_matroids.py +5 -0
  516. sage/matroids/rank_matroid.py +268 -0
  517. sage/matroids/set_system.cpython-314-x86_64-linux-musl.so +0 -0
  518. sage/matroids/set_system.pxd +38 -0
  519. sage/matroids/set_system.pyx +800 -0
  520. sage/matroids/transversal_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  521. sage/matroids/transversal_matroid.pxd +14 -0
  522. sage/matroids/transversal_matroid.pyx +893 -0
  523. sage/matroids/union_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  524. sage/matroids/union_matroid.pxd +20 -0
  525. sage/matroids/union_matroid.pyx +331 -0
  526. sage/matroids/unpickling.cpython-314-x86_64-linux-musl.so +0 -0
  527. sage/matroids/unpickling.pyx +843 -0
  528. sage/matroids/utilities.py +809 -0
  529. sage/misc/all__sagemath_modules.py +20 -0
  530. sage/misc/c3.cpython-314-x86_64-linux-musl.so +0 -0
  531. sage/misc/c3.pyx +238 -0
  532. sage/misc/compat.py +87 -0
  533. sage/misc/element_with_label.py +173 -0
  534. sage/misc/func_persist.py +79 -0
  535. sage/misc/pickle_old.cpython-314-x86_64-linux-musl.so +0 -0
  536. sage/misc/pickle_old.pyx +19 -0
  537. sage/misc/proof.py +7 -0
  538. sage/misc/replace_dot_all.py +472 -0
  539. sage/misc/sagedoc_conf.py +168 -0
  540. sage/misc/sphinxify.py +167 -0
  541. sage/misc/test_class_pickling.py +85 -0
  542. sage/modules/all.py +42 -0
  543. sage/modules/complex_double_vector.py +25 -0
  544. sage/modules/diamond_cutting.py +380 -0
  545. sage/modules/fg_pid/all.py +1 -0
  546. sage/modules/fg_pid/fgp_element.py +456 -0
  547. sage/modules/fg_pid/fgp_module.py +2091 -0
  548. sage/modules/fg_pid/fgp_morphism.py +550 -0
  549. sage/modules/filtered_vector_space.py +1271 -0
  550. sage/modules/finite_submodule_iter.cpython-314-x86_64-linux-musl.so +0 -0
  551. sage/modules/finite_submodule_iter.pxd +27 -0
  552. sage/modules/finite_submodule_iter.pyx +452 -0
  553. sage/modules/fp_graded/all.py +1 -0
  554. sage/modules/fp_graded/element.py +346 -0
  555. sage/modules/fp_graded/free_element.py +298 -0
  556. sage/modules/fp_graded/free_homspace.py +53 -0
  557. sage/modules/fp_graded/free_module.py +1060 -0
  558. sage/modules/fp_graded/free_morphism.py +217 -0
  559. sage/modules/fp_graded/homspace.py +563 -0
  560. sage/modules/fp_graded/module.py +1340 -0
  561. sage/modules/fp_graded/morphism.py +1990 -0
  562. sage/modules/fp_graded/steenrod/all.py +1 -0
  563. sage/modules/fp_graded/steenrod/homspace.py +65 -0
  564. sage/modules/fp_graded/steenrod/module.py +477 -0
  565. sage/modules/fp_graded/steenrod/morphism.py +404 -0
  566. sage/modules/fp_graded/steenrod/profile.py +241 -0
  567. sage/modules/free_module.py +8447 -0
  568. sage/modules/free_module_element.cpython-314-x86_64-linux-musl.so +0 -0
  569. sage/modules/free_module_element.pxd +22 -0
  570. sage/modules/free_module_element.pyx +5445 -0
  571. sage/modules/free_module_homspace.py +369 -0
  572. sage/modules/free_module_integer.py +896 -0
  573. sage/modules/free_module_morphism.py +823 -0
  574. sage/modules/free_module_pseudohomspace.py +352 -0
  575. sage/modules/free_module_pseudomorphism.py +578 -0
  576. sage/modules/free_quadratic_module.py +1706 -0
  577. sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
  578. sage/modules/matrix_morphism.py +1745 -0
  579. sage/modules/misc.py +103 -0
  580. sage/modules/module_functors.py +192 -0
  581. sage/modules/multi_filtered_vector_space.py +719 -0
  582. sage/modules/ore_module.py +2208 -0
  583. sage/modules/ore_module_element.py +178 -0
  584. sage/modules/ore_module_homspace.py +147 -0
  585. sage/modules/ore_module_morphism.py +968 -0
  586. sage/modules/quotient_module.py +699 -0
  587. sage/modules/real_double_vector.py +22 -0
  588. sage/modules/submodule.py +255 -0
  589. sage/modules/tensor_operations.py +567 -0
  590. sage/modules/torsion_quadratic_module.py +1352 -0
  591. sage/modules/tutorial_free_modules.py +248 -0
  592. sage/modules/vector_complex_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  593. sage/modules/vector_complex_double_dense.pxd +6 -0
  594. sage/modules/vector_complex_double_dense.pyx +117 -0
  595. sage/modules/vector_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  596. sage/modules/vector_double_dense.pxd +6 -0
  597. sage/modules/vector_double_dense.pyx +604 -0
  598. sage/modules/vector_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  599. sage/modules/vector_integer_dense.pxd +15 -0
  600. sage/modules/vector_integer_dense.pyx +361 -0
  601. sage/modules/vector_integer_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  602. sage/modules/vector_integer_sparse.pxd +29 -0
  603. sage/modules/vector_integer_sparse.pyx +406 -0
  604. sage/modules/vector_modn_dense.cpython-314-x86_64-linux-musl.so +0 -0
  605. sage/modules/vector_modn_dense.pxd +12 -0
  606. sage/modules/vector_modn_dense.pyx +394 -0
  607. sage/modules/vector_modn_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  608. sage/modules/vector_modn_sparse.pxd +21 -0
  609. sage/modules/vector_modn_sparse.pyx +298 -0
  610. sage/modules/vector_numpy_dense.cpython-314-x86_64-linux-musl.so +0 -0
  611. sage/modules/vector_numpy_dense.pxd +15 -0
  612. sage/modules/vector_numpy_dense.pyx +304 -0
  613. sage/modules/vector_numpy_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  614. sage/modules/vector_numpy_integer_dense.pxd +7 -0
  615. sage/modules/vector_numpy_integer_dense.pyx +54 -0
  616. sage/modules/vector_rational_dense.cpython-314-x86_64-linux-musl.so +0 -0
  617. sage/modules/vector_rational_dense.pxd +15 -0
  618. sage/modules/vector_rational_dense.pyx +387 -0
  619. sage/modules/vector_rational_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  620. sage/modules/vector_rational_sparse.pxd +30 -0
  621. sage/modules/vector_rational_sparse.pyx +413 -0
  622. sage/modules/vector_real_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  623. sage/modules/vector_real_double_dense.pxd +6 -0
  624. sage/modules/vector_real_double_dense.pyx +126 -0
  625. sage/modules/vector_space_homspace.py +430 -0
  626. sage/modules/vector_space_morphism.py +989 -0
  627. sage/modules/with_basis/all.py +15 -0
  628. sage/modules/with_basis/cell_module.py +494 -0
  629. sage/modules/with_basis/indexed_element.cpython-314-x86_64-linux-musl.so +0 -0
  630. sage/modules/with_basis/indexed_element.pxd +13 -0
  631. sage/modules/with_basis/indexed_element.pyx +1058 -0
  632. sage/modules/with_basis/invariant.py +1075 -0
  633. sage/modules/with_basis/morphism.py +1636 -0
  634. sage/modules/with_basis/representation.py +2939 -0
  635. sage/modules/with_basis/subquotient.py +685 -0
  636. sage/numerical/all__sagemath_modules.py +6 -0
  637. sage/numerical/gauss_legendre.cpython-314-x86_64-linux-musl.so +0 -0
  638. sage/numerical/gauss_legendre.pyx +381 -0
  639. sage/numerical/optimize.py +910 -0
  640. sage/probability/all.py +10 -0
  641. sage/probability/probability_distribution.cpython-314-x86_64-linux-musl.so +0 -0
  642. sage/probability/probability_distribution.pyx +1242 -0
  643. sage/probability/random_variable.py +411 -0
  644. sage/quadratic_forms/all.py +4 -0
  645. sage/quadratic_forms/all__sagemath_modules.py +15 -0
  646. sage/quadratic_forms/binary_qf.py +2042 -0
  647. sage/quadratic_forms/bqf_class_group.py +748 -0
  648. sage/quadratic_forms/constructions.py +93 -0
  649. sage/quadratic_forms/count_local_2.cpython-314-x86_64-linux-musl.so +0 -0
  650. sage/quadratic_forms/count_local_2.pyx +365 -0
  651. sage/quadratic_forms/extras.py +195 -0
  652. sage/quadratic_forms/quadratic_form.py +1753 -0
  653. sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
  654. sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
  655. sage/quadratic_forms/quadratic_form__evaluate.cpython-314-x86_64-linux-musl.so +0 -0
  656. sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
  657. sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
  658. sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
  659. sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
  660. sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
  661. sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
  662. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
  663. sage/quadratic_forms/quadratic_form__theta.py +352 -0
  664. sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
  665. sage/quadratic_forms/random_quadraticform.py +209 -0
  666. sage/quadratic_forms/ternary.cpython-314-x86_64-linux-musl.so +0 -0
  667. sage/quadratic_forms/ternary.pyx +1154 -0
  668. sage/quadratic_forms/ternary_qf.py +2027 -0
  669. sage/rings/all__sagemath_modules.py +28 -0
  670. sage/rings/asymptotic/all__sagemath_modules.py +1 -0
  671. sage/rings/asymptotic/misc.py +1252 -0
  672. sage/rings/cc.py +4 -0
  673. sage/rings/cfinite_sequence.py +1306 -0
  674. sage/rings/complex_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  675. sage/rings/complex_conversion.pxd +8 -0
  676. sage/rings/complex_conversion.pyx +23 -0
  677. sage/rings/complex_double.cpython-314-x86_64-linux-musl.so +0 -0
  678. sage/rings/complex_double.pxd +21 -0
  679. sage/rings/complex_double.pyx +2654 -0
  680. sage/rings/complex_mpc.cpython-314-x86_64-linux-musl.so +0 -0
  681. sage/rings/complex_mpc.pxd +21 -0
  682. sage/rings/complex_mpc.pyx +2576 -0
  683. sage/rings/complex_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  684. sage/rings/complex_mpfr.pxd +18 -0
  685. sage/rings/complex_mpfr.pyx +3602 -0
  686. sage/rings/derivation.py +2334 -0
  687. sage/rings/finite_rings/all__sagemath_modules.py +1 -0
  688. sage/rings/finite_rings/maps_finite_field.py +191 -0
  689. sage/rings/function_field/all__sagemath_modules.py +8 -0
  690. sage/rings/function_field/derivations.py +102 -0
  691. sage/rings/function_field/derivations_rational.py +132 -0
  692. sage/rings/function_field/differential.py +853 -0
  693. sage/rings/function_field/divisor.py +1107 -0
  694. sage/rings/function_field/drinfeld_modules/action.py +199 -0
  695. sage/rings/function_field/drinfeld_modules/all.py +1 -0
  696. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
  697. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
  698. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
  699. sage/rings/function_field/drinfeld_modules/homset.py +420 -0
  700. sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
  701. sage/rings/function_field/hermite_form_polynomial.cpython-314-x86_64-linux-musl.so +0 -0
  702. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  703. sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-linux-musl.so +0 -0
  704. sage/rings/function_field/khuri_makdisi.pyx +935 -0
  705. sage/rings/invariants/all.py +4 -0
  706. sage/rings/invariants/invariant_theory.py +4597 -0
  707. sage/rings/invariants/reconstruction.py +395 -0
  708. sage/rings/polynomial/all__sagemath_modules.py +17 -0
  709. sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
  710. sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-x86_64-linux-musl.so +0 -0
  711. sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
  712. sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
  713. sage/rings/polynomial/ore_function_element.py +952 -0
  714. sage/rings/polynomial/ore_function_field.py +1028 -0
  715. sage/rings/polynomial/ore_polynomial_element.cpython-314-x86_64-linux-musl.so +0 -0
  716. sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
  717. sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
  718. sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
  719. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-x86_64-linux-musl.so +0 -0
  720. sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
  721. sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
  722. sage/rings/polynomial/skew_polynomial_element.cpython-314-x86_64-linux-musl.so +0 -0
  723. sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
  724. sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
  725. sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-x86_64-linux-musl.so +0 -0
  726. sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
  727. sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
  728. sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-x86_64-linux-musl.so +0 -0
  729. sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
  730. sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
  731. sage/rings/polynomial/skew_polynomial_ring.py +908 -0
  732. sage/rings/real_double_element_gsl.cpython-314-x86_64-linux-musl.so +0 -0
  733. sage/rings/real_double_element_gsl.pxd +8 -0
  734. sage/rings/real_double_element_gsl.pyx +794 -0
  735. sage/rings/real_field.py +58 -0
  736. sage/rings/real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  737. sage/rings/real_mpfr.pxd +29 -0
  738. sage/rings/real_mpfr.pyx +6122 -0
  739. sage/rings/ring_extension.cpython-314-x86_64-linux-musl.so +0 -0
  740. sage/rings/ring_extension.pxd +42 -0
  741. sage/rings/ring_extension.pyx +2779 -0
  742. sage/rings/ring_extension_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  743. sage/rings/ring_extension_conversion.pxd +16 -0
  744. sage/rings/ring_extension_conversion.pyx +462 -0
  745. sage/rings/ring_extension_element.cpython-314-x86_64-linux-musl.so +0 -0
  746. sage/rings/ring_extension_element.pxd +21 -0
  747. sage/rings/ring_extension_element.pyx +1635 -0
  748. sage/rings/ring_extension_homset.py +64 -0
  749. sage/rings/ring_extension_morphism.cpython-314-x86_64-linux-musl.so +0 -0
  750. sage/rings/ring_extension_morphism.pxd +35 -0
  751. sage/rings/ring_extension_morphism.pyx +920 -0
  752. sage/schemes/all__sagemath_modules.py +1 -0
  753. sage/schemes/projective/all__sagemath_modules.py +1 -0
  754. sage/schemes/projective/coherent_sheaf.py +300 -0
  755. sage/schemes/projective/cohomology.py +510 -0
  756. sage/stats/all.py +15 -0
  757. sage/stats/basic_stats.py +489 -0
  758. sage/stats/distributions/all.py +7 -0
  759. sage/stats/distributions/catalog.py +34 -0
  760. sage/stats/distributions/dgs.h +50 -0
  761. sage/stats/distributions/dgs.pxd +111 -0
  762. sage/stats/distributions/dgs_bern.h +400 -0
  763. sage/stats/distributions/dgs_gauss.h +614 -0
  764. sage/stats/distributions/dgs_misc.h +104 -0
  765. sage/stats/distributions/discrete_gaussian_integer.cpython-314-x86_64-linux-musl.so +0 -0
  766. sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
  767. sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
  768. sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
  769. sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
  770. sage/stats/hmm/all.py +15 -0
  771. sage/stats/hmm/chmm.cpython-314-x86_64-linux-musl.so +0 -0
  772. sage/stats/hmm/chmm.pyx +1595 -0
  773. sage/stats/hmm/distributions.cpython-314-x86_64-linux-musl.so +0 -0
  774. sage/stats/hmm/distributions.pxd +29 -0
  775. sage/stats/hmm/distributions.pyx +531 -0
  776. sage/stats/hmm/hmm.cpython-314-x86_64-linux-musl.so +0 -0
  777. sage/stats/hmm/hmm.pxd +17 -0
  778. sage/stats/hmm/hmm.pyx +1388 -0
  779. sage/stats/hmm/util.cpython-314-x86_64-linux-musl.so +0 -0
  780. sage/stats/hmm/util.pxd +7 -0
  781. sage/stats/hmm/util.pyx +165 -0
  782. sage/stats/intlist.cpython-314-x86_64-linux-musl.so +0 -0
  783. sage/stats/intlist.pxd +14 -0
  784. sage/stats/intlist.pyx +588 -0
  785. sage/stats/r.py +49 -0
  786. sage/stats/time_series.cpython-314-x86_64-linux-musl.so +0 -0
  787. sage/stats/time_series.pxd +6 -0
  788. sage/stats/time_series.pyx +2546 -0
  789. sage/tensor/all.py +2 -0
  790. sage/tensor/modules/all.py +8 -0
  791. sage/tensor/modules/alternating_contr_tensor.py +761 -0
  792. sage/tensor/modules/comp.py +5598 -0
  793. sage/tensor/modules/ext_pow_free_module.py +824 -0
  794. sage/tensor/modules/finite_rank_free_module.py +3589 -0
  795. sage/tensor/modules/format_utilities.py +333 -0
  796. sage/tensor/modules/free_module_alt_form.py +858 -0
  797. sage/tensor/modules/free_module_automorphism.py +1207 -0
  798. sage/tensor/modules/free_module_basis.py +1074 -0
  799. sage/tensor/modules/free_module_element.py +284 -0
  800. sage/tensor/modules/free_module_homset.py +652 -0
  801. sage/tensor/modules/free_module_linear_group.py +564 -0
  802. sage/tensor/modules/free_module_morphism.py +1581 -0
  803. sage/tensor/modules/free_module_tensor.py +3289 -0
  804. sage/tensor/modules/reflexive_module.py +386 -0
  805. sage/tensor/modules/tensor_free_module.py +780 -0
  806. sage/tensor/modules/tensor_free_submodule.py +538 -0
  807. sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
  808. sage/tensor/modules/tensor_with_indices.py +1043 -0
@@ -0,0 +1,2171 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ # sage.doctest: needs sage.combinat sage.modules sage.rings.finite_rings
3
+ r"""
4
+ Mini-AES
5
+
6
+ A simplified variant of the Advanced Encryption Standard (AES). Note that
7
+ Mini-AES is for educational purposes only. It is a small-scale version of
8
+ the AES designed to help beginners understand the basic structure of AES.
9
+
10
+ AUTHORS:
11
+
12
+ - Minh Van Nguyen (2009-05): initial version
13
+ """
14
+
15
+ # #########################################################################
16
+ # Copyright (c) 2009 Minh Van Nguyen <nguyenminh2@gmail.com>
17
+ #
18
+ # This program is free software; you can redistribute it and/or modify
19
+ # it under the terms of the GNU General Public License as published by
20
+ # the Free Software Foundation; either version 2 of the License, or
21
+ # (at your option) any later version.
22
+ #
23
+ # This program is distributed in the hope that it will be useful,
24
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
25
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
+ # GNU General Public License for more details.
27
+ #
28
+ # https://www.gnu.org/licenses/
29
+ # #########################################################################
30
+
31
+ from sage.matrix.matrix_dense import Matrix_dense
32
+ from sage.matrix.matrix_space import MatrixSpace
33
+ from sage.monoids.string_monoid import BinaryStrings
34
+ from sage.monoids.string_monoid_element import StringMonoidElement
35
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField
36
+ from sage.rings.integer import Integer
37
+ from sage.structure.sage_object import SageObject
38
+
39
+
40
+ class MiniAES(SageObject):
41
+ r"""
42
+ This class implements the Mini Advanced Encryption Standard (Mini-AES)
43
+ described in [Pha2002]_. Note that Phan's Mini-AES is for educational purposes
44
+ only and is not secure for practical purposes. Mini-AES is a version of
45
+ the AES with all parameters significantly reduced, but at the same time
46
+ preserving the structure of AES. The goal of Mini-AES is to allow a
47
+ beginner to understand the structure of AES, thus laying a foundation
48
+ for a thorough study of AES. Its goal is as a teaching tool and is
49
+ different from the :mod:`SR <sage.crypto.mq.sr>` small scale variants
50
+ of the AES. SR defines a family of parameterizable variants of the AES
51
+ suitable as a framework for comparing different cryptanalytic techniques
52
+ that can be brought to bear on the AES.
53
+
54
+ EXAMPLES:
55
+
56
+ Encrypt a plaintext::
57
+
58
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
59
+ sage: maes = MiniAES()
60
+ sage: K = FiniteField(16, "x")
61
+ sage: MS = MatrixSpace(K, 2, 2)
62
+ sage: P = MS([K("x^3 + x"), K("x^2 + 1"), K("x^2 + x"), K("x^3 + x^2")]); P
63
+ <BLANKLINE>
64
+ [ x^3 + x x^2 + 1]
65
+ [ x^2 + x x^3 + x^2]
66
+ sage: key = MS([K("x^3 + x^2"), K("x^3 + x"), K("x^3 + x^2 + x"), K("x^2 + x + 1")]); key
67
+ <BLANKLINE>
68
+ [ x^3 + x^2 x^3 + x]
69
+ [x^3 + x^2 + x x^2 + x + 1]
70
+ sage: C = maes.encrypt(P, key); C
71
+ [ x^3 + x^2 + 1 x^3 + x^2 + x + 1]
72
+ [ x x^3 + x^2 + x]
73
+
74
+ Decrypt the result::
75
+
76
+ sage: plaintxt = maes.decrypt(C, key)
77
+ sage: plaintxt; P
78
+ <BLANKLINE>
79
+ [ x^3 + x x^2 + 1]
80
+ [ x^2 + x x^3 + x^2]
81
+ <BLANKLINE>
82
+ [ x^3 + x x^2 + 1]
83
+ [ x^2 + x x^3 + x^2]
84
+ sage: plaintxt == P
85
+ True
86
+
87
+ We can also work directly with binary strings::
88
+
89
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
90
+ sage: maes = MiniAES()
91
+ sage: bin = BinaryStrings()
92
+ sage: key = bin.encoding("KE"); key
93
+ 0100101101000101
94
+ sage: P = bin.encoding("Encrypt this secret message!"); P
95
+ 01000101011011100110001101110010011110010111000001110100001000000111010001101000011010010111001100100000011100110110010101100011011100100110010101110100001000000110110101100101011100110111001101100001011001110110010100100001
96
+ sage: C = maes(P, key, algorithm='encrypt'); C
97
+ 11100000101000010110001101101001110110010010111011010001100111100000101000101111100110010010100001110101011100111001000010101000001111000101010011010001100111100111001100000001101100110110101001001000011100000101010110110101
98
+ sage: plaintxt = maes(C, key, algorithm='decrypt')
99
+ sage: plaintxt == P
100
+ True
101
+
102
+ Now we work with integers `n` such that `0 \leq n \leq 15`::
103
+
104
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
105
+ sage: maes = MiniAES()
106
+ sage: P = [n for n in range(16)]; P
107
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
108
+ sage: key = [2, 3, 11, 0]; key
109
+ [2, 3, 11, 0]
110
+ sage: P = maes.integer_to_binary(P); P
111
+ 0000000100100011010001010110011110001001101010111100110111101111
112
+ sage: key = maes.integer_to_binary(key); key
113
+ 0010001110110000
114
+ sage: C = maes(P, key, algorithm='encrypt'); C
115
+ 0011101000101110010011000101010100011101010000111000100100011010
116
+ sage: plaintxt = maes(C, key, algorithm='decrypt')
117
+ sage: plaintxt == P
118
+ True
119
+
120
+ Generate some random plaintext and a random secret key. Encrypt the
121
+ plaintext using that secret key and decrypt the result. Then compare the
122
+ decrypted plaintext with the original plaintext::
123
+
124
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
125
+ sage: maes = MiniAES()
126
+ sage: MS = MatrixSpace(FiniteField(16, "x"), 2, 2)
127
+ sage: P = MS.random_element()
128
+ sage: key = maes.random_key()
129
+ sage: C = maes.encrypt(P, key)
130
+ sage: plaintxt = maes.decrypt(C, key)
131
+ sage: plaintxt == P
132
+ True
133
+ """
134
+
135
+ def __init__(self):
136
+ r"""
137
+ A simplified variant of the Advanced Encryption Standard (AES).
138
+
139
+ EXAMPLES::
140
+
141
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
142
+ sage: maes = MiniAES(); maes
143
+ Mini-AES block cipher with 16-bit keys
144
+ sage: MS = MatrixSpace(FiniteField(16, "x"), 2, 2)
145
+ sage: P = MS.random_element()
146
+ sage: key = maes.random_key()
147
+ sage: C = maes.encrypt(P, key)
148
+ sage: plaintxt = maes.decrypt(C, key)
149
+ sage: plaintxt == P
150
+ True
151
+ """
152
+ from sage.crypto.sbox import SBox
153
+ self._key_size = 16 # the number of bits in a secret key
154
+ B = BinaryStrings()
155
+ K = FiniteField(self._key_size, "x")
156
+ # the S-box for encryption
157
+ self._sboxE = SBox(14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7)
158
+ # the S-box for decryption
159
+ self._sboxD = SBox(14, 3, 4, 8, 1, 12, 10, 15, 7, 13, 9, 6, 11, 2, 0, 5)
160
+ # nibble to finite field element
161
+ self._bin_to_GF = { B("0000"): K("0"),
162
+ B("0001"): K("1"),
163
+ B("0010"): K("x"),
164
+ B("0011"): K("x + 1"),
165
+ B("0100"): K("x^2"),
166
+ B("0101"): K("x^2 + 1"),
167
+ B("0110"): K("x^2 + x"),
168
+ B("0111"): K("x^2 + x + 1"),
169
+ B("1000"): K("x^3"),
170
+ B("1001"): K("x^3 + 1"),
171
+ B("1010"): K("x^3 + x"),
172
+ B("1011"): K("x^3 + x + 1"),
173
+ B("1100"): K("x^3 + x^2"),
174
+ B("1101"): K("x^3 + x^2 + 1"),
175
+ B("1110"): K("x^3 + x^2 + x"),
176
+ B("1111"): K("x^3 + x^2 + x+ 1") }
177
+ # nibble to integer
178
+ self._bin_to_int = { B("0000"): Integer(0),
179
+ B("0001"): Integer(1),
180
+ B("0010"): Integer(2),
181
+ B("0011"): Integer(3),
182
+ B("0100"): Integer(4),
183
+ B("0101"): Integer(5),
184
+ B("0110"): Integer(6),
185
+ B("0111"): Integer(7),
186
+ B("1000"): Integer(8),
187
+ B("1001"): Integer(9),
188
+ B("1010"): Integer(10),
189
+ B("1011"): Integer(11),
190
+ B("1100"): Integer(12),
191
+ B("1101"): Integer(13),
192
+ B("1110"): Integer(14),
193
+ B("1111"): Integer(15) }
194
+ # finite field element to nibble
195
+ self._GF_to_bin = { K("0"): B("0000"),
196
+ K("1"): B("0001"),
197
+ K("x"): B("0010"),
198
+ K("x + 1"): B("0011"),
199
+ K("x^2"): B("0100"),
200
+ K("x^2 + 1"): B("0101"),
201
+ K("x^2 + x"): B("0110"),
202
+ K("x^2 + x + 1"): B("0111"),
203
+ K("x^3"): B("1000"),
204
+ K("x^3 + 1"): B("1001"),
205
+ K("x^3 + x"): B("1010"),
206
+ K("x^3 + x + 1"): B("1011"),
207
+ K("x^3 + x^2"): B("1100"),
208
+ K("x^3 + x^2 + 1"): B("1101"),
209
+ K("x^3 + x^2 + x"): B("1110"),
210
+ K("x^3 + x^2 + x+ 1"): B("1111") }
211
+ # finite field element to integer
212
+ self._GF_to_int = { K("0"): Integer(0),
213
+ K("1"): Integer(1),
214
+ K("x"): Integer(2),
215
+ K("x + 1"): Integer(3),
216
+ K("x^2"): Integer(4),
217
+ K("x^2 + 1"): Integer(5),
218
+ K("x^2 + x"): Integer(6),
219
+ K("x^2 + x + 1"): Integer(7),
220
+ K("x^3"): Integer(8),
221
+ K("x^3 + 1"): Integer(9),
222
+ K("x^3 + x"): Integer(10),
223
+ K("x^3 + x + 1"): Integer(11),
224
+ K("x^3 + x^2"): Integer(12),
225
+ K("x^3 + x^2 + 1"): Integer(13),
226
+ K("x^3 + x^2 + x"): Integer(14),
227
+ K("x^3 + x^2 + x+ 1"): Integer(15) }
228
+ # integer to nibble
229
+ self._int_to_bin = { Integer(0): B("0000"),
230
+ Integer(1): B("0001"),
231
+ Integer(2): B("0010"),
232
+ Integer(3): B("0011"),
233
+ Integer(4): B("0100"),
234
+ Integer(5): B("0101"),
235
+ Integer(6): B("0110"),
236
+ Integer(7): B("0111"),
237
+ Integer(8): B("1000"),
238
+ Integer(9): B("1001"),
239
+ Integer(10): B("1010"),
240
+ Integer(11): B("1011"),
241
+ Integer(12): B("1100"),
242
+ Integer(13): B("1101"),
243
+ Integer(14): B("1110"),
244
+ Integer(15): B("1111") }
245
+ # integer to finite field element
246
+ self._int_to_GF = { Integer(0): K("0"),
247
+ Integer(1): K("1"),
248
+ Integer(2): K("x"),
249
+ Integer(3): K("x + 1"),
250
+ Integer(4): K("x^2"),
251
+ Integer(5): K("x^2 + 1"),
252
+ Integer(6): K("x^2 + x"),
253
+ Integer(7): K("x^2 + x + 1"),
254
+ Integer(8): K("x^3"),
255
+ Integer(9): K("x^3 + 1"),
256
+ Integer(10): K("x^3 + x"),
257
+ Integer(11): K("x^3 + x + 1"),
258
+ Integer(12): K("x^3 + x^2"),
259
+ Integer(13): K("x^3 + x^2 + 1"),
260
+ Integer(14): K("x^3 + x^2 + x"),
261
+ Integer(15): K("x^3 + x^2 + x+ 1") }
262
+
263
+ def __call__(self, B, key, algorithm='encrypt'):
264
+ r"""
265
+ Apply Mini-AES encryption or decryption on the binary string ``B``
266
+ using the key ``key``. The flag ``algorithm`` controls what action is
267
+ to be performed on ``B``.
268
+
269
+ INPUT:
270
+
271
+ - ``B`` -- a binary string, where the number of bits is positive and
272
+ a multiple of 16. The number of 16 bits is evenly divided into four
273
+ nibbles. Hence 16 bits can be conveniently represented as a
274
+ `2 \times 2` matrix block for encryption or decryption.
275
+
276
+ - ``key`` -- a secret key; this must be a 16-bit binary string
277
+
278
+ - ``algorithm`` -- (default: ``'encrypt'``) a string; a flag to signify
279
+ whether encryption or decryption is to be applied to the binary
280
+ string ``B``. The encryption flag is ``'encrypt'`` and the decryption
281
+ flag is ``'decrypt'``.
282
+
283
+ OUTPUT:
284
+
285
+ - The ciphertext (respectively plaintext) corresponding to the
286
+ binary string ``B``.
287
+
288
+ EXAMPLES::
289
+
290
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
291
+ sage: maes = MiniAES()
292
+ sage: bin = BinaryStrings()
293
+ sage: key = bin.encoding("KE"); key
294
+ 0100101101000101
295
+ sage: P = bin.encoding("Encrypt this secret message!"); P
296
+ 01000101011011100110001101110010011110010111000001110100001000000111010001101000011010010111001100100000011100110110010101100011011100100110010101110100001000000110110101100101011100110111001101100001011001110110010100100001
297
+ sage: C = maes(P, key, algorithm='encrypt'); C
298
+ 11100000101000010110001101101001110110010010111011010001100111100000101000101111100110010010100001110101011100111001000010101000001111000101010011010001100111100111001100000001101100110110101001001000011100000101010110110101
299
+ sage: plaintxt = maes(C, key, algorithm='decrypt')
300
+ sage: plaintxt == P
301
+ True
302
+
303
+ TESTS:
304
+
305
+ The binary string ``B`` must be non-empty and the number of bits must
306
+ be a multiple of 16::
307
+
308
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
309
+ sage: maes = MiniAES()
310
+ sage: maes("B", "key")
311
+ Traceback (most recent call last):
312
+ ...
313
+ TypeError: input B must be a non-empty binary string with number of bits a multiple of 16
314
+ sage: bin = BinaryStrings()
315
+ sage: B = bin.encoding("A")
316
+ sage: maes(B, "key")
317
+ Traceback (most recent call last):
318
+ ...
319
+ ValueError: the number of bits in the binary string B must be positive and a multiple of 16
320
+
321
+ The secret key ``key`` must be a 16-bit binary string::
322
+
323
+ sage: B = bin.encoding("ABCD")
324
+ sage: maes(B, "key")
325
+ Traceback (most recent call last):
326
+ ...
327
+ TypeError: secret key must be a 16-bit binary string
328
+ sage: key = bin.encoding("K")
329
+ sage: maes(B, key)
330
+ Traceback (most recent call last):
331
+ ...
332
+ ValueError: secret key must be a 16-bit binary string
333
+
334
+ The value for ``algorithm`` must be either ``'encrypt'`` or
335
+ ``'decrypt'``::
336
+
337
+ sage: B = bin.encoding("ABCD")
338
+ sage: key = bin.encoding("KE")
339
+ sage: maes(B, key, algorithm='ABC')
340
+ Traceback (most recent call last):
341
+ ...
342
+ ValueError: algorithm must be either 'encrypt' or 'decrypt'
343
+ sage: maes(B, key, algorithm='e')
344
+ Traceback (most recent call last):
345
+ ...
346
+ ValueError: algorithm must be either 'encrypt' or 'decrypt'
347
+ sage: maes(B, key, algorithm='d')
348
+ Traceback (most recent call last):
349
+ ...
350
+ ValueError: algorithm must be either 'encrypt' or 'decrypt'
351
+ """
352
+ from sage.rings.finite_rings.integer_mod import Mod
353
+ if not isinstance(B, StringMonoidElement):
354
+ raise TypeError("input B must be a non-empty binary string with number of bits a multiple of 16")
355
+ if (len(B) == 0) or (Mod(len(B), self._key_size).lift() != 0):
356
+ raise ValueError("the number of bits in the binary string B must be positive and a multiple of 16")
357
+ if not isinstance(key, StringMonoidElement):
358
+ raise TypeError("secret key must be a 16-bit binary string")
359
+ if len(key) != self._key_size:
360
+ raise ValueError("secret key must be a 16-bit binary string")
361
+
362
+ N = len(B) // self._key_size # the number of 16-bit blocks
363
+ MS = MatrixSpace(FiniteField(self._key_size, "x"), 2, 2)
364
+ bin = BinaryStrings()
365
+ S = ""
366
+ if algorithm == "encrypt":
367
+ # encrypt each 16-bit block in succession
368
+ for i in range(N):
369
+ # here 16 is the number of bits per encryption block
370
+ block = B[i*16 : (i+1)*16]
371
+ matB = MS(self.binary_to_GF(block))
372
+ matK = MS(self.binary_to_GF(key))
373
+ e = self.encrypt(matB, matK)
374
+ e = self.GF_to_binary(e)
375
+ S = "".join([S, str(e)])
376
+ return bin(S)
377
+ elif algorithm == "decrypt":
378
+ # decrypt each 16-bit block in succession
379
+ for i in range(N):
380
+ # here 16 is the number of bits per encryption block
381
+ block = B[i*16 : (i+1)*16]
382
+ matB = MS(self.binary_to_GF(block))
383
+ matK = MS(self.binary_to_GF(key))
384
+ e = self.decrypt(matB, matK)
385
+ e = self.GF_to_binary(e)
386
+ S = "".join([S, str(e)])
387
+ return bin(S)
388
+ else:
389
+ raise ValueError("algorithm must be either 'encrypt' or 'decrypt'")
390
+
391
+ def __eq__(self, other):
392
+ r"""
393
+ Compare ``self`` with ``other``.
394
+
395
+ Mini-AES objects are the same if they have the same key size and
396
+ the same S-boxes.
397
+
398
+ EXAMPLES::
399
+
400
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
401
+ sage: m = MiniAES()
402
+ sage: m == loads(dumps(m))
403
+ True
404
+ """
405
+ return ( (self._key_size == other._key_size) and
406
+ (self._sboxE == other._sboxE) and
407
+ (self._sboxD == other._sboxD) )
408
+
409
+ def __repr__(self):
410
+ r"""
411
+ Return the string representation of ``self``.
412
+
413
+ EXAMPLES::
414
+
415
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
416
+ sage: m = MiniAES(); m
417
+ Mini-AES block cipher with 16-bit keys
418
+ """
419
+ return "Mini-AES block cipher with 16-bit keys"
420
+
421
+ def add_key(self, block, rkey):
422
+ r"""
423
+ Return the matrix addition of ``block`` and ``rkey``. Both ``block``
424
+ and ``rkey`` are `2 \times 2` matrices over the finite field
425
+ `\GF{2^4}`. This method just return the matrix addition of
426
+ these two matrices.
427
+
428
+ INPUT:
429
+
430
+ - ``block`` -- a `2 \times 2` matrix with entries over
431
+ `\GF{2^4}`
432
+
433
+ - ``rkey`` -- a round key; a `2 \times 2` matrix with entries over
434
+ `\GF{2^4}`
435
+
436
+ OUTPUT: the matrix addition of ``block`` and ``rkey``
437
+
438
+ EXAMPLES:
439
+
440
+ We can work with elements of `\GF{2^4}`::
441
+
442
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
443
+ sage: maes = MiniAES()
444
+ sage: K = FiniteField(16, "x")
445
+ sage: MS = MatrixSpace(K, 2, 2)
446
+ sage: D = MS([ [K("x^3 + x^2 + x + 1"), K("x^3 + x")], [K("0"), K("x^3 + x^2")] ]); D
447
+ <BLANKLINE>
448
+ [x^3 + x^2 + x + 1 x^3 + x]
449
+ [ 0 x^3 + x^2]
450
+ sage: k = MS([ [K("x^2 + 1"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ]); k
451
+ <BLANKLINE>
452
+ [ x^2 + 1 x^3 + x^2 + x + 1]
453
+ [ x + 1 0]
454
+ sage: maes.add_key(D, k)
455
+ <BLANKLINE>
456
+ [ x^3 + x x^2 + 1]
457
+ [ x + 1 x^3 + x^2]
458
+
459
+ Or work with binary strings::
460
+
461
+ sage: bin = BinaryStrings()
462
+ sage: B = bin.encoding("We"); B
463
+ 0101011101100101
464
+ sage: B = MS(maes.binary_to_GF(B)); B
465
+ <BLANKLINE>
466
+ [ x^2 + 1 x^2 + x + 1]
467
+ [ x^2 + x x^2 + 1]
468
+ sage: key = bin.encoding("KY"); key
469
+ 0100101101011001
470
+ sage: key = MS(maes.binary_to_GF(key)); key
471
+ <BLANKLINE>
472
+ [ x^2 x^3 + x + 1]
473
+ [ x^2 + 1 x^3 + 1]
474
+ sage: maes.add_key(B, key)
475
+ <BLANKLINE>
476
+ [ 1 x^3 + x^2]
477
+ [ x + 1 x^3 + x^2]
478
+
479
+ We can also work with integers `n` such that `0 \leq n \leq 15`::
480
+
481
+ sage: N = [2, 3, 5, 7]; N
482
+ [2, 3, 5, 7]
483
+ sage: key = [9, 11, 13, 15]; key
484
+ [9, 11, 13, 15]
485
+ sage: N = MS(maes.integer_to_GF(N)); N
486
+ <BLANKLINE>
487
+ [ x x + 1]
488
+ [ x^2 + 1 x^2 + x + 1]
489
+ sage: key = MS(maes.integer_to_GF(key)); key
490
+ <BLANKLINE>
491
+ [ x^3 + 1 x^3 + x + 1]
492
+ [ x^3 + x^2 + 1 x^3 + x^2 + x + 1]
493
+ sage: maes.add_key(N, key)
494
+ <BLANKLINE>
495
+ [x^3 + x + 1 x^3]
496
+ [ x^3 x^3]
497
+
498
+ TESTS:
499
+
500
+ The input block and key must each be a matrix::
501
+
502
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
503
+ sage: maes = MiniAES()
504
+ sage: K = FiniteField(16, "x")
505
+ sage: MSB = MatrixSpace(K, 2, 2)
506
+ sage: B = MSB([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ])
507
+ sage: maes.add_key(B, "key")
508
+ Traceback (most recent call last):
509
+ ...
510
+ TypeError: round key must be a 2 x 2 matrix over GF(16)
511
+ sage: maes.add_key("block", "key")
512
+ Traceback (most recent call last):
513
+ ...
514
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
515
+
516
+ In addition, the dimensions of the input matrices must each be
517
+ `2 \times 2`::
518
+
519
+ sage: MSB = MatrixSpace(K, 1, 2)
520
+ sage: B = MSB([ [K("x^3 + 1"), K("x^2 + x")] ])
521
+ sage: maes.add_key(B, "key")
522
+ Traceback (most recent call last):
523
+ ...
524
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
525
+ sage: MSB = MatrixSpace(K, 2, 2)
526
+ sage: B = MSB([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ])
527
+ sage: MSK = MatrixSpace(K, 1, 2)
528
+ sage: key = MSK([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")]])
529
+ sage: maes.add_key(B, key)
530
+ Traceback (most recent call last):
531
+ ...
532
+ TypeError: round key must be a 2 x 2 matrix over GF(16)
533
+ """
534
+ if not isinstance(block, Matrix_dense) or \
535
+ not (block.base_ring().order() == 16 and block.base_ring().is_field()):
536
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
537
+ if not (block.nrows() == block.ncols() == 2):
538
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
539
+
540
+ if not isinstance(rkey, Matrix_dense) or \
541
+ not (rkey.base_ring().order() == 16 and rkey.base_ring().is_field()):
542
+ raise TypeError("round key must be a 2 x 2 matrix over GF(16)")
543
+ if not (rkey.nrows() == rkey.ncols() == 2):
544
+ raise TypeError("round key must be a 2 x 2 matrix over GF(16)")
545
+
546
+ return block + rkey
547
+
548
+ def block_length(self):
549
+ r"""
550
+ Return the block length of Phan's Mini-AES block cipher. A key in
551
+ Phan's Mini-AES is a block of 16 bits. Each nibble of a key can be
552
+ considered as an element of the finite field `\GF{2^4}`.
553
+ Therefore the key consists of four elements from `\GF{2^4}`.
554
+
555
+ OUTPUT:
556
+
557
+ - The block (or key) length in number of bits.
558
+
559
+ EXAMPLES::
560
+
561
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
562
+ sage: maes = MiniAES()
563
+ sage: maes.block_length()
564
+ 16
565
+ """
566
+ return self._key_size
567
+
568
+ def decrypt(self, C, key):
569
+ r"""
570
+ Use Phan's Mini-AES to decrypt the ciphertext ``C`` with the secret
571
+ key ``key``. Both ``C`` and ``key`` must be `2 \times 2` matrices over
572
+ the finite field `\GF{2^4}`. Let `\gamma` denote the
573
+ operation of nibble-sub, `\pi` denote shift-row, `\theta` denote
574
+ mix-column, and `\sigma_{K_i}` denote add-key with the round key
575
+ `K_i`. Then decryption `D` using Phan's Mini-AES is the function
576
+ composition
577
+
578
+ .. MATH::
579
+
580
+ D = \sigma_{K_0} \circ \gamma^{-1} \circ \pi \circ \theta \circ \sigma_{K_1} \circ \gamma^{-1} \circ \pi \circ \sigma_{K_2}
581
+
582
+ where `\gamma^{-1}` is the nibble-sub operation that uses the S-box
583
+ for decryption, and the order of execution is from right to left.
584
+
585
+ INPUT:
586
+
587
+ - ``C`` -- a ciphertext block; must be a `2 \times 2` matrix over
588
+ the finite field `\GF{2^4}`
589
+
590
+ - ``key`` -- a secret key for this Mini-AES block cipher; must be a
591
+ `2 \times 2` matrix over the finite field `\GF{2^4}`
592
+
593
+ OUTPUT: the plaintext corresponding to ``C``
594
+
595
+ EXAMPLES:
596
+
597
+ We encrypt a plaintext, decrypt the ciphertext, then compare the
598
+ decrypted plaintext with the original plaintext. Here we work with
599
+ elements of `\GF{2^4}`::
600
+
601
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
602
+ sage: maes = MiniAES()
603
+ sage: K = FiniteField(16, "x")
604
+ sage: MS = MatrixSpace(K, 2, 2)
605
+ sage: P = MS([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ]); P
606
+ <BLANKLINE>
607
+ [ x^3 + 1 x^2 + x]
608
+ [x^3 + x^2 x + 1]
609
+ sage: key = MS([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ]); key
610
+ <BLANKLINE>
611
+ [ x^3 + x^2 x^3 + x^2 + x + 1]
612
+ [ x + 1 0]
613
+ sage: C = maes.encrypt(P, key); C
614
+ [ x + 1 x^2 + 1]
615
+ [x^3 + x^2 + x + 1 x^2]
616
+ sage: plaintxt = maes.decrypt(C, key)
617
+ sage: plaintxt; P
618
+ <BLANKLINE>
619
+ [ x^3 + 1 x^2 + x]
620
+ [x^3 + x^2 x + 1]
621
+ <BLANKLINE>
622
+ [ x^3 + 1 x^2 + x]
623
+ [x^3 + x^2 x + 1]
624
+ sage: plaintxt == P
625
+ True
626
+
627
+ But we can also work with binary strings::
628
+
629
+ sage: bin = BinaryStrings()
630
+ sage: P = bin.encoding("de"); P
631
+ 0110010001100101
632
+ sage: P = MS(maes.binary_to_GF(P)); P
633
+ <BLANKLINE>
634
+ [x^2 + x x^2]
635
+ [x^2 + x x^2 + 1]
636
+ sage: key = bin.encoding("ke"); key
637
+ 0110101101100101
638
+ sage: key = MS(maes.binary_to_GF(key)); key
639
+ <BLANKLINE>
640
+ [ x^2 + x x^3 + x + 1]
641
+ [ x^2 + x x^2 + 1]
642
+ sage: C = maes.encrypt(P, key)
643
+ sage: plaintxt = maes.decrypt(C, key)
644
+ sage: plaintxt == P
645
+ True
646
+
647
+ Here we work with integers `n` such that `0 \leq n \leq 15`::
648
+
649
+ sage: P = [3, 5, 7, 14]; P
650
+ [3, 5, 7, 14]
651
+ sage: key = [2, 6, 7, 8]; key
652
+ [2, 6, 7, 8]
653
+ sage: P = MS(maes.integer_to_GF(P)); P
654
+ <BLANKLINE>
655
+ [ x + 1 x^2 + 1]
656
+ [ x^2 + x + 1 x^3 + x^2 + x]
657
+ sage: key = MS(maes.integer_to_GF(key)); key
658
+ <BLANKLINE>
659
+ [ x x^2 + x]
660
+ [x^2 + x + 1 x^3]
661
+ sage: C = maes.encrypt(P, key)
662
+ sage: plaintxt = maes.decrypt(C, key)
663
+ sage: plaintxt == P
664
+ True
665
+
666
+ TESTS:
667
+
668
+ The input block must be a matrix::
669
+
670
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
671
+ sage: maes = MiniAES()
672
+ sage: K = FiniteField(16, "x")
673
+ sage: MS = MatrixSpace(K, 2, 2)
674
+ sage: key = MS([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ])
675
+ sage: maes.decrypt("C", key)
676
+ Traceback (most recent call last):
677
+ ...
678
+ TypeError: ciphertext block must be a 2 x 2 matrix over GF(16)
679
+ sage: C = MS([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ])
680
+ sage: maes.decrypt(C, "key")
681
+ Traceback (most recent call last):
682
+ ...
683
+ TypeError: secret key must be a 2 x 2 matrix over GF(16)
684
+
685
+ In addition, the dimensions of the input matrices must be
686
+ `2 \times 2`::
687
+
688
+ sage: MS = MatrixSpace(K, 1, 2)
689
+ sage: C = MS([ [K("x^3 + 1"), K("x^2 + x")]])
690
+ sage: maes.decrypt(C, "key")
691
+ Traceback (most recent call last):
692
+ ...
693
+ TypeError: ciphertext block must be a 2 x 2 matrix over GF(16)
694
+ sage: MSC = MatrixSpace(K, 2, 2)
695
+ sage: C = MSC([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ])
696
+ sage: MSK = MatrixSpace(K, 1, 2)
697
+ sage: key = MSK([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")]])
698
+ sage: maes.decrypt(C, key)
699
+ Traceback (most recent call last):
700
+ ...
701
+ TypeError: secret key must be a 2 x 2 matrix over GF(16)
702
+ """
703
+ if not isinstance(C, Matrix_dense) or \
704
+ not (C.base_ring().order() == 16 and C.base_ring().is_field()):
705
+ raise TypeError("ciphertext block must be a 2 x 2 matrix over GF(16)")
706
+ if not (C.nrows() == C.ncols() == 2):
707
+ raise TypeError("ciphertext block must be a 2 x 2 matrix over GF(16)")
708
+ if not isinstance(key, Matrix_dense) or \
709
+ not (key.base_ring().order() == 16 and key.base_ring().is_field()):
710
+ raise TypeError("secret key must be a 2 x 2 matrix over GF(16)")
711
+ if not (key.nrows() == key.ncols() == 2):
712
+ raise TypeError("secret key must be a 2 x 2 matrix over GF(16)")
713
+
714
+ # pre-compute the round keys
715
+ rkey0 = self.round_key(key, 0)
716
+ rkey1 = self.round_key(key, 1)
717
+ rkey2 = self.round_key(key, 2)
718
+
719
+ # now proceed with decrypting the ciphertext
720
+
721
+ # undo the result of round 2
722
+ plaintext = self.add_key(C, rkey2)
723
+ plaintext = self.shift_row(plaintext)
724
+ plaintext = self.nibble_sub(plaintext, algorithm='decrypt')
725
+
726
+ # undo the result of round 1
727
+ plaintext = self.add_key(plaintext, rkey1)
728
+ plaintext = self.mix_column(plaintext)
729
+ plaintext = self.shift_row(plaintext)
730
+ plaintext = self.nibble_sub(plaintext, algorithm='decrypt')
731
+
732
+ # undo the result of round 0
733
+ plaintext = self.add_key(plaintext, rkey0)
734
+
735
+ return plaintext
736
+
737
+ def encrypt(self, P, key):
738
+ r"""
739
+ Use Phan's Mini-AES to encrypt the plaintext ``P`` with the secret
740
+ key ``key``. Both ``P`` and ``key`` must be `2 \times 2` matrices
741
+ over the finite field `\GF{2^4}`. Let `\gamma` denote the
742
+ operation of nibble-sub, `\pi` denote shift-row, `\theta` denote
743
+ mix-column, and `\sigma_{K_i}` denote add-key with the round key
744
+ `K_i`. Then encryption `E` using Phan's Mini-AES is the function
745
+ composition
746
+
747
+ .. MATH::
748
+
749
+ E = \sigma_{K_2} \circ \pi \circ \gamma \circ \sigma_{K_1} \circ \theta \circ \pi \circ \gamma \circ \sigma_{K_0}
750
+
751
+ where the order of execution is from right to left. Note that
752
+ `\gamma` is the nibble-sub operation that uses the S-box for
753
+ encryption.
754
+
755
+ INPUT:
756
+
757
+ - ``P`` -- a plaintext block; must be a `2 \times 2` matrix over
758
+ the finite field `\GF{2^4}`
759
+
760
+ - ``key`` -- a secret key for this Mini-AES block cipher; must be a
761
+ `2 \times 2` matrix over the finite field `\GF{2^4}`
762
+
763
+ OUTPUT: the ciphertext corresponding to ``P``
764
+
765
+ EXAMPLES:
766
+
767
+ Here we work with elements of `\GF{2^4}`::
768
+
769
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
770
+ sage: maes = MiniAES()
771
+ sage: K = FiniteField(16, "x")
772
+ sage: MS = MatrixSpace(K, 2, 2)
773
+ sage: P = MS([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ]); P
774
+ <BLANKLINE>
775
+ [ x^3 + 1 x^2 + x]
776
+ [x^3 + x^2 x + 1]
777
+ sage: key = MS([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ]); key
778
+ <BLANKLINE>
779
+ [ x^3 + x^2 x^3 + x^2 + x + 1]
780
+ [ x + 1 0]
781
+ sage: maes.encrypt(P, key)
782
+ [ x + 1 x^2 + 1]
783
+ [x^3 + x^2 + x + 1 x^2]
784
+
785
+ But we can also work with binary strings::
786
+
787
+ sage: bin = BinaryStrings()
788
+ sage: P = bin.encoding("de"); P
789
+ 0110010001100101
790
+ sage: P = MS(maes.binary_to_GF(P)); P
791
+ <BLANKLINE>
792
+ [x^2 + x x^2]
793
+ [x^2 + x x^2 + 1]
794
+ sage: key = bin.encoding("ke"); key
795
+ 0110101101100101
796
+ sage: key = MS(maes.binary_to_GF(key)); key
797
+ <BLANKLINE>
798
+ [ x^2 + x x^3 + x + 1]
799
+ [ x^2 + x x^2 + 1]
800
+ sage: C = maes.encrypt(P, key)
801
+ sage: plaintxt = maes.decrypt(C, key)
802
+ sage: plaintxt == P
803
+ True
804
+
805
+ Now we work with integers `n` such that `0 \leq n \leq 15`::
806
+
807
+ sage: P = [1, 5, 8, 12]; P
808
+ [1, 5, 8, 12]
809
+ sage: key = [5, 9, 15, 0]; key
810
+ [5, 9, 15, 0]
811
+ sage: P = MS(maes.integer_to_GF(P)); P
812
+ <BLANKLINE>
813
+ [ 1 x^2 + 1]
814
+ [ x^3 x^3 + x^2]
815
+ sage: key = MS(maes.integer_to_GF(key)); key
816
+ <BLANKLINE>
817
+ [ x^2 + 1 x^3 + 1]
818
+ [x^3 + x^2 + x + 1 0]
819
+ sage: C = maes.encrypt(P, key)
820
+ sage: plaintxt = maes.decrypt(C, key)
821
+ sage: plaintxt == P
822
+ True
823
+
824
+ TESTS:
825
+
826
+ The input block must be a matrix::
827
+
828
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
829
+ sage: maes = MiniAES()
830
+ sage: K = FiniteField(16, "x")
831
+ sage: MS = MatrixSpace(K, 2, 2)
832
+ sage: key = MS([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ])
833
+ sage: maes.encrypt("P", key)
834
+ Traceback (most recent call last):
835
+ ...
836
+ TypeError: plaintext block must be a 2 x 2 matrix over GF(16)
837
+ sage: P = MS([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ])
838
+ sage: maes.encrypt(P, "key")
839
+ Traceback (most recent call last):
840
+ ...
841
+ TypeError: secret key must be a 2 x 2 matrix over GF(16)
842
+
843
+ In addition, the dimensions of the input matrices must be
844
+ `2 \times 2`::
845
+
846
+ sage: MS = MatrixSpace(K, 1, 2)
847
+ sage: P = MS([ [K("x^3 + 1"), K("x^2 + x")]])
848
+ sage: maes.encrypt(P, "key")
849
+ Traceback (most recent call last):
850
+ ...
851
+ TypeError: plaintext block must be a 2 x 2 matrix over GF(16)
852
+ sage: MSP = MatrixSpace(K, 2, 2)
853
+ sage: P = MSP([ [K("x^3 + 1"), K("x^2 + x")], [K("x^3 + x^2"), K("x + 1")] ])
854
+ sage: MSK = MatrixSpace(K, 1, 2)
855
+ sage: key = MSK([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")]])
856
+ sage: maes.encrypt(P, key)
857
+ Traceback (most recent call last):
858
+ ...
859
+ TypeError: secret key must be a 2 x 2 matrix over GF(16)
860
+ """
861
+ if not isinstance(P, Matrix_dense) or \
862
+ not (P.base_ring().order() == 16 and P.base_ring().is_field()):
863
+ raise TypeError("plaintext block must be a 2 x 2 matrix over GF(16)")
864
+ if not (P.nrows() == P.ncols() == 2):
865
+ raise TypeError("plaintext block must be a 2 x 2 matrix over GF(16)")
866
+ if not isinstance(key, Matrix_dense) or \
867
+ not (key.base_ring().order() == 16 and key.base_ring().is_field()):
868
+ raise TypeError("secret key must be a 2 x 2 matrix over GF(16)")
869
+ if not (key.nrows() == key.ncols() == 2):
870
+ raise TypeError("secret key must be a 2 x 2 matrix over GF(16)")
871
+
872
+ # pre-compute the round keys
873
+ rkey0 = self.round_key(key, 0)
874
+ rkey1 = self.round_key(key, 1)
875
+ rkey2 = self.round_key(key, 2)
876
+
877
+ # now proceed with encrypting the plaintext
878
+
879
+ # round 0
880
+ ciphertext = self.add_key(P, rkey0)
881
+
882
+ # round 1
883
+ ciphertext = self.nibble_sub(ciphertext, algorithm='encrypt')
884
+ ciphertext = self.shift_row(ciphertext)
885
+ ciphertext = self.mix_column(ciphertext)
886
+ ciphertext = self.add_key(ciphertext, rkey1)
887
+
888
+ # round 2
889
+ ciphertext = self.nibble_sub(ciphertext, algorithm='encrypt')
890
+ ciphertext = self.shift_row(ciphertext)
891
+ ciphertext = self.add_key(ciphertext, rkey2)
892
+
893
+ return ciphertext
894
+
895
+ def mix_column(self, block):
896
+ r"""
897
+ Return the matrix multiplication of ``block`` with a constant matrix.
898
+ The constant matrix is
899
+
900
+ .. MATH::
901
+
902
+ \begin{bmatrix}
903
+ x + 1 & x \\
904
+ x & x + 1
905
+ \end{bmatrix}
906
+
907
+ If the input block is
908
+
909
+ .. MATH::
910
+
911
+ \begin{bmatrix}
912
+ c_0 & c_2 \\
913
+ c_1 & c_3
914
+ \end{bmatrix}
915
+
916
+ then the output block is
917
+
918
+ .. MATH::
919
+
920
+ \begin{bmatrix}
921
+ d_0 & d_2 \\
922
+ d_1 & d_3
923
+ \end{bmatrix}
924
+ =
925
+ \begin{bmatrix}
926
+ x + 1 & x \\
927
+ x & x + 1
928
+ \end{bmatrix}
929
+ \begin{bmatrix}
930
+ c_0 & c_2 \\
931
+ c_1 & c_3
932
+ \end{bmatrix}
933
+
934
+ INPUT:
935
+
936
+ - ``block`` -- a `2 \times 2` matrix with entries over
937
+ `\GF{2^4}`
938
+
939
+ OUTPUT:
940
+
941
+ - A `2 \times 2` matrix resulting from multiplying the above constant
942
+ matrix with the input matrix ``block``.
943
+
944
+ EXAMPLES:
945
+
946
+ Here we work with elements of `\GF{2^4}`::
947
+
948
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
949
+ sage: maes = MiniAES()
950
+ sage: K = FiniteField(16, "x")
951
+ sage: MS = MatrixSpace(K, 2, 2)
952
+ sage: mat = MS([ [K("x^2 + x + 1"), K("x^3 + x^2 + 1")], [K("x^3"), K("x")] ])
953
+ sage: maes.mix_column(mat)
954
+ <BLANKLINE>
955
+ [ x^3 + x 0]
956
+ [ x^2 + 1 x^3 + x^2 + x + 1]
957
+
958
+ Multiplying by the identity matrix should leave the constant matrix
959
+ unchanged::
960
+
961
+ sage: eye = MS([ [K("1"), K("0")], [K("0"), K("1")] ])
962
+ sage: maes.mix_column(eye)
963
+ <BLANKLINE>
964
+ [x + 1 x]
965
+ [ x x + 1]
966
+
967
+ We can also work with binary strings::
968
+
969
+ sage: bin = BinaryStrings()
970
+ sage: B = bin.encoding("rT"); B
971
+ 0111001001010100
972
+ sage: B = MS(maes.binary_to_GF(B)); B
973
+ <BLANKLINE>
974
+ [x^2 + x + 1 x]
975
+ [ x^2 + 1 x^2]
976
+ sage: maes.mix_column(B)
977
+ <BLANKLINE>
978
+ [ x + 1 x^3 + x^2 + x]
979
+ [ 1 x^3]
980
+
981
+ We can also work with integers `n` such that `0 \leq n \leq 15`::
982
+
983
+ sage: P = [10, 5, 2, 7]; P
984
+ [10, 5, 2, 7]
985
+ sage: P = MS(maes.integer_to_GF(P)); P
986
+ <BLANKLINE>
987
+ [ x^3 + x x^2 + 1]
988
+ [ x x^2 + x + 1]
989
+ sage: maes.mix_column(P)
990
+ <BLANKLINE>
991
+ [x^3 + 1 1]
992
+ [ 1 x + 1]
993
+
994
+ TESTS:
995
+
996
+ The input block must be a matrix::
997
+
998
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
999
+ sage: maes = MiniAES()
1000
+ sage: maes.mix_column("mat")
1001
+ Traceback (most recent call last):
1002
+ ...
1003
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
1004
+
1005
+ In addition, the dimensions of the input matrix must be `2 \times 2`::
1006
+
1007
+ sage: K = FiniteField(16, "x")
1008
+ sage: MS = MatrixSpace(K, 1, 2)
1009
+ sage: mat = MS([[K("x^3 + x^2 + x + 1"), K("0")]])
1010
+ sage: maes.mix_column(mat)
1011
+ Traceback (most recent call last):
1012
+ ...
1013
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
1014
+ """
1015
+ if not isinstance(block, Matrix_dense) or \
1016
+ not (block.base_ring().order() == 16 and block.base_ring().is_field()):
1017
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
1018
+ if not (block.nrows() == block.ncols() == 2):
1019
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
1020
+
1021
+ K = FiniteField(self._key_size, "x")
1022
+ MS = MatrixSpace(K, 2, 2)
1023
+ M = MS( [ [K("x + 1"), K("x")],
1024
+ [K("x"), K("x + 1")] ] )
1025
+ return M * block
1026
+
1027
+ def nibble_sub(self, block, algorithm='encrypt'):
1028
+ r"""
1029
+ Substitute a nibble (or a block of 4 bits) using the following S-box:
1030
+
1031
+ .. MATH::
1032
+
1033
+ \begin{tabular}{ll|ll} \hline
1034
+ Input & Output & Input & Output \\\hline
1035
+ 0000 & 1110 & 1000 & 0011 \\
1036
+ 0001 & 0100 & 1001 & 1010 \\
1037
+ 0010 & 1101 & 1010 & 0110 \\
1038
+ 0011 & 0001 & 1011 & 1100 \\
1039
+ 0100 & 0010 & 1100 & 0101 \\
1040
+ 0101 & 1111 & 1101 & 1001 \\
1041
+ 0110 & 1011 & 1110 & 0000 \\
1042
+ 0111 & 1000 & 1111 & 0111 \\\hline
1043
+ \end{tabular}
1044
+
1045
+ The values in the above S-box are taken from the first row of the first
1046
+ S-box of the Data Encryption Standard (DES). Each nibble can be
1047
+ thought of as an element of the finite field `\GF{2^4}` of 16
1048
+ elements. Thus in terms of `\GF{2^4}`, the S-box can also be
1049
+ specified as:
1050
+
1051
+ .. MATH::
1052
+
1053
+ \begin{tabular}{ll} \hline
1054
+ Input & Output \\\hline
1055
+ $0$ & $x^3 + x^2 + x$ \\
1056
+ $1$ & $x^2$ \\
1057
+ $x$ & $x^3 + x^2 + 1$ \\
1058
+ $x + 1$ & $1$ \\
1059
+ $x^2$ & $x$ \\
1060
+ $x^2 + 1$ & $x^3 + x^2 + x + 1$ \\
1061
+ $x^2 + x$ & $x^3 + x + 1$ \\
1062
+ $x^2 + x + 1$ & $x^3$ \\
1063
+ $x^3$ & $x + 1$ \\
1064
+ $x^3 + 1$ & $x^3 + x$ \\
1065
+ $x^3 + x$ & $x^2 + x$ \\
1066
+ $x^3 + x + 1$ & $x^3 + x^2$ \\
1067
+ $x^3 + x^2$ & $x^2 + 1$ \\
1068
+ $x^3 + x^2 + 1$ & $x^3 + 1$ \\
1069
+ $x^3 + x^2 + x$ & $0$ \\
1070
+ $x^3 + x^2 + x + 1$ & $x^2 + x + 1$ \\\hline
1071
+ \end{tabular}
1072
+
1073
+ Note that the above S-box is used for encryption. The S-box for
1074
+ decryption is obtained from the above S-box by reversing the role of
1075
+ the Input and Output columns. Thus the previous Input column for
1076
+ encryption now becomes the Output column for decryption, and the
1077
+ previous Output column for encryption is now the Input column for
1078
+ decryption. The S-box used for decryption can be specified as:
1079
+
1080
+ .. MATH::
1081
+
1082
+ \begin{tabular}{ll} \hline
1083
+ Input & Output \\\hline
1084
+ $0$ & $x^3 + x^2 + x$ \\
1085
+ $1$ & $x + 1$ \\
1086
+ $x$ & $x^2$ \\
1087
+ $x + 1$ & $x^3$ \\
1088
+ $x^2$ & $1$ \\
1089
+ $x^2 + 1$ & $x^3 + x^2$ \\
1090
+ $x^2 + x$ & $x^3 + x$ \\
1091
+ $x^2 + x + 1$ & $x^3 + x^2 + x + 1$ \\
1092
+ $x^3$ & $x^2 + x + 1$ \\
1093
+ $x^3 + 1$ & $x^3 + x^2 + 1$ \\
1094
+ $x^3 + x$ & $x^3 + 1$ \\
1095
+ $x^3 + x + 1$ & $x^2 + x$ \\
1096
+ $x^3 + x^2$ & $x^3 + x + 1$ \\
1097
+ $x^3 + x^2 + 1$ & $x$ \\
1098
+ $x^3 + x^2 + x$ & $0$ \\
1099
+ $x^3 + x^2 + x + 1$ & $x^2 + 1$ \\\hline
1100
+ \end{tabular}
1101
+
1102
+ INPUT:
1103
+
1104
+ - ``block`` -- a `2 \times 2` matrix with entries over
1105
+ `\GF{2^4}`
1106
+
1107
+ - ``algorithm`` -- (default: ``'encrypt'``) a string; a flag to signify
1108
+ whether this nibble-sub operation is used for encryption or
1109
+ decryption. The encryption flag is ``'encrypt'`` and the decryption
1110
+ flag is ``'decrypt'``.
1111
+
1112
+ OUTPUT: a `2 \times 2` matrix resulting from applying an S-box on
1113
+ entries of the `2 \times 2` matrix ``block``.
1114
+
1115
+ EXAMPLES:
1116
+
1117
+ Here we work with elements of the finite field `\GF{2^4}`::
1118
+
1119
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1120
+ sage: maes = MiniAES()
1121
+ sage: K = FiniteField(16, "x")
1122
+ sage: MS = MatrixSpace(K, 2, 2)
1123
+ sage: mat = MS([[K("x^3 + x^2 + x + 1"), K("0")], [K("x^2 + x + 1"), K("x^3 + x")]])
1124
+ sage: maes.nibble_sub(mat, algorithm='encrypt')
1125
+ <BLANKLINE>
1126
+ [ x^2 + x + 1 x^3 + x^2 + x]
1127
+ [ x^3 x^2 + x]
1128
+
1129
+ But we can also work with binary strings::
1130
+
1131
+ sage: bin = BinaryStrings()
1132
+ sage: B = bin.encoding("bi"); B
1133
+ 0110001001101001
1134
+ sage: B = MS(maes.binary_to_GF(B)); B
1135
+ <BLANKLINE>
1136
+ [x^2 + x x]
1137
+ [x^2 + x x^3 + 1]
1138
+ sage: maes.nibble_sub(B, algorithm='encrypt')
1139
+ <BLANKLINE>
1140
+ [ x^3 + x + 1 x^3 + x^2 + 1]
1141
+ [ x^3 + x + 1 x^3 + x]
1142
+ sage: maes.nibble_sub(B, algorithm='decrypt')
1143
+ <BLANKLINE>
1144
+ [ x^3 + x x^2]
1145
+ [ x^3 + x x^3 + x^2 + 1]
1146
+
1147
+ Here we work with integers `n` such that `0 \leq n \leq 15`::
1148
+
1149
+ sage: P = [2, 6, 8, 14]; P
1150
+ [2, 6, 8, 14]
1151
+ sage: P = MS(maes.integer_to_GF(P)); P
1152
+ <BLANKLINE>
1153
+ [ x x^2 + x]
1154
+ [ x^3 x^3 + x^2 + x]
1155
+ sage: maes.nibble_sub(P, algorithm='encrypt')
1156
+ <BLANKLINE>
1157
+ [x^3 + x^2 + 1 x^3 + x + 1]
1158
+ [ x + 1 0]
1159
+ sage: maes.nibble_sub(P, algorithm='decrypt')
1160
+ <BLANKLINE>
1161
+ [ x^2 x^3 + x]
1162
+ [x^2 + x + 1 0]
1163
+
1164
+ TESTS:
1165
+
1166
+ The input block must be a matrix::
1167
+
1168
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1169
+ sage: maes = MiniAES()
1170
+ sage: maes.nibble_sub("mat")
1171
+ Traceback (most recent call last):
1172
+ ...
1173
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
1174
+
1175
+ In addition, the dimensions of the input matrix must be `2 \times 2`::
1176
+
1177
+ sage: K = FiniteField(16, "x")
1178
+ sage: MS = MatrixSpace(K, 1, 2)
1179
+ sage: mat = MS([[K("x^3 + x^2 + x + 1"), K("0")]])
1180
+ sage: maes.nibble_sub(mat)
1181
+ Traceback (most recent call last):
1182
+ ...
1183
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
1184
+
1185
+ The value for the option ``algorithm`` must be either the string
1186
+ ``'encrypt'`` or ``'decrypt'``::
1187
+
1188
+ sage: K = FiniteField(16, "x")
1189
+ sage: MS = MatrixSpace(K, 2, 2)
1190
+ sage: mat = MS([[K("x^3 + x^2 + x + 1"), K("0")], [K("x^2 + x + 1"), K("x^3 + x")]])
1191
+ sage: maes.nibble_sub(mat, algorithm='abc')
1192
+ Traceback (most recent call last):
1193
+ ...
1194
+ ValueError: the algorithm for nibble-sub must be either 'encrypt' or 'decrypt'
1195
+ sage: maes.nibble_sub(mat, algorithm='e')
1196
+ Traceback (most recent call last):
1197
+ ...
1198
+ ValueError: the algorithm for nibble-sub must be either 'encrypt' or 'decrypt'
1199
+ sage: maes.nibble_sub(mat, algorithm='d')
1200
+ Traceback (most recent call last):
1201
+ ...
1202
+ ValueError: the algorithm for nibble-sub must be either 'encrypt' or 'decrypt'
1203
+ """
1204
+ if not isinstance(block, Matrix_dense) or \
1205
+ not (block.base_ring().order() == 16 and block.base_ring().is_field()):
1206
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
1207
+ if not (block.nrows() == block.ncols() == 2):
1208
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
1209
+
1210
+ MS = MatrixSpace(FiniteField(self._key_size, "x"), 2, 2)
1211
+ # get the integer representation of each GF(2^4) element
1212
+ # in the input matrix block
1213
+ lst = [self._GF_to_int[block[i][j]] for i in range(block.nrows()) for j in range(block.ncols())]
1214
+ if algorithm == "encrypt":
1215
+ # Now run each resulting integer through the S-box for
1216
+ # encryption. Then convert the result output by the S-box
1217
+ # to an element of GF(2^4).
1218
+ return MS([self._int_to_GF[self._sboxE[e]] for e in lst])
1219
+ elif algorithm == "decrypt":
1220
+ # Now run each resulting integer through the S-box for
1221
+ # decryption. Then convert the result output by the S-box
1222
+ # to an element of GF(2^4).
1223
+ return MS([self._int_to_GF[self._sboxD[e]] for e in lst])
1224
+ else:
1225
+ raise ValueError("the algorithm for nibble-sub must be either 'encrypt' or 'decrypt'")
1226
+
1227
+ def random_key(self):
1228
+ r"""
1229
+ A random key within the key space of this Mini-AES block cipher. Like
1230
+ the AES, Phan's Mini-AES is a symmetric-key block cipher. A Mini-AES
1231
+ key is a block of 16 bits, or a `2 \times 2` matrix with entries over
1232
+ the finite field `\GF{2^4}`. Thus the number of possible keys is
1233
+ `2^{16} = 16^4`.
1234
+
1235
+ OUTPUT:
1236
+
1237
+ - A `2 \times 2` matrix over the finite field `\GF{2^4}`, used
1238
+ as a secret key for this Mini-AES block cipher.
1239
+
1240
+ EXAMPLES:
1241
+
1242
+ Each nibble of a key is an element of the finite field
1243
+ `\GF{2^4}`::
1244
+
1245
+ sage: K = FiniteField(16, "x")
1246
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1247
+ sage: maes = MiniAES()
1248
+ sage: key = maes.random_key()
1249
+ sage: [key[i][j] in K for i in range(key.nrows()) for j in range(key.ncols())]
1250
+ [True, True, True, True]
1251
+
1252
+ Generate a random key, then perform encryption and decryption using
1253
+ that key::
1254
+
1255
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1256
+ sage: maes = MiniAES()
1257
+ sage: K = FiniteField(16, "x")
1258
+ sage: MS = MatrixSpace(K, 2, 2)
1259
+ sage: key = maes.random_key()
1260
+ sage: P = MS.random_element()
1261
+ sage: C = maes.encrypt(P, key)
1262
+ sage: plaintxt = maes.decrypt(C, key)
1263
+ sage: plaintxt == P
1264
+ True
1265
+ """
1266
+ MS = MatrixSpace(FiniteField(16, "x"), 2, 2)
1267
+ return MS.random_element()
1268
+
1269
+ def round_key(self, key, n):
1270
+ r"""
1271
+ Return the round key for round ``n``. Phan's Mini-AES is defined to
1272
+ have two rounds. The round key `K_0` is generated and used prior to
1273
+ the first round, with round keys `K_1` and `K_2` being used in rounds
1274
+ 1 and 2 respectively. In total, there are three round keys, each
1275
+ generated from the secret key ``key``.
1276
+
1277
+ INPUT:
1278
+
1279
+ - ``key`` -- the secret key
1280
+
1281
+ - ``n`` -- nonnegative integer; the round number
1282
+
1283
+ OUTPUT: the `n`-th round key
1284
+
1285
+ EXAMPLES:
1286
+
1287
+ Obtaining the round keys from the secret key::
1288
+
1289
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1290
+ sage: maes = MiniAES()
1291
+ sage: K = FiniteField(16, "x")
1292
+ sage: MS = MatrixSpace(K, 2, 2)
1293
+ sage: key = MS([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ])
1294
+ sage: maes.round_key(key, 0)
1295
+ <BLANKLINE>
1296
+ [ x^3 + x^2 x^3 + x^2 + x + 1]
1297
+ [ x + 1 0]
1298
+ sage: key
1299
+ <BLANKLINE>
1300
+ [ x^3 + x^2 x^3 + x^2 + x + 1]
1301
+ [ x + 1 0]
1302
+ sage: maes.round_key(key, 1)
1303
+ [x^3 + x x^2 + x]
1304
+ [x^3 + 1 x^2 + x]
1305
+ sage: maes.round_key(key, 2)
1306
+ <BLANKLINE>
1307
+ [ x^2 + 1 x^3 + x]
1308
+ [x^3 + x^2 x^3 + x^2]
1309
+
1310
+ TESTS:
1311
+
1312
+ Only two rounds are defined for this AES variant::
1313
+
1314
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1315
+ sage: maes = MiniAES()
1316
+ sage: K = FiniteField(16, "x")
1317
+ sage: MS = MatrixSpace(K, 2, 2)
1318
+ sage: key = MS([ [K("x^3 + x^2"), K("x^3 + x^2 + x + 1")], [K("x + 1"), K("0")] ])
1319
+ sage: maes.round_key(key, -1)
1320
+ Traceback (most recent call last):
1321
+ ...
1322
+ ValueError: Mini-AES only defines two rounds
1323
+ sage: maes.round_key(key, 3)
1324
+ Traceback (most recent call last):
1325
+ ...
1326
+ ValueError: Mini-AES only defines two rounds
1327
+
1328
+ The input key must be a matrix::
1329
+
1330
+ sage: maes.round_key("key", 0)
1331
+ Traceback (most recent call last):
1332
+ ...
1333
+ TypeError: secret key must be a 2 x 2 matrix over GF(16)
1334
+
1335
+ In addition, the dimensions of the key matrix must be `2 \times 2`::
1336
+
1337
+ sage: K = FiniteField(16, "x")
1338
+ sage: MS = MatrixSpace(K, 1, 2)
1339
+ sage: key = MS([[K("x^3 + x^2 + x + 1"), K("0")]])
1340
+ sage: maes.round_key(key, 2)
1341
+ Traceback (most recent call last):
1342
+ ...
1343
+ TypeError: secret key must be a 2 x 2 matrix over GF(16)
1344
+ """
1345
+ if not isinstance(key, Matrix_dense) or \
1346
+ not (key.base_ring().order() == 16 and key.base_ring().is_field()):
1347
+ raise TypeError("secret key must be a 2 x 2 matrix over GF(16)")
1348
+ if not (key.nrows() == key.ncols() == 2):
1349
+ raise TypeError("secret key must be a 2 x 2 matrix over GF(16)")
1350
+
1351
+ K = FiniteField(self._key_size, "x")
1352
+ MS = MatrixSpace(K, 2, 2)
1353
+ # round 0
1354
+ if n == 0:
1355
+ return key
1356
+ # round 1
1357
+ if n == 1:
1358
+ round_constant_1 = K("1")
1359
+ w4 = key[0][0] + self._sboxE[key[1][1]] + round_constant_1
1360
+ w5 = key[1][0] + w4
1361
+ w6 = key[0][1] + w5
1362
+ w7 = key[1][1] + w6
1363
+ return MS([ [w4, w6], [w5, w7] ])
1364
+ # round 2
1365
+ if n == 2:
1366
+ round_constant_2 = K("x")
1367
+ key1 = self.round_key(key, 1)
1368
+ w8 = key1[0][0] + self._sboxE[key1[1][1]] + round_constant_2
1369
+ w9 = key1[1][0] + w8
1370
+ w10 = key1[0][1] + w9
1371
+ w11 = key1[1][1] + w10
1372
+ return MS([ [w8, w10], [w9, w11] ])
1373
+ # unsupported round number
1374
+ if (n < 0) or (n > 2):
1375
+ raise ValueError("Mini-AES only defines two rounds")
1376
+
1377
+ def sbox(self):
1378
+ r"""
1379
+ Return the S-box of Mini-AES.
1380
+
1381
+ EXAMPLES::
1382
+
1383
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1384
+ sage: maes = MiniAES()
1385
+ sage: maes.sbox()
1386
+ (14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7)
1387
+ """
1388
+ return self._sboxE
1389
+
1390
+ def shift_row(self, block):
1391
+ r"""
1392
+ Rotate each row of ``block`` to the left by different nibble
1393
+ amounts. The first or zero-th row is left unchanged, while the
1394
+ second or row one is rotated left by one nibble. This has the effect
1395
+ of only interchanging the nibbles in the second row. Let
1396
+ `b_0, b_1, b_2, b_3` be four nibbles arranged as the following
1397
+ `2 \times 2` matrix
1398
+
1399
+ .. MATH::
1400
+
1401
+ \begin{bmatrix}
1402
+ b_0 & b_2 \\
1403
+ b_1 & b_3
1404
+ \end{bmatrix}
1405
+
1406
+ Then the operation of shift-row is the mapping
1407
+
1408
+ .. MATH::
1409
+
1410
+ \begin{bmatrix}
1411
+ b_0 & b_2 \\
1412
+ b_1 & b_3
1413
+ \end{bmatrix}
1414
+ \longmapsto
1415
+ \begin{bmatrix}
1416
+ b_0 & b_2 \\
1417
+ b_3 & b_1
1418
+ \end{bmatrix}
1419
+
1420
+ INPUT:
1421
+
1422
+ - ``block`` -- a `2 \times 2` matrix with entries over
1423
+ `\GF{2^4}`
1424
+
1425
+ OUTPUT: a `2 \times 2` matrix resulting from applying shift-row on ``block``
1426
+
1427
+ EXAMPLES:
1428
+
1429
+ Here we work with elements of the finite field `\GF{2^4}`::
1430
+
1431
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1432
+ sage: maes = MiniAES()
1433
+ sage: K = FiniteField(16, "x")
1434
+ sage: MS = MatrixSpace(K, 2, 2)
1435
+ sage: mat = MS([[K("x^3 + x^2 + x + 1"), K("0")], [K("x^2 + x + 1"), K("x^3 + x")]])
1436
+ sage: maes.shift_row(mat)
1437
+ <BLANKLINE>
1438
+ [x^3 + x^2 + x + 1 0]
1439
+ [ x^3 + x x^2 + x + 1]
1440
+ sage: mat
1441
+ <BLANKLINE>
1442
+ [x^3 + x^2 + x + 1 0]
1443
+ [ x^2 + x + 1 x^3 + x]
1444
+
1445
+ But we can also work with binary strings::
1446
+
1447
+ sage: bin = BinaryStrings()
1448
+ sage: B = bin.encoding("Qt"); B
1449
+ 0101000101110100
1450
+ sage: B = MS(maes.binary_to_GF(B)); B
1451
+ <BLANKLINE>
1452
+ [ x^2 + 1 1]
1453
+ [x^2 + x + 1 x^2]
1454
+ sage: maes.shift_row(B)
1455
+ <BLANKLINE>
1456
+ [ x^2 + 1 1]
1457
+ [ x^2 x^2 + x + 1]
1458
+
1459
+ Here we work with integers `n` such that `0 \leq n \leq 15`::
1460
+
1461
+ sage: P = [3, 6, 9, 12]; P
1462
+ [3, 6, 9, 12]
1463
+ sage: P = MS(maes.integer_to_GF(P)); P
1464
+ <BLANKLINE>
1465
+ [ x + 1 x^2 + x]
1466
+ [ x^3 + 1 x^3 + x^2]
1467
+ sage: maes.shift_row(P)
1468
+ <BLANKLINE>
1469
+ [ x + 1 x^2 + x]
1470
+ [x^3 + x^2 x^3 + 1]
1471
+
1472
+ TESTS:
1473
+
1474
+ The input block must be a matrix::
1475
+
1476
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1477
+ sage: maes = MiniAES()
1478
+ sage: maes.shift_row("block")
1479
+ Traceback (most recent call last):
1480
+ ...
1481
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
1482
+
1483
+ In addition, the dimensions of the input matrix must be `2 \times 2`::
1484
+
1485
+ sage: K = FiniteField(16, "x")
1486
+ sage: MS = MatrixSpace(K, 1, 2)
1487
+ sage: mat = MS([[K("x^3 + x^2 + x + 1"), K("0")]])
1488
+ sage: maes.shift_row(mat)
1489
+ Traceback (most recent call last):
1490
+ ...
1491
+ TypeError: input block must be a 2 x 2 matrix over GF(16)
1492
+ """
1493
+ if not isinstance(block, Matrix_dense) or \
1494
+ not (block.base_ring().order() == 16 and block.base_ring().is_field()):
1495
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
1496
+ if not (block.nrows() == block.ncols() == 2):
1497
+ raise TypeError("input block must be a 2 x 2 matrix over GF(16)")
1498
+
1499
+ MS = MatrixSpace(FiniteField(self._key_size, "x"), 2, 2)
1500
+ mat = MS([ [block[0][0], block[0][1]],
1501
+ [block[1][1], block[1][0]] ] )
1502
+ return mat
1503
+
1504
+ ### conversion functions to convert between different data formats
1505
+
1506
+ def GF_to_binary(self, G):
1507
+ r"""
1508
+ Return the binary representation of ``G``.
1509
+ If ``G`` is an element of the finite field `\GF{2^4}`, then
1510
+ obtain the binary representation of ``G``. If ``G`` is a list of
1511
+ elements belonging to `\GF{2^4}`, obtain the 4-bit
1512
+ representation of each element of the list, then concatenate the
1513
+ resulting 4-bit strings into a binary string. If ``G`` is a matrix
1514
+ with entries over `\GF{2^4}`, convert each matrix entry to its
1515
+ 4-bit representation, then concatenate the 4-bit strings. The
1516
+ concatenation is performed starting from the top-left corner of the
1517
+ matrix, working across left to right, top to bottom. Each element of
1518
+ `\GF{2^4}` can be associated with a unique 4-bit string
1519
+ according to the following table:
1520
+
1521
+ .. MATH::
1522
+
1523
+ \begin{tabular}{ll|ll} \hline
1524
+ 4-bit string & $\GF{2^4}$ & 4-bit string & $\GF{2^4}$ \\\hline
1525
+ 0000 & $0$ & 1000 & $x^3$ \\
1526
+ 0001 & $1$ & 1001 & $x^3 + 1$ \\
1527
+ 0010 & $x$ & 1010 & $x^3 + x$ \\
1528
+ 0011 & $x + 1$ & 1011 & $x^3 + x + 1$ \\
1529
+ 0100 & $x^2$ & 1100 & $x^3 + x^2$ \\
1530
+ 0101 & $x^2 + 1$ & 1101 & $x^3 + x^2 + 1$ \\
1531
+ 0110 & $x^2 + x$ & 1110 & $x^3 + x^2 + x$ \\
1532
+ 0111 & $x^2 + x + 1$ & 1111 & $x^3 + x^2 + x+ 1$ \\\hline
1533
+ \end{tabular}
1534
+
1535
+ INPUT:
1536
+
1537
+ - ``G`` -- an element of `\GF{2^4}`, a list of elements of
1538
+ `\GF{2^4}`, or a matrix over `\GF{2^4}`
1539
+
1540
+ OUTPUT: a binary string representation of ``G``
1541
+
1542
+ EXAMPLES:
1543
+
1544
+ Obtain the binary representation of all elements of `\GF{2^4}`::
1545
+
1546
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1547
+ sage: maes = MiniAES()
1548
+ sage: K = FiniteField(16, "x")
1549
+ sage: S = Set(K); len(S) # GF(2^4) has this many elements
1550
+ 16
1551
+ sage: [maes.GF_to_binary(S[i]) for i in range(len(S))]
1552
+ <BLANKLINE>
1553
+ [0000,
1554
+ 0001,
1555
+ 0010,
1556
+ 0011,
1557
+ 0100,
1558
+ 0101,
1559
+ 0110,
1560
+ 0111,
1561
+ 1000,
1562
+ 1001,
1563
+ 1010,
1564
+ 1011,
1565
+ 1100,
1566
+ 1101,
1567
+ 1110,
1568
+ 1111]
1569
+
1570
+ The binary representation of a list of elements belonging to
1571
+ `\GF{2^4}`::
1572
+
1573
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1574
+ sage: maes = MiniAES()
1575
+ sage: K = FiniteField(16, "x")
1576
+ sage: G = [K("x^2 + x + 1"), K("x^3 + x^2"), K("x"), K("x^3 + x + 1"), K("x^3 + x^2 + x + 1"), K("x^2 + x"), K("1"), K("x^2 + x + 1")]
1577
+ sage: maes.GF_to_binary(G)
1578
+ 01111100001010111111011000010111
1579
+
1580
+ The binary representation of a matrix over `\GF{2^4}`::
1581
+
1582
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1583
+ sage: maes = MiniAES()
1584
+ sage: K = FiniteField(16, "x")
1585
+ sage: MS = MatrixSpace(K, 2, 2)
1586
+ sage: G = MS([K("x^3 + x^2"), K("x + 1"), K("x^2 + x + 1"), K("x^3 + x^2 + x")]); G
1587
+ <BLANKLINE>
1588
+ [ x^3 + x^2 x + 1]
1589
+ [ x^2 + x + 1 x^3 + x^2 + x]
1590
+ sage: maes.GF_to_binary(G)
1591
+ 1100001101111110
1592
+ sage: MS = MatrixSpace(K, 2, 4)
1593
+ sage: G = MS([K("x^2 + x + 1"), K("x^3 + x^2"), K("x"), K("x^3 + x + 1"), K("x^3 + x^2 + x + 1"), K("x^2 + x"), K("1"), K("x^2 + x + 1")]); G
1594
+ <BLANKLINE>
1595
+ [ x^2 + x + 1 x^3 + x^2 x x^3 + x + 1]
1596
+ [x^3 + x^2 + x + 1 x^2 + x 1 x^2 + x + 1]
1597
+ sage: maes.GF_to_binary(G)
1598
+ 01111100001010111111011000010111
1599
+
1600
+ TESTS:
1601
+
1602
+ Input must be an element of `\GF{2^4}`::
1603
+
1604
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1605
+ sage: maes = MiniAES()
1606
+ sage: K = FiniteField(8, "x")
1607
+ sage: G = K.random_element()
1608
+ sage: maes.GF_to_binary(G)
1609
+ Traceback (most recent call last):
1610
+ ...
1611
+ TypeError: input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)
1612
+
1613
+ A list of elements belonging to `\GF{2^4}`::
1614
+
1615
+ sage: maes.GF_to_binary([])
1616
+ Traceback (most recent call last):
1617
+ ...
1618
+ ValueError: input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)
1619
+ sage: G = [K.random_element() for i in range(5)]
1620
+ sage: maes.GF_to_binary(G)
1621
+ Traceback (most recent call last):
1622
+ ...
1623
+ KeyError:...
1624
+
1625
+ A matrix over `\GF{2^4}`::
1626
+
1627
+ sage: MS = MatrixSpace(FiniteField(7, "x"), 4, 5)
1628
+ sage: maes.GF_to_binary(MS.random_element())
1629
+ Traceback (most recent call last):
1630
+ ...
1631
+ TypeError: input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)
1632
+ """
1633
+ B = BinaryStrings()
1634
+ K = FiniteField(self._key_size, "x")
1635
+ # G is an element over GF(16)
1636
+ if G in K:
1637
+ return self._GF_to_bin[G]
1638
+ # G is a list of elements over GF(16)
1639
+ elif isinstance(G, list):
1640
+ if len(G) == 0:
1641
+ raise ValueError("input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)")
1642
+ S = "".join(str(self._GF_to_bin[g]) for g in G)
1643
+ return B(S)
1644
+ # G is a matrix over GF(16)
1645
+ elif isinstance(G, Matrix_dense):
1646
+ if G.base_ring() is not K:
1647
+ raise TypeError("input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)")
1648
+ S = "".join(str(self._GF_to_bin[G[i][j]])
1649
+ for i in range(G.nrows()) for j in range(G.ncols()))
1650
+ return B(S)
1651
+ # the type of G doesn't match the supported types
1652
+ else:
1653
+ raise TypeError("input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)")
1654
+
1655
+ def GF_to_integer(self, G):
1656
+ r"""
1657
+ Return the integer representation of the finite field element ``G``.
1658
+ If ``G`` is an element of the finite field `\GF{2^4}`, then
1659
+ obtain the integer representation of ``G``. If ``G`` is a list of
1660
+ elements belonging to `\GF{2^4}`, obtain the integer
1661
+ representation of each element of the list, and return the result
1662
+ as a list of integers. If ``G`` is a matrix with entries over
1663
+ `\GF{2^4}`, convert each matrix entry to its integer representation,
1664
+ and return the result as a list of integers. The resulting list is
1665
+ obtained by starting from the top-left corner of the matrix, working
1666
+ across left to right, top to bottom. Each element of `\GF{2^4}` can
1667
+ be associated with a unique integer according to the following table:
1668
+
1669
+ .. MATH::
1670
+
1671
+ \begin{tabular}{ll|ll} \hline
1672
+ integer & $\GF{2^4}$ & integer & $\GF{2^4}$ \\\hline
1673
+ 0 & $0$ & 8 & $x^3$ \\
1674
+ 1 & $1$ & 9 & $x^3 + 1$ \\
1675
+ 2 & $x$ & 10 & $x^3 + x$ \\
1676
+ 3 & $x + 1$ & 11 & $x^3 + x + 1$ \\
1677
+ 4 & $x^2$ & 12 & $x^3 + x^2$ \\
1678
+ 5 & $x^2 + 1$ & 13 & $x^3 + x^2 + 1$ \\
1679
+ 6 & $x^2 + x$ & 14 & $x^3 + x^2 + x$ \\
1680
+ 7 & $x^2 + x + 1$ & 15 & $x^3 + x^2 + x+ 1$ \\\hline
1681
+ \end{tabular}
1682
+
1683
+ INPUT:
1684
+
1685
+ - ``G`` -- an element of `\GF{2^4}`, a list of elements belonging to
1686
+ `\GF{2^4}`, or a matrix over `\GF{2^4}`
1687
+
1688
+ OUTPUT: the integer representation of ``G``
1689
+
1690
+ EXAMPLES:
1691
+
1692
+ Obtain the integer representation of all elements of `\GF{2^4}`::
1693
+
1694
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1695
+ sage: maes = MiniAES()
1696
+ sage: K = FiniteField(16, "x")
1697
+ sage: S = Set(K); len(S) # GF(2^4) has this many elements
1698
+ 16
1699
+ sage: [maes.GF_to_integer(S[i]) for i in range(len(S))]
1700
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
1701
+
1702
+ The integer representation of a list of elements belonging to
1703
+ `\GF{2^4}`::
1704
+
1705
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1706
+ sage: maes = MiniAES()
1707
+ sage: K = FiniteField(16, "x")
1708
+ sage: G = [K("x^2 + x + 1"), K("x^3 + x^2"), K("x"), K("x^3 + x + 1"), K("x^3 + x^2 + x + 1"), K("x^2 + x"), K("1"), K("x^2 + x + 1")]
1709
+ sage: maes.GF_to_integer(G)
1710
+ [7, 12, 2, 11, 15, 6, 1, 7]
1711
+
1712
+ The integer representation of a matrix over `\GF{2^4}`::
1713
+
1714
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1715
+ sage: maes = MiniAES()
1716
+ sage: K = FiniteField(16, "x")
1717
+ sage: MS = MatrixSpace(K, 2, 2)
1718
+ sage: G = MS([K("x^3 + x^2"), K("x + 1"), K("x^2 + x + 1"), K("x^3 + x^2 + x")]); G
1719
+ <BLANKLINE>
1720
+ [ x^3 + x^2 x + 1]
1721
+ [ x^2 + x + 1 x^3 + x^2 + x]
1722
+ sage: maes.GF_to_integer(G)
1723
+ [12, 3, 7, 14]
1724
+ sage: MS = MatrixSpace(K, 2, 4)
1725
+ sage: G = MS([K("x^2 + x + 1"), K("x^3 + x^2"), K("x"), K("x^3 + x + 1"), K("x^3 + x^2 + x + 1"), K("x^2 + x"), K("1"), K("x^2 + x + 1")]); G
1726
+ <BLANKLINE>
1727
+ [ x^2 + x + 1 x^3 + x^2 x x^3 + x + 1]
1728
+ [x^3 + x^2 + x + 1 x^2 + x 1 x^2 + x + 1]
1729
+ sage: maes.GF_to_integer(G)
1730
+ [7, 12, 2, 11, 15, 6, 1, 7]
1731
+
1732
+ TESTS:
1733
+
1734
+ Input must be an element of `\GF{2^4}`::
1735
+
1736
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1737
+ sage: maes = MiniAES()
1738
+ sage: K = FiniteField(7, "x")
1739
+ sage: G = K.random_element()
1740
+ sage: maes.GF_to_integer(G)
1741
+ Traceback (most recent call last):
1742
+ ...
1743
+ TypeError: input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)
1744
+
1745
+ A list of elements belonging to `\GF{2^4}`::
1746
+
1747
+ sage: maes.GF_to_integer([])
1748
+ Traceback (most recent call last):
1749
+ ...
1750
+ ValueError: input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)
1751
+ sage: G = [K.random_element() for i in range(5)]
1752
+ sage: maes.GF_to_integer(G)
1753
+ Traceback (most recent call last):
1754
+ ...
1755
+ KeyError:...
1756
+
1757
+ A matrix over `\GF{2^4}`::
1758
+
1759
+ sage: MS = MatrixSpace(FiniteField(7, "x"), 4, 5)
1760
+ sage: maes.GF_to_integer(MS.random_element())
1761
+ Traceback (most recent call last):
1762
+ ...
1763
+ TypeError: input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)
1764
+ """
1765
+ K = FiniteField(self._key_size, "x")
1766
+ # G is an element over GF(16)
1767
+ if G in K:
1768
+ return self._GF_to_int[G]
1769
+ # G is a list of elements over GF(16)
1770
+ elif isinstance(G, list):
1771
+ if len(G) == 0:
1772
+ raise ValueError("input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)")
1773
+ return [self._GF_to_int[g] for g in G]
1774
+ # G is a matrix over GF(16)
1775
+ elif isinstance(G, Matrix_dense):
1776
+ if G.base_ring() is not K:
1777
+ raise TypeError("input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)")
1778
+ return [self._GF_to_int[G[i][j]] for i in range(G.nrows()) for j in range(G.ncols())]
1779
+ # the type of G doesn't match the supported types
1780
+ else:
1781
+ raise TypeError("input G must be an element of GF(16), a list of elements of GF(16), or a matrix over GF(16)")
1782
+
1783
+ def binary_to_GF(self, B):
1784
+ r"""
1785
+ Return a list of elements of `\GF{2^4}` that represents the
1786
+ binary string ``B``. The number of bits in ``B`` must be greater
1787
+ than zero and a multiple of 4. Each nibble (or 4-bit string) is
1788
+ uniquely associated with an element of `\GF{2^4}` as
1789
+ specified by the following table:
1790
+
1791
+ .. MATH::
1792
+
1793
+ \begin{tabular}{ll|ll} \hline
1794
+ 4-bit string & $\GF{2^4}$ & 4-bit string & $\GF{2^4}$ \\\hline
1795
+ 0000 & $0$ & 1000 & $x^3$ \\
1796
+ 0001 & $1$ & 1001 & $x^3 + 1$ \\
1797
+ 0010 & $x$ & 1010 & $x^3 + x$ \\
1798
+ 0011 & $x + 1$ & 1011 & $x^3 + x + 1$ \\
1799
+ 0100 & $x^2$ & 1100 & $x^3 + x^2$ \\
1800
+ 0101 & $x^2 + 1$ & 1101 & $x^3 + x^2 + 1$ \\
1801
+ 0110 & $x^2 + x$ & 1110 & $x^3 + x^2 + x$ \\
1802
+ 0111 & $x^2 + x + 1$ & 1111 & $x^3 + x^2 + x+ 1$ \\\hline
1803
+ \end{tabular}
1804
+
1805
+ INPUT:
1806
+
1807
+ - ``B`` -- a binary string, where the number of bits is positive and
1808
+ a multiple of 4
1809
+
1810
+ OUTPUT:
1811
+
1812
+ - A list of elements of the finite field `\GF{2^4}` that
1813
+ represent the binary string ``B``.
1814
+
1815
+ EXAMPLES:
1816
+
1817
+ Obtain all the elements of the finite field `\GF{2^4}`::
1818
+
1819
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1820
+ sage: maes = MiniAES()
1821
+ sage: bin = BinaryStrings()
1822
+ sage: B = bin("0000000100100011010001010110011110001001101010111100110111101111")
1823
+ sage: maes.binary_to_GF(B)
1824
+ <BLANKLINE>
1825
+ [0,
1826
+ 1,
1827
+ x,
1828
+ x + 1,
1829
+ x^2,
1830
+ x^2 + 1,
1831
+ x^2 + x,
1832
+ x^2 + x + 1,
1833
+ x^3,
1834
+ x^3 + 1,
1835
+ x^3 + x,
1836
+ x^3 + x + 1,
1837
+ x^3 + x^2,
1838
+ x^3 + x^2 + 1,
1839
+ x^3 + x^2 + x,
1840
+ x^3 + x^2 + x + 1]
1841
+
1842
+ TESTS:
1843
+
1844
+ The input ``B`` must be a non-empty binary string, where the number
1845
+ of bits is a multiple of 4::
1846
+
1847
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1848
+ sage: maes = MiniAES()
1849
+ sage: maes.binary_to_GF("")
1850
+ Traceback (most recent call last):
1851
+ ...
1852
+ ValueError: the number of bits in the binary string B must be positive and a multiple of 4
1853
+ sage: maes.binary_to_GF("101")
1854
+ Traceback (most recent call last):
1855
+ ...
1856
+ ValueError: the number of bits in the binary string B must be positive and a multiple of 4
1857
+ """
1858
+ from sage.rings.finite_rings.integer_mod import Mod
1859
+ bin = BinaryStrings()
1860
+ b = bin(B)
1861
+ # an empty string
1862
+ if len(b) == 0:
1863
+ raise ValueError("the number of bits in the binary string B must be positive and a multiple of 4")
1864
+ # a string with number of bits that is a multiple of 4
1865
+ if Mod(len(b), 4).lift() == 0:
1866
+ M = len(b) // 4 # the number of nibbles
1867
+ return [self._bin_to_GF[b[i*4 : (i+1)*4]] for i in range(M)]
1868
+ else:
1869
+ raise ValueError("the number of bits in the binary string B must be positive and a multiple of 4")
1870
+
1871
+ def binary_to_integer(self, B):
1872
+ r"""
1873
+ Return a list of integers representing the binary string ``B``. The
1874
+ number of bits in ``B`` must be greater than zero and a multiple of
1875
+ 4. Each nibble (or 4-bit string) is uniquely associated with an
1876
+ integer as specified by the following table:
1877
+
1878
+ .. MATH::
1879
+
1880
+ \begin{tabular}{ll|ll} \hline
1881
+ 4-bit string & integer & 4-bit string & integer \\\hline
1882
+ 0000 & 0 & 1000 & 8 \\
1883
+ 0001 & 1 & 1001 & 9 \\
1884
+ 0010 & 2 & 1010 & 10 \\
1885
+ 0011 & 3 & 1011 & 11 \\
1886
+ 0100 & 4 & 1100 & 12 \\
1887
+ 0101 & 5 & 1101 & 13 \\
1888
+ 0110 & 6 & 1110 & 14 \\
1889
+ 0111 & 7 & 1111 & 15 \\\hline
1890
+ \end{tabular}
1891
+
1892
+ INPUT:
1893
+
1894
+ - ``B`` -- a binary string, where the number of bits is positive and
1895
+ a multiple of 4
1896
+
1897
+ OUTPUT: list of integers that represent the binary string ``B``
1898
+
1899
+ EXAMPLES:
1900
+
1901
+ Obtain the integer representation of every 4-bit string::
1902
+
1903
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1904
+ sage: maes = MiniAES()
1905
+ sage: bin = BinaryStrings()
1906
+ sage: B = bin("0000000100100011010001010110011110001001101010111100110111101111")
1907
+ sage: maes.binary_to_integer(B)
1908
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
1909
+
1910
+ TESTS:
1911
+
1912
+ The input ``B`` must be a non-empty binary string, where the number
1913
+ of bits is a multiple of 4::
1914
+
1915
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1916
+ sage: maes = MiniAES()
1917
+ sage: maes.binary_to_integer("")
1918
+ Traceback (most recent call last):
1919
+ ...
1920
+ ValueError: the number of bits in the binary string B must be positive and a multiple of 4
1921
+ sage: maes.binary_to_integer("101")
1922
+ Traceback (most recent call last):
1923
+ ...
1924
+ ValueError: the number of bits in the binary string B must be positive and a multiple of 4
1925
+ """
1926
+ from sage.rings.finite_rings.integer_mod import Mod
1927
+ bin = BinaryStrings()
1928
+ b = bin(B)
1929
+ # an empty string
1930
+ if len(b) == 0:
1931
+ raise ValueError("the number of bits in the binary string B must be positive and a multiple of 4")
1932
+ # a string with number of bits that is a multiple of 4
1933
+ if Mod(len(b), 4).lift() == 0:
1934
+ M = len(b) // 4 # the number of nibbles
1935
+ return [self._bin_to_int[b[i*4 : (i+1)*4]] for i in range(M)]
1936
+ else:
1937
+ raise ValueError("the number of bits in the binary string B must be positive and a multiple of 4")
1938
+
1939
+ def integer_to_binary(self, N):
1940
+ r"""
1941
+ Return the binary representation of ``N``. If `N` is an integer such
1942
+ that `0 \leq N \leq 15`, return the binary representation of ``N``.
1943
+ If ``N`` is a list of integers each of which is `\geq 0` and
1944
+ `\leq 15`, then obtain the binary representation of each integer,
1945
+ and concatenate the individual binary representations into a single
1946
+ binary string. Each integer between 0 and 15, inclusive, can be
1947
+ associated with a unique 4-bit string according to the following
1948
+ table:
1949
+
1950
+ .. MATH::
1951
+
1952
+ \begin{tabular}{ll|ll} \hline
1953
+ 4-bit string & integer & 4-bit string & integer \\\hline
1954
+ 0000 & 0 & 1000 & 8 \\
1955
+ 0001 & 1 & 1001 & 9 \\
1956
+ 0010 & 2 & 1010 & 10 \\
1957
+ 0011 & 3 & 1011 & 11 \\
1958
+ 0100 & 4 & 1100 & 12 \\
1959
+ 0101 & 5 & 1101 & 13 \\
1960
+ 0110 & 6 & 1110 & 14 \\
1961
+ 0111 & 7 & 1111 & 15 \\\hline
1962
+ \end{tabular}
1963
+
1964
+ INPUT:
1965
+
1966
+ - ``N`` -- nonnegative integer less than or equal to 15, or a list
1967
+ of such integers
1968
+
1969
+ OUTPUT: a binary string representing ``N``
1970
+
1971
+ EXAMPLES:
1972
+
1973
+ The binary representations of all integers between 0 and
1974
+ 15, inclusive::
1975
+
1976
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1977
+ sage: maes = MiniAES()
1978
+ sage: lst = [n for n in range(16)]; lst
1979
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
1980
+ sage: maes.integer_to_binary(lst)
1981
+ 0000000100100011010001010110011110001001101010111100110111101111
1982
+
1983
+ The binary representation of an integer between 0 and 15,
1984
+ inclusive::
1985
+
1986
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
1987
+ sage: maes = MiniAES()
1988
+ sage: maes.integer_to_binary(3)
1989
+ 0011
1990
+ sage: maes.integer_to_binary(5)
1991
+ 0101
1992
+ sage: maes.integer_to_binary(7)
1993
+ 0111
1994
+
1995
+ TESTS:
1996
+
1997
+ The input ``N`` can be an integer, but must be bounded such that
1998
+ `0 \leq N \leq 15`::
1999
+
2000
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
2001
+ sage: maes = MiniAES()
2002
+ sage: maes.integer_to_binary(-1)
2003
+ Traceback (most recent call last):
2004
+ ...
2005
+ KeyError:...
2006
+ sage: maes.integer_to_binary("1")
2007
+ Traceback (most recent call last):
2008
+ ...
2009
+ TypeError: N must be an integer 0 <= N <= 15 or a list of such integers
2010
+ sage: maes.integer_to_binary("")
2011
+ Traceback (most recent call last):
2012
+ ...
2013
+ TypeError: N must be an integer 0 <= N <= 15 or a list of such integers
2014
+
2015
+ The input ``N`` can be a list of integers, but each integer `n` of
2016
+ the list must be `0 \leq n \leq 15`::
2017
+
2018
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
2019
+ sage: maes = MiniAES()
2020
+ sage: maes.integer_to_binary([])
2021
+ Traceback (most recent call last):
2022
+ ...
2023
+ ValueError: N must be an integer 0 <= N <= 15 or a list of such integers
2024
+ sage: maes.integer_to_binary([""])
2025
+ Traceback (most recent call last):
2026
+ ...
2027
+ KeyError:...
2028
+ sage: maes.integer_to_binary([0, 1, 2, 16])
2029
+ Traceback (most recent call last):
2030
+ ...
2031
+ KeyError:...
2032
+ """
2033
+ if isinstance(N, list):
2034
+ if len(N) == 0:
2035
+ raise ValueError("N must be an integer 0 <= N <= 15 or a list of such integers")
2036
+ bin = BinaryStrings()
2037
+ # Here, we assume that each element of the list is an integer n
2038
+ # such that 0 <= n <= 15. An error will be raised if otherwise.
2039
+ b = "".join(str(self._int_to_bin[n]) for n in N)
2040
+ return bin(b)
2041
+ elif isinstance(N, Integer):
2042
+ # Here, we assume that N is an integer such that 0 <= n <= 15.
2043
+ # An error will be raised if otherwise.
2044
+ return self._int_to_bin[N]
2045
+ else:
2046
+ raise TypeError("N must be an integer 0 <= N <= 15 or a list of such integers")
2047
+
2048
+ def integer_to_GF(self, N):
2049
+ r"""
2050
+ Return the finite field representation of ``N``. If `N` is an
2051
+ integer such that `0 \leq N \leq 15`, return the element of
2052
+ `\GF{2^4}` that represents ``N``. If ``N`` is a list of integers
2053
+ each of which is `\geq 0` and `\leq 15`, then obtain the element
2054
+ of `\GF{2^4}` that represents each such integer, and return a list
2055
+ of such finite field representations. Each integer between 0 and 15,
2056
+ inclusive, can be associated with a unique element of `\GF{2^4}`
2057
+ according to the following table:
2058
+
2059
+ .. MATH::
2060
+
2061
+ \begin{tabular}{ll|ll} \hline
2062
+ integer & $\GF{2^4}$ & integer & $\GF{2^4}$ \\\hline
2063
+ 0 & $0$ & 8 & $x^3$ \\
2064
+ 1 & $1$ & 9 & $x^3 + 1$ \\
2065
+ 2 & $x$ & 10 & $x^3 + x$ \\
2066
+ 3 & $x + 1$ & 11 & $x^3 + x + 1$ \\
2067
+ 4 & $x^2$ & 12 & $x^3 + x^2$ \\
2068
+ 5 & $x^2 + 1$ & 13 & $x^3 + x^2 + 1$ \\
2069
+ 6 & $x^2 + x$ & 14 & $x^3 + x^2 + x$ \\
2070
+ 7 & $x^2 + x + 1$ & 15 & $x^3 + x^2 + x+ 1$ \\\hline
2071
+ \end{tabular}
2072
+
2073
+ INPUT:
2074
+
2075
+ - ``N`` -- nonnegative integer less than or equal to 15, or a list
2076
+ of such integers
2077
+
2078
+ OUTPUT: elements of the finite field `\GF{2^4}`
2079
+
2080
+ EXAMPLES:
2081
+
2082
+ Obtain the element of `\GF{2^4}` representing an integer `n`, where
2083
+ `0 \leq n \leq 15`::
2084
+
2085
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
2086
+ sage: maes = MiniAES()
2087
+ sage: maes.integer_to_GF(0)
2088
+ 0
2089
+ sage: maes.integer_to_GF(2)
2090
+ x
2091
+ sage: maes.integer_to_GF(7)
2092
+ x^2 + x + 1
2093
+
2094
+ Obtain the finite field elements corresponding to all nonnegative
2095
+ integers less than or equal to 15::
2096
+
2097
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
2098
+ sage: maes = MiniAES()
2099
+ sage: lst = [n for n in range(16)]; lst
2100
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
2101
+ sage: maes.integer_to_GF(lst)
2102
+ <BLANKLINE>
2103
+ [0,
2104
+ 1,
2105
+ x,
2106
+ x + 1,
2107
+ x^2,
2108
+ x^2 + 1,
2109
+ x^2 + x,
2110
+ x^2 + x + 1,
2111
+ x^3,
2112
+ x^3 + 1,
2113
+ x^3 + x,
2114
+ x^3 + x + 1,
2115
+ x^3 + x^2,
2116
+ x^3 + x^2 + 1,
2117
+ x^3 + x^2 + x,
2118
+ x^3 + x^2 + x + 1]
2119
+
2120
+ TESTS:
2121
+
2122
+ The input ``N`` can be an integer, but it must be such that
2123
+ `0 \leq N \leq 15`::
2124
+
2125
+ sage: from sage.crypto.block_cipher.miniaes import MiniAES
2126
+ sage: maes = MiniAES()
2127
+ sage: maes.integer_to_GF(-1)
2128
+ Traceback (most recent call last):
2129
+ ...
2130
+ KeyError:...
2131
+ sage: maes.integer_to_GF(16)
2132
+ Traceback (most recent call last):
2133
+ ...
2134
+ KeyError:...
2135
+ sage: maes.integer_to_GF("2")
2136
+ Traceback (most recent call last):
2137
+ ...
2138
+ TypeError: N must be an integer 0 <= N <= 15 or a list of such integers
2139
+
2140
+ The input ``N`` can be a list of integers, but each integer `n` in
2141
+ the list must be bounded such that `0 \leq n \leq 15`::
2142
+
2143
+ sage: maes.integer_to_GF([])
2144
+ Traceback (most recent call last):
2145
+ ...
2146
+ ValueError: N must be an integer 0 <= N <= 15 or a list of such integers
2147
+ sage: maes.integer_to_GF([""])
2148
+ Traceback (most recent call last):
2149
+ ...
2150
+ KeyError:...
2151
+ sage: maes.integer_to_GF([0, 2, 3, "4"])
2152
+ Traceback (most recent call last):
2153
+ ...
2154
+ KeyError:...
2155
+ sage: maes.integer_to_GF([0, 2, 3, 16])
2156
+ Traceback (most recent call last):
2157
+ ...
2158
+ KeyError:...
2159
+ """
2160
+ if isinstance(N, list):
2161
+ if len(N) == 0:
2162
+ raise ValueError("N must be an integer 0 <= N <= 15 or a list of such integers")
2163
+ # Here, we assume that each element of the list is an integer n
2164
+ # such that 0 <= n <= 15. An error will be raised if otherwise.
2165
+ return [self._int_to_GF[n] for n in N]
2166
+ elif isinstance(N, Integer):
2167
+ # Here, we assume that N is an integer such that 0 <= n <= 15.
2168
+ # An error will be raised if otherwise.
2169
+ return self._int_to_GF[N]
2170
+ else:
2171
+ raise TypeError("N must be an integer 0 <= N <= 15 or a list of such integers")