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
sage/crypto/mq/sr.py ADDED
@@ -0,0 +1,3344 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ # sage.doctest: needs sage.modules sage.rings.finite_rings
3
+ r"""
4
+ Small Scale Variants of the AES (SR) Polynomial System Generator
5
+
6
+ Sage supports polynomial system generation for small scale (and full
7
+ scale) AES variants over `\GF{2}` and `\GF{2^e}`. Also, Sage supports
8
+ both the specification of SR as given in the papers [CMR2005]_ and
9
+ [CMR2006]_ and a variant of SR* which is equivalent to AES.
10
+
11
+ SR is a family of parameterizable variants of the AES suitable as a
12
+ framework for comparing different cryptanalytic techniques that can be
13
+ brought to bear on the AES. It is different from
14
+ :class:`Mini-AES <sage.crypto.block_cipher.miniaes.MiniAES>`, whose
15
+ purpose is as a teaching tool to help beginners understand the basic
16
+ structure and working of the full AES.
17
+
18
+ AUTHORS:
19
+
20
+ - Martin Albrecht (2008,2009-01): usability improvements
21
+
22
+ - Martin Albrecht (2007-09): initial version
23
+
24
+ - Niles Johnson (2010-08): (:issue:`3893`) ``random_element()`` should pass on ``*args`` and ``**kwds``.
25
+
26
+ EXAMPLES:
27
+
28
+ We construct SR(1,1,1,4) and study its properties.
29
+ ::
30
+
31
+ sage: sr = mq.SR(1, 1, 1, 4)
32
+
33
+ ``n`` is the number of rounds, ``r`` the number of rows in the
34
+ state array, ``c`` the number of columns in the state array, and ``e`` the
35
+ degree of the underlying field.
36
+
37
+ ::
38
+
39
+ sage: sr.n, sr.r, sr.c, sr.e
40
+ (1, 1, 1, 4)
41
+
42
+ By default variables are ordered reverse to as they appear, e.g.::
43
+
44
+ sage: print(sr.R.repr_long())
45
+ Polynomial Ring
46
+ Base Ring : Finite Field in a of size 2^4
47
+ Size : 20 Variables
48
+ Block 0 : Ordering : deglex
49
+ Names : k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003, k000, k001, k002, k003
50
+
51
+ However, this can be prevented by passing in ``reverse_variables=False`` to the constructor.
52
+
53
+ For SR(1, 1, 1, 4) the ``ShiftRows`` matrix isn't that interesting.::
54
+
55
+ sage: sr.ShiftRows
56
+ [1 0 0 0]
57
+ [0 1 0 0]
58
+ [0 0 1 0]
59
+ [0 0 0 1]
60
+
61
+ Also, the ``MixColumns`` matrix is the identity matrix.::
62
+
63
+ sage: sr.MixColumns
64
+ [1 0 0 0]
65
+ [0 1 0 0]
66
+ [0 0 1 0]
67
+ [0 0 0 1]
68
+
69
+ ``Lin``, however, is not the identity matrix.::
70
+
71
+ sage: sr.Lin
72
+ [ a^2 + 1 1 a^3 + a^2 a^2 + 1]
73
+ [ a a 1 a^3 + a^2 + a + 1]
74
+ [ a^3 + a a^2 a^2 1]
75
+ [ 1 a^3 a + 1 a + 1]
76
+
77
+ ``M`` and ``Mstar`` are identical for SR(1, 1, 1, 4)::
78
+
79
+ sage: sr.M
80
+ [ a^2 + 1 1 a^3 + a^2 a^2 + 1]
81
+ [ a a 1 a^3 + a^2 + a + 1]
82
+ [ a^3 + a a^2 a^2 1]
83
+ [ 1 a^3 a + 1 a + 1]
84
+
85
+ ::
86
+
87
+ sage: sr.Mstar
88
+ [ a^2 + 1 1 a^3 + a^2 a^2 + 1]
89
+ [ a a 1 a^3 + a^2 + a + 1]
90
+ [ a^3 + a a^2 a^2 1]
91
+ [ 1 a^3 a + 1 a + 1]
92
+
93
+
94
+ However, for larger instances of SR Mstar is not equal to M::
95
+
96
+ sage: sr = mq.SR(10,4,4,8)
97
+ sage: sr.Mstar == ~sr.MixColumns * sr.M
98
+ True
99
+
100
+ We can compute a Groebner basis for the ideals spanned by SR
101
+ instances to recover all solutions to the system.::
102
+
103
+ sage: sr = mq.SR(1,1,1,4, gf2=True, polybori=True)
104
+ sage: K = sr.base_ring()
105
+ sage: a = K.gen()
106
+ sage: K = [a]
107
+ sage: P = [1]
108
+ sage: F,s = sr.polynomial_system(P=P, K=K) # needs sage.rings.polynomial.pbori
109
+ sage: F.groebner_basis() # needs sage.rings.polynomial.pbori
110
+ [k100, k101 + 1, k102, k103 + k003,
111
+ x100 + 1, x101 + k003 + 1, x102 + k003 + 1,
112
+ x103 + k003, w100, w101, w102 + 1, w103 + k003 + 1,
113
+ s000 + 1, s001 + k003, s002 + k003, s003 + k003 + 1,
114
+ k000, k001, k002 + 1]
115
+
116
+ Note that the order of ``k000``, ``k001``, ``k002`` and ``k003`` is
117
+ little endian. Thus the result ``k002 + 1, k001, k000`` indicates that
118
+ the key is either `a` or `a+1`. We can verify that both keys encrypt P
119
+ to the same ciphertext::
120
+
121
+ sage: sr(P,[a])
122
+ [0]
123
+ sage: sr(P,[a+1])
124
+ [0]
125
+
126
+ All solutions can easily be recovered using the variety function for ideals.::
127
+
128
+ sage: I = F.ideal() # needs sage.rings.polynomial.pbori
129
+ sage: for V in I.variety(): # needs sage.rings.polynomial.pbori sage.symbolic
130
+ ....: for k,v in sorted(V.items()):
131
+ ....: print("{} {}".format(k, v))
132
+ ....: print("\n")
133
+ k003 0
134
+ k002 1
135
+ k001 0
136
+ k000 0
137
+ s003 1
138
+ s002 0
139
+ s001 0
140
+ s000 1
141
+ w103 1
142
+ w102 1
143
+ w101 0
144
+ w100 0
145
+ x103 0
146
+ x102 1
147
+ x101 1
148
+ x100 1
149
+ k103 0
150
+ k102 0
151
+ k101 1
152
+ k100 0
153
+ <BLANKLINE>
154
+ k003 1
155
+ k002 1
156
+ k001 0
157
+ k000 0
158
+ s003 0
159
+ s002 1
160
+ s001 1
161
+ s000 1
162
+ w103 0
163
+ w102 1
164
+ w101 0
165
+ w100 0
166
+ x103 1
167
+ x102 0
168
+ x101 0
169
+ x100 1
170
+ k103 1
171
+ k102 0
172
+ k101 1
173
+ k100 0
174
+
175
+ We can also verify the correctness of the variety by evaluating all
176
+ ideal generators on all points.::
177
+
178
+ sage: for V in I.variety(): # needs sage.rings.polynomial.pbori sage.symbolic
179
+ ....: for f in I.gens():
180
+ ....: if f.subs(V) != 0:
181
+ ....: print("epic fail")
182
+
183
+
184
+ Note that the S-Box object for SR can be constructed with a call to ``sr.sbox()``::
185
+
186
+ sage: sr = mq.SR(1,1,1,4, gf2=True, polybori=True)
187
+ sage: S = sr.sbox()
188
+
189
+ For example, we can now study the difference distribution table of ``S``::
190
+
191
+ sage: S.difference_distribution_table()
192
+ [16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
193
+ [ 0 2 2 2 2 0 0 0 2 0 0 0 2 4 0 0]
194
+ [ 0 2 0 4 2 2 2 0 0 2 0 0 0 0 0 2]
195
+ [ 0 2 4 0 0 2 0 0 2 2 0 2 0 0 2 0]
196
+ [ 0 0 2 0 4 2 0 0 0 0 2 0 2 0 2 2]
197
+ [ 0 0 0 2 0 0 0 2 4 2 0 0 2 0 2 2]
198
+ [ 0 4 0 0 0 2 0 2 0 2 2 0 2 2 0 0]
199
+ [ 0 2 0 0 0 0 2 0 0 0 0 2 4 2 2 2]
200
+ [ 0 2 2 0 0 0 2 2 2 0 2 0 0 0 0 4]
201
+ [ 0 0 2 2 0 0 0 0 0 2 2 4 0 2 0 2]
202
+ [ 0 0 2 0 2 0 2 2 0 4 0 2 2 0 0 0]
203
+ [ 0 0 0 0 2 0 2 0 2 2 4 0 0 2 2 0]
204
+ [ 0 0 0 2 0 4 2 0 2 0 2 2 2 0 0 0]
205
+ [ 0 0 0 0 2 2 0 4 2 0 0 2 0 2 0 2]
206
+ [ 0 0 2 2 0 2 4 2 0 0 0 0 0 2 2 0]
207
+ [ 0 2 0 2 2 0 0 2 0 0 2 2 0 0 4 0]
208
+
209
+ or use ``S`` to find alternative polynomial representations for the S-Box.::
210
+
211
+ sage: S.polynomials(degree=3) # needs sage.libs.singular
212
+ [x0*x1 + x1*x2 + x0*x3 + x0*y2 + x1 + y0 + y1 + 1,
213
+ x0*x1 + x0*x2 + x0*y0 + x0*y1 + x0*y2 + x1 + x2 + y0 + y1 + y2,
214
+ x0*x1 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x1*y0 + x0*y1 + x0*y3,
215
+ x0*x1 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x1*y1 + x0*y3 + x1 + y0 + y1 + 1,
216
+ x0*x1 + x0*x2 + x0*y2 + x1*y2 + x0*y3 + x0 + x1,
217
+ x0*x3 + x1*x3 + x0*y1 + x0*y2 + x1*y3 + x0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
218
+ x0*x1 + x1*x3 + x2*x3 + x0*y0 + x0*y2 + x0*y3 + x2 + y0 + y3,
219
+ x0*x1 + x0*x2 + x0*x3 + x1*x3 + x2*y0 + x0*y2 + x0 + x2 + x3 + y3,
220
+ x0*x3 + x1*x3 + x0*y0 + x2*y1 + x0*y2 + x3 + y3,
221
+ x0*x1 + x0*x2 + x0*y0 + x0*y1 + x2*y2 + x0*y3 + x1 + y0 + y1 + 1,
222
+ x0*x3 + x1*x3 + x0*y0 + x0*y1 + x0*y3 + x2*y3 + y0 + y3,
223
+ x0*x1 + x0*x2 + x3*y0 + x0*y1 + x0*y3 + y0,
224
+ x0*y0 + x0*y1 + x3*y1 + x0 + x2 + y0 + y3,
225
+ x0*y0 + x3*y2 + y0,
226
+ x0*x1 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x0*y2 + x3*y3 + y0,
227
+ x0*x2 + x0*x3 + x0*y1 + y0*y1 + x0*y3 + x2 + x3 + y3,
228
+ x0*x2 + x0*y0 + y0*y2 + x0*y3 + x0 + y0,
229
+ x0*x1 + x0*x2 + x1*x3 + x0*y2 + y0*y3 + y0,
230
+ x0*x1 + x0*y0 + y1*y2 + x0*y3 + x1 + x2 + y0 + 1,
231
+ x0*x2 + x1*x3 + x0*y1 + x0*y2 + x0*y3 + y1*y3 + x0 + y0 + y3,
232
+ x0*x1 + x0*x2 + x0*x3 + x0*y1 + x0*y2 + x0*y3 + y2*y3 + x0 + x1 + x2 + x3 + y1 + y3 + 1,
233
+ x0*x1*x2 + x0*x3 + x0*y0 + x0*y1 + x0*y2 + x0,
234
+ x0*x1*x3 + x0*x2 + x0*x3 + x0*y1 + x0*y3 + x0,
235
+ x0*x1*y0 + x0*x1 + x0*y0 + x0,
236
+ x0*x1*y1,
237
+ x0*x1*y2 + x0*x2 + x0*y2 + x0*y3 + x0,
238
+ x0*x1*y3 + x0*x1 + x0*x3 + x0*y0 + x0*y1 + x0*y2 + x0,
239
+ x0*x2*x3 + x0*x1 + x0*x3 + x0*y1 + x0*y2 + x0*y3 + x0,
240
+ x0*x2*y0 + x0*x1 + x0*x2 + x0*x3 + x0*y1 + x0*y2,
241
+ x0*x2*y1 + x0*x2 + x0*x3 + x0*y0 + x0*y1 + x0*y2 + x0,
242
+ x0*x2*y2 + x0*x2 + x0*y3 + x0,
243
+ x0*x2*y3 + x0*x2 + x0*y3 + x0,
244
+ x0*x3*y0 + x0*x1 + x0*x2 + x0*y0 + x0*y1 + x0*y3,
245
+ x0*x3*y1 + x0*x2 + x0*y1 + x0*y3 + x0,
246
+ x0*x3*y2,
247
+ x0*x3*y3 + x0*x1 + x0*y1 + x0*y2 + x0*y3 + x0,
248
+ x0*y0*y1 + x0*y1,
249
+ x0*y0*y2 + x0*x2 + x0*y3 + x0,
250
+ x0*y0*y3 + x0*x1 + x0*x3 + x0*y0 + x0*y1 + x0*y2 + x0*y3 + x0,
251
+ x0*y1*y2 + x0*x2 + x0*y3 + x0,
252
+ x0*y1*y3 + x0*x3 + x0*y0 + x0*y2 + x0*y3,
253
+ x0*y2*y3 + x0*y2,
254
+ x1*x2*x3 + x0*x1 + x1*x3 + x0*y0 + x0*y1 + x2 + x3 + y3,
255
+ x1*x2*y0 + x0*x1 + x1*x3 + x0*y0 + x0*y1 + x2 + x3 + y3,
256
+ x1*x2*y1 + x0*x1 + x1*x3 + x0*y0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
257
+ x1*x2*y2 + x0*x1 + x0*y0 + x0*y1 + x0 + x1 + y0 + y1 + 1,
258
+ x1*x2*y3 + x0*x1 + x1*x3 + x0*y0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
259
+ x1*x3*y0 + x0*x1 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x0*y1 + x0*y3,
260
+ x1*x3*y1 + x0*x2 + x0*x3 + x0*y3 + x2 + x3 + y3,
261
+ x1*x3*y2 + x0*x2 + x0*x3 + x1*x3 + x0*y1 + x0*y3 + x0,
262
+ x1*x3*y3 + x0*x1 + x0*x2 + x0*x3 + x0*y0 + x0*y1 + x0*y3,
263
+ x1*y0*y1 + x0*x2 + x0*x3 + x0*y3 + x2 + x3 + y3,
264
+ x1*y0*y2 + x0*x2 + x0*x3 + x1*x3 + x0*y1 + x0*y3 + x0,
265
+ x1*y0*y3,
266
+ x1*y1*y2 + x0*x1 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x0*y3 + x1 + y0 + y1 + 1,
267
+ x1*y1*y3 + x0*x1 + x1*x3 + x0*y0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
268
+ x1*y2*y3 + x0*x1 + x0*x2 + x1*x3 + x0*y0 + x0*y2 + x0*y3 + x0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
269
+ x2*x3*y0 + x0*x1 + x0*x3 + x1*x3 + x0*y2 + x0*y3 + x2 + x3 + y3,
270
+ x2*x3*y1 + x0*y1 + x0*y2 + x0*y3 + x3 + y0,
271
+ x2*x3*y2 + x1*x3 + x0*y1 + x0 + x2 + x3 + y3,
272
+ x2*x3*y3,
273
+ x2*y0*y1 + x0*x2 + x0*x3 + x0*y0 + x0*y1 + x0*y2 + x0,
274
+ x2*y0*y2 + x0*x2 + x1*x3 + x0*y1 + x0*y3 + x2 + x3 + y3,
275
+ x2*y0*y3 + x0*x2 + x0*y3 + x0,
276
+ x2*y1*y2 + x0*x1 + x0*x2 + x1*x3 + x0*y0 + x0*y3 + x0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
277
+ x2*y1*y3 + x0*x3 + x1*x3 + x0*y0 + x0*y1 + x0*y3 + y0 + y3,
278
+ x2*y2*y3 + x0*x1 + x0*x2 + x1*x3 + x0*y0 + x0*y3 + x0 + x1 + x2 + x3 + y0 + y1 + y3 + 1,
279
+ x3*y0*y1 + x0*x3 + x0*y1 + x0 + x2 + x3 + y3,
280
+ x3*y0*y2 + x0*y0 + y0,
281
+ x3*y0*y3 + x1*x3 + x0*y1 + x0*y2 + x0*y3 + y0,
282
+ x3*y1*y2 + x0*x2 + x0*x3 + x0*y3 + x2 + x3 + y3,
283
+ x3*y1*y3 + x0*x2 + x0*x3 + x0*y0 + x0*y2 + x0,
284
+ x3*y2*y3 + x0*x2 + x0*x3 + x1*x3 + x0*y0 + x0*y1 + x0*y3 + x0 + y0,
285
+ y0*y1*y2 + x0*x3 + x0 + x2 + x3 + y3,
286
+ y0*y1*y3 + x0*x3 + x0*y0 + x0*y2 + x0*y3,
287
+ y0*y2*y3 + x0*x3 + x1*x3 + x0*y0 + x0*y1 + y0,
288
+ y1*y2*y3 + x0*x1 + x0*x2 + x1*x3 + x0*y0 + x0*y3 + x0 + x1 + x2 + x3 + y0 + y1 + y3 + 1]
289
+
290
+ sage: S.interpolation_polynomial()
291
+ (a^2 + 1)*x^14 + a^2*x^13 + x^12 + a^2*x^11 + a*x^10 + (a^3 + a)*x^9 +
292
+ (a^3 + 1)*x^7 + (a^3 + a^2 + a)*x^6 + a^2*x^5 + (a + 1)*x^4 + a^2*x^3 +
293
+ (a^3 + a^2 + a)*x^2 + (a^3 + 1)*x + a^2 + a
294
+
295
+ The :class:`SR_gf2_2` gives an example how use alternative polynomial
296
+ representations of the S-Box for construction of polynomial systems.
297
+
298
+ TESTS::
299
+
300
+ sage: sr == loads(dumps(sr))
301
+ True
302
+
303
+ REFERENCES:
304
+
305
+ - [CMR2005]_
306
+
307
+ - [CMR2006]_
308
+
309
+ - [MR2002]_
310
+ """
311
+
312
+ from sage.matrix.constructor import matrix, random_matrix
313
+ from sage.matrix.matrix_space import MatrixSpace
314
+ from sage.misc.flatten import flatten
315
+ from sage.misc.verbose import get_verbose
316
+ from sage.modules.vector_modn_dense import Vector_modn_dense
317
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
318
+ from sage.rings.integer_ring import ZZ
319
+ from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
320
+ from sage.rings.polynomial.polynomial_ring_constructor import \
321
+ BooleanPolynomialRing_constructor as BooleanPolynomialRing
322
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
323
+ from sage.rings.polynomial.term_order import TermOrder
324
+ from sage.structure.element import Matrix
325
+
326
+ from .mpolynomialsystemgenerator import MPolynomialSystemGenerator
327
+
328
+
329
+ def SR(n=1, r=1, c=1, e=4, star=False, **kwargs):
330
+ r"""
331
+ Return a small scale variant of the AES polynomial system
332
+ constructor subject to the following conditions:
333
+
334
+ INPUT:
335
+
336
+ - ``n`` -- the number of rounds (default: 1)
337
+ - ``r`` -- the number of rows in the state array (default: 1)
338
+ - ``c`` -- the number of columns in the state array (default: 1)
339
+ - ``e`` -- the exponent of the finite extension field (default: 4)
340
+ - ``star`` -- determines if SR\* or SR should be constructed (default: ``False``)
341
+ - ``aes_mode`` -- as the SR key schedule specification differs
342
+ slightly from the AES key schedule, this parameter controls
343
+ which schedule to use (default: ``True``)
344
+ - ``gf2`` -- generate polynomial systems over `\GF{2}` rather than
345
+ over `\GF{2^e}` (default: ``False``)
346
+ - ``polybori`` -- use the ``BooleanPolynomialRing`` as polynomial
347
+ representation (default: ``True``, `\GF{2}` only)
348
+ - ``order`` -- string to specify the term ordering of the
349
+ variables (default: ``deglex``)
350
+ - ``postfix`` -- string which is appended after the variable name
351
+ (default: ``''``)
352
+ - ``allow_zero_inversions`` -- boolean to control whether zero
353
+ inversions raise an exception (default: ``False``)
354
+ - ``correct_only`` -- only include correct inversion polynomials
355
+ (default: ``False``, `\GF{2}` only)
356
+ - ``biaffine_only`` -- only include bilinear and biaffine inversion
357
+ polynomials (default: ``True``, `\GF{2}` only)
358
+
359
+ EXAMPLES::
360
+
361
+ sage: sr = mq.SR(1, 1, 1, 4)
362
+ sage: ShiftRows = sr.shift_rows_matrix()
363
+ sage: MixColumns = sr.mix_columns_matrix()
364
+ sage: Lin = sr.lin_matrix()
365
+ sage: M = MixColumns * ShiftRows * Lin
366
+ sage: print(sr.hex_str_matrix(M))
367
+ 5 1 C 5
368
+ 2 2 1 F
369
+ A 4 4 1
370
+ 1 8 3 3
371
+
372
+ ::
373
+
374
+ sage: sr = mq.SR(1, 2, 1, 4)
375
+ sage: ShiftRows = sr.shift_rows_matrix()
376
+ sage: MixColumns = sr.mix_columns_matrix()
377
+ sage: Lin = sr.lin_matrix()
378
+ sage: M = MixColumns * ShiftRows * Lin
379
+ sage: print(sr.hex_str_matrix(M))
380
+ F 3 7 F A 2 B A
381
+ A A 5 6 8 8 4 9
382
+ 7 8 8 2 D C C 3
383
+ 4 6 C C 5 E F F
384
+ A 2 B A F 3 7 F
385
+ 8 8 4 9 A A 5 6
386
+ D C C 3 7 8 8 2
387
+ 5 E F F 4 6 C C
388
+
389
+ ::
390
+
391
+ sage: sr = mq.SR(1, 2, 2, 4)
392
+ sage: ShiftRows = sr.shift_rows_matrix()
393
+ sage: MixColumns = sr.mix_columns_matrix()
394
+ sage: Lin = sr.lin_matrix()
395
+ sage: M = MixColumns * ShiftRows * Lin
396
+ sage: print(sr.hex_str_matrix(M))
397
+ F 3 7 F 0 0 0 0 0 0 0 0 A 2 B A
398
+ A A 5 6 0 0 0 0 0 0 0 0 8 8 4 9
399
+ 7 8 8 2 0 0 0 0 0 0 0 0 D C C 3
400
+ 4 6 C C 0 0 0 0 0 0 0 0 5 E F F
401
+ A 2 B A 0 0 0 0 0 0 0 0 F 3 7 F
402
+ 8 8 4 9 0 0 0 0 0 0 0 0 A A 5 6
403
+ D C C 3 0 0 0 0 0 0 0 0 7 8 8 2
404
+ 5 E F F 0 0 0 0 0 0 0 0 4 6 C C
405
+ 0 0 0 0 A 2 B A F 3 7 F 0 0 0 0
406
+ 0 0 0 0 8 8 4 9 A A 5 6 0 0 0 0
407
+ 0 0 0 0 D C C 3 7 8 8 2 0 0 0 0
408
+ 0 0 0 0 5 E F F 4 6 C C 0 0 0 0
409
+ 0 0 0 0 F 3 7 F A 2 B A 0 0 0 0
410
+ 0 0 0 0 A A 5 6 8 8 4 9 0 0 0 0
411
+ 0 0 0 0 7 8 8 2 D C C 3 0 0 0 0
412
+ 0 0 0 0 4 6 C C 5 E F F 0 0 0 0
413
+ """
414
+ if not kwargs.get("gf2", False):
415
+ return SR_gf2n(n, r, c, e, star, **kwargs)
416
+ else:
417
+ return SR_gf2(n, r, c, e, star, **kwargs)
418
+
419
+
420
+ class SR_generic(MPolynomialSystemGenerator):
421
+ def __init__(self, n=1, r=1, c=1, e=4, star=False, **kwargs):
422
+ """
423
+ Small Scale Variants of the AES.
424
+
425
+ EXAMPLES::
426
+
427
+ sage: sr = mq.SR(1, 1, 1, 4)
428
+ sage: ShiftRows = sr.shift_rows_matrix()
429
+ sage: MixColumns = sr.mix_columns_matrix()
430
+ sage: Lin = sr.lin_matrix()
431
+ sage: M = MixColumns * ShiftRows * Lin
432
+ sage: print(sr.hex_str_matrix(M))
433
+ 5 1 C 5
434
+ 2 2 1 F
435
+ A 4 4 1
436
+ 1 8 3 3
437
+ """
438
+ if n-1 not in range(10):
439
+ raise TypeError("n must be between 1 and 10 (inclusive)")
440
+ self._n = n
441
+
442
+ if r not in (1, 2, 4):
443
+ raise TypeError("r must be in (1, 2, 4)")
444
+ self._r = r
445
+
446
+ if c not in (1, 2, 4):
447
+ raise TypeError("c must be in (1, 2, 4)")
448
+ self._c = c
449
+
450
+ if e not in (4, 8):
451
+ raise TypeError("e must be either 4 or 8")
452
+ self._e = e
453
+
454
+ self._star = bool(star)
455
+
456
+ self._base = self.base_ring()
457
+
458
+ self._postfix = kwargs.get("postfix", "")
459
+ self._order = kwargs.get("order", "deglex")
460
+ self._aes_mode = kwargs.get("aes_mode", True)
461
+ self._gf2 = kwargs.get("gf2", False)
462
+ self._allow_zero_inversions = bool(kwargs.get("allow_zero_inversions", False))
463
+ self._reverse_variables = bool(kwargs.get("reverse_variables", True))
464
+
465
+ with AllowZeroInversionsContext(self):
466
+ sub_byte_lookup = {v: self.sub_byte(v) for v in self._base}
467
+ self._sub_byte_lookup = sub_byte_lookup
468
+
469
+ if self._gf2:
470
+ self._polybori = kwargs.get("polybori", True)
471
+
472
+ def new_generator(self, **kwds):
473
+ r"""
474
+ Return a new ``SR`` instance equal to this instance
475
+ except for the parameters passed explicitly to this function.
476
+
477
+ INPUT:
478
+
479
+ - ``**kwds`` -- see the ``SR`` constructor for accepted
480
+ parameters
481
+
482
+ EXAMPLES::
483
+
484
+ sage: sr = mq.SR(2,1,1,4); sr
485
+ SR(2,1,1,4)
486
+ sage: sr.ring().base_ring()
487
+ Finite Field in a of size 2^4
488
+
489
+ ::
490
+
491
+ sage: sr2 = sr.new_generator(gf2=True); sr2
492
+ SR(2,1,1,4)
493
+ sage: sr2.ring().base_ring()
494
+ Finite Field of size 2
495
+ sage: sr3 = sr2.new_generator(correct_only=True)
496
+ sage: len(sr2.inversion_polynomials_single_sbox())
497
+ 20
498
+ sage: len(sr3.inversion_polynomials_single_sbox())
499
+ 19
500
+ """
501
+ kwds.setdefault("n", self._n)
502
+ kwds.setdefault("r", self._r)
503
+ kwds.setdefault("c", self._c)
504
+ kwds.setdefault("e", self._e)
505
+ kwds.setdefault("star", self._star)
506
+ kwds.setdefault("postfix", self._postfix)
507
+ kwds.setdefault("order", self._order)
508
+ kwds.setdefault("allow_zero_inversions", self._allow_zero_inversions)
509
+ kwds.setdefault("aes_mode", self._aes_mode)
510
+ kwds.setdefault("gf2", self._gf2)
511
+ kwds.setdefault("reverse_variables", self._reverse_variables)
512
+
513
+ try:
514
+ polybori = self._polybori
515
+ except AttributeError:
516
+ polybori = False
517
+ kwds.setdefault("polybori", polybori)
518
+
519
+ try:
520
+ correct_only = self._correct_only
521
+ except AttributeError:
522
+ correct_only = False
523
+ kwds.setdefault("correct_only", correct_only)
524
+
525
+ try:
526
+ biaffine_only = self._biaffine_only
527
+ except AttributeError:
528
+ biaffine_only = False
529
+ kwds.setdefault("biaffine_only", biaffine_only)
530
+
531
+ if self._gf2 == kwds.get('gf2'):
532
+ return self.__class__(**kwds)
533
+ else:
534
+ return SR(**kwds)
535
+
536
+ def __getattr__(self, attr):
537
+ """
538
+ EXAMPLES::
539
+
540
+ sage: sr = mq.SR(1, 2, 1, 4, gf2=True)
541
+ sage: sr.Mstar
542
+ [1 0 1 1 0 0 0 0]
543
+ [1 1 0 1 0 0 0 0]
544
+ [1 1 1 0 0 0 0 0]
545
+ [0 1 1 1 0 0 0 0]
546
+ [0 0 0 0 1 0 1 1]
547
+ [0 0 0 0 1 1 0 1]
548
+ [0 0 0 0 1 1 1 0]
549
+ [0 0 0 0 0 1 1 1]
550
+ """
551
+ if attr == "e":
552
+ return self._e
553
+ elif attr == "c":
554
+ return self._c
555
+ elif attr == "n":
556
+ return self._n
557
+ elif attr == "r":
558
+ return self._r
559
+
560
+ elif attr == "R":
561
+ self.R = self.ring()
562
+ return self.R
563
+ elif attr == "k":
564
+ self.k = self.base_ring()
565
+ return self.k
566
+
567
+ elif attr == "Lin":
568
+ self.Lin = self.lin_matrix()
569
+ return self.Lin
570
+
571
+ elif attr == "ShiftRows":
572
+ self.ShiftRows = self.shift_rows_matrix()
573
+ return self.ShiftRows
574
+
575
+ elif attr == "MixColumns":
576
+ self.MixColumns = self.mix_columns_matrix()
577
+ return self.MixColumns
578
+
579
+ elif attr == "M":
580
+ self.M = self.MixColumns * self.ShiftRows * self.Lin
581
+ return self.M
582
+
583
+ elif attr == "Mstar":
584
+ self.Mstar = self.ShiftRows * self.Lin
585
+ return self.Mstar
586
+
587
+ raise AttributeError("%s has no attribute %s" % (type(self), attr))
588
+
589
+ def _repr_(self):
590
+ """
591
+ EXAMPLES::
592
+
593
+ sage: sr = mq.SR(1, 2, 2, 4); sr #indirect doctest
594
+ SR(1,2,2,4)
595
+ sage: sr = mq.SR(1, 2, 2, 4, star=True); sr
596
+ SR*(1,2,2,4)
597
+ """
598
+ if self._star:
599
+ return "SR*(%d,%d,%d,%d)" % (self._n, self._r, self._c, self._e)
600
+ else:
601
+ return "SR(%d,%d,%d,%d)" % (self._n, self._r, self._c, self._e)
602
+
603
+ def base_ring(self):
604
+ r"""
605
+ Return the base field of ``self`` as determined by
606
+ ``self.e``.
607
+
608
+ EXAMPLES::
609
+
610
+ sage: sr = mq.SR(10, 2, 2, 4)
611
+ sage: sr.base_ring().polynomial()
612
+ a^4 + a + 1
613
+
614
+ The Rijndael polynomial::
615
+
616
+ sage: sr = mq.SR(10, 4, 4, 8)
617
+ sage: sr.base_ring().polynomial()
618
+ a^8 + a^4 + a^3 + a + 1
619
+ """
620
+ try:
621
+ return self._base
622
+ except AttributeError:
623
+ if self._e == 4:
624
+ self._base = GF(2**4, 'a', modulus=(1, 1, 0, 0, 1))
625
+ elif self._e == 8:
626
+ self._base = GF(2**8, 'a', modulus=(1, 1, 0, 1, 1, 0, 0, 0, 1))
627
+
628
+ return self._base
629
+
630
+ def __eq__(self, other):
631
+ """
632
+ Two generators are considered equal if they agree on all parameters
633
+ passed to them during construction.
634
+
635
+ EXAMPLES::
636
+
637
+ sage: sr1 = mq.SR(2, 2, 2, 4)
638
+ sage: sr1 == sr1
639
+ True
640
+
641
+ sage: sr2 = mq.SR(2, 2, 2, 4, gf2=True)
642
+ sage: sr1 == sr2
643
+ False
644
+ """
645
+ for name in ['n', 'r', 'c', 'e', '_postfix', '_order',
646
+ '_allow_zero_inversions', '_aes_mode', '_gf2', '_star']:
647
+ lx = getattr(self, name)
648
+ rx = getattr(other, name)
649
+ if lx != rx:
650
+ return False
651
+ return True
652
+
653
+ def __ne__(self, other):
654
+ """
655
+ Return whether ``self`` is not equal to ``other``.
656
+
657
+ EXAMPLES::
658
+
659
+ sage: sr1 = mq.SR(2, 2, 2, 4)
660
+ sage: sr1 != sr1
661
+ False
662
+
663
+ sage: sr2 = mq.SR(2, 2, 2, 4, gf2=True)
664
+ sage: sr1 != sr2
665
+ True
666
+ """
667
+ return not (self == other)
668
+
669
+ def sub_bytes(self, d):
670
+ r"""
671
+ Perform the non-linear transform on ``d``.
672
+
673
+ INPUT:
674
+
675
+ - ``d`` -- state array or something coercible to a state array
676
+
677
+ EXAMPLES::
678
+
679
+ sage: sr = mq.SR(2, 1, 2, 8, gf2=True)
680
+ sage: k = sr.base_ring()
681
+ sage: A = Matrix(k, 1, 2 , [k(1), k.gen()])
682
+ sage: sr.sub_bytes(A)
683
+ [ a^6 + a^5 + a^4 + a^3 + a^2 a^6 + a^5 + a^4 + a^2 + a + 1]
684
+ """
685
+ d = self.state_array(d)
686
+ return matrix(self.base_ring(), d.nrows(), d.ncols(), [self.sub_byte(b) for b in d.list()])
687
+
688
+ def sub_byte(self, b):
689
+ r"""
690
+ Perform ``SubByte`` on a single byte/halfbyte ``b``.
691
+
692
+ A ``ZeroDivision`` exception is raised if an attempt is made
693
+ to perform an inversion on the zero element. This can be
694
+ disabled by passing ``allow_zero_inversion=True`` to the
695
+ constructor. A zero inversion can result in an inconsistent
696
+ equation system.
697
+
698
+ INPUT:
699
+
700
+ - ``b`` -- an element in ``self.base_ring()``
701
+
702
+ EXAMPLES:
703
+
704
+ The S-Box table for `\GF{2^4}`::
705
+
706
+ sage: sr = mq.SR(1, 1, 1, 4, allow_zero_inversions=True)
707
+ sage: for e in sr.base_ring():
708
+ ....: print('% 20s % 20s'%(e, sr.sub_byte(e)))
709
+ 0 a^2 + a
710
+ a a^2 + 1
711
+ a^2 a
712
+ a^3 a^3 + 1
713
+ a + 1 a^2
714
+ a^2 + a a^2 + a + 1
715
+ a^3 + a^2 a + 1
716
+ a^3 + a + 1 a^3 + a^2
717
+ a^2 + 1 a^3 + a^2 + a
718
+ a^3 + a a^3 + a^2 + a + 1
719
+ a^2 + a + 1 a^3 + a
720
+ a^3 + a^2 + a 0
721
+ a^3 + a^2 + a + 1 a^3
722
+ a^3 + a^2 + 1 1
723
+ a^3 + 1 a^3 + a^2 + 1
724
+ 1 a^3 + a + 1
725
+ """
726
+ if not b:
727
+ if not self._allow_zero_inversions:
728
+ raise ZeroDivisionError("A zero inversion occurred during an encryption or key schedule.")
729
+ else:
730
+ return self.sbox_constant()
731
+ try:
732
+ return self._sub_byte_lookup[b]
733
+ except AttributeError:
734
+ e = self.e
735
+ k = self.k
736
+
737
+ # inversion
738
+ b = b ** ( 2**e - 2 )
739
+
740
+ # GF(2) linear map
741
+ if e == 4:
742
+ if not hasattr(self, "_L"):
743
+ self._L = matrix(GF(2), 4, 4, [[1, 1, 1, 0],
744
+ [0, 1, 1, 1],
745
+ [1, 0, 1, 1],
746
+ [1, 1, 0, 1]])
747
+
748
+ elif e == 8:
749
+ if not hasattr(self, "_L"):
750
+ self._L = matrix(GF(2), 8, 8, [[1, 0, 0, 0, 1, 1, 1, 1],
751
+ [1, 1, 0, 0, 0, 1, 1, 1],
752
+ [1, 1, 1, 0, 0, 0, 1, 1],
753
+ [1, 1, 1, 1, 0, 0, 0, 1],
754
+ [1, 1, 1, 1, 1, 0, 0, 0],
755
+ [0, 1, 1, 1, 1, 1, 0, 0],
756
+ [0, 0, 1, 1, 1, 1, 1, 0],
757
+ [0, 0, 0, 1, 1, 1, 1, 1]])
758
+
759
+ b = k(self._L * b._vector_())
760
+
761
+ # constant addition
762
+ if e == 4:
763
+ b = b + k.from_integer(6)
764
+ elif e == 8:
765
+ b = b + k.from_integer(99)
766
+
767
+ return b
768
+
769
+ def sbox_constant(self):
770
+ """
771
+ Return the S-Box constant which is added after `L(x^{-1})` was
772
+ performed. That is ``0x63`` if ``e == 8`` or ``0x6`` if ``e ==
773
+ 4``.
774
+
775
+ EXAMPLES::
776
+
777
+ sage: sr = mq.SR(10, 1, 1, 8)
778
+ sage: sr.sbox_constant()
779
+ a^6 + a^5 + a + 1
780
+ """
781
+ k = self.k
782
+ if self.e == 4:
783
+ return k.from_integer(6)
784
+ elif self.e == 8:
785
+ return k.from_integer(99)
786
+ else:
787
+ raise TypeError("sbox constant only defined for e in (4, 8)")
788
+
789
+ def sbox(self, inversion_only=False):
790
+ r"""
791
+ Return an S-Box object for this SR instance.
792
+
793
+ INPUT:
794
+
795
+ - ``inversion_only`` -- do not include the `\GF{2}` affine map when
796
+ computing the S-Box (default: ``False``)
797
+
798
+ EXAMPLES::
799
+
800
+ sage: sr = mq.SR(1,2,2,4, allow_zero_inversions=True)
801
+ sage: S = sr.sbox(); S
802
+ (6, 11, 5, 4, 2, 14, 7, 10, 9, 13, 15, 12, 3, 1, 0, 8)
803
+
804
+ sage: sr.sub_byte(0)
805
+ a^2 + a
806
+ sage: sage_eval(str(sr.sub_byte(0)), {'a':2})
807
+ 6
808
+ sage: S(0)
809
+ 6
810
+
811
+ sage: sr.sub_byte(1)
812
+ a^3 + a + 1
813
+ sage: sage_eval(str(sr.sub_byte(1)), {'a':2})
814
+ 11
815
+ sage: S(1)
816
+ 11
817
+
818
+ sage: sr = mq.SR(1,2,2,8, allow_zero_inversions=True)
819
+ sage: S = sr.sbox(); S
820
+ (99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43,
821
+ 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240,
822
+ 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38,
823
+ 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4,
824
+ 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39,
825
+ 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214,
826
+ 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91,
827
+ 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251,
828
+ 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81,
829
+ 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16,
830
+ 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196,
831
+ 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
832
+ 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58,
833
+ 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
834
+ 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234,
835
+ 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198,
836
+ 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102,
837
+ 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225,
838
+ 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206,
839
+ 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65,
840
+ 153, 45, 15, 176, 84, 187, 22)
841
+
842
+ sage: sr.sub_byte(0)
843
+ a^6 + a^5 + a + 1
844
+
845
+ sage: sage_eval(str(sr.sub_byte(0)), {'a':2})
846
+ 99
847
+ sage: S(0)
848
+ 99
849
+
850
+ sage: sr.sub_byte(1)
851
+ a^6 + a^5 + a^4 + a^3 + a^2
852
+
853
+ sage: sage_eval(str(sr.sub_byte(1)), {'a':2})
854
+ 124
855
+
856
+ sage: S(1)
857
+ 124
858
+
859
+ sage: sr = mq.SR(1,2,2,4, allow_zero_inversions=True)
860
+ sage: S = sr.sbox(inversion_only=True); S
861
+ (0, 1, 9, 14, 13, 11, 7, 6, 15, 2, 12, 5, 10, 4, 3, 8)
862
+
863
+ sage: S(0)
864
+ 0
865
+ sage: S(1)
866
+ 1
867
+
868
+ sage: S(sr.k.gen())
869
+ a^3 + a + 1
870
+ """
871
+ from sage.crypto.sbox import SBox
872
+
873
+ k = self.base_ring()
874
+ if not inversion_only:
875
+ with AllowZeroInversionsContext(self):
876
+ S = [self.sub_byte(elem) for elem in sorted(k)]
877
+ return SBox(S)
878
+ else:
879
+ e = self.e
880
+ S = [elem ** (2**e - 2) for elem in sorted(k)]
881
+ return SBox(S)
882
+
883
+ def shift_rows(self, d):
884
+ r"""
885
+ Perform the ``ShiftRows`` operation on ``d``.
886
+
887
+ INPUT:
888
+
889
+ - ``d`` -- state array or something coercible to a state array
890
+
891
+ EXAMPLES::
892
+
893
+ sage: sr = mq.SR(10, 4, 4, 4)
894
+ sage: E = sr.state_array() + 1; E
895
+ [1 0 0 0]
896
+ [0 1 0 0]
897
+ [0 0 1 0]
898
+ [0 0 0 1]
899
+
900
+ ::
901
+
902
+ sage: sr.shift_rows(E)
903
+ [1 0 0 0]
904
+ [1 0 0 0]
905
+ [1 0 0 0]
906
+ [1 0 0 0]
907
+ """
908
+ d = self.state_array(d)
909
+ ret = []
910
+ for i in range(d.nrows()):
911
+ ret += list(d.row(i)[i % d.ncols():]) + list(d.row(i)[:i % d.ncols()])
912
+ return matrix(self.base_ring(), self._r, self._c, ret)
913
+
914
+ def mix_columns(self, d):
915
+ r"""
916
+ Perform the ``MixColumns`` operation on
917
+ ``d``.
918
+
919
+ INPUT:
920
+
921
+ - ``d`` -- state array or something coercible to a state array
922
+
923
+ EXAMPLES::
924
+
925
+ sage: sr = mq.SR(10, 4, 4, 4)
926
+ sage: E = sr.state_array() + 1; E
927
+ [1 0 0 0]
928
+ [0 1 0 0]
929
+ [0 0 1 0]
930
+ [0 0 0 1]
931
+
932
+ ::
933
+
934
+ sage: sr.mix_columns(E)
935
+ [ a a + 1 1 1]
936
+ [ 1 a a + 1 1]
937
+ [ 1 1 a a + 1]
938
+ [a + 1 1 1 a]
939
+ """
940
+ d = self.state_array(d)
941
+ k = self.base_ring()
942
+ a = k.gen()
943
+ r = self._r
944
+ if r == 1:
945
+ M = matrix(self.base_ring(), 1, 1, [[1]])
946
+ elif r == 2:
947
+ M = matrix(self.base_ring(), 2, 2, [[a + 1, a],
948
+ [a, a + 1]])
949
+
950
+ elif r == 4:
951
+ M = matrix(self.base_ring(), 4, 4, [[a, a+1, 1, 1],
952
+ [1, a, a+1, 1],
953
+ [1, 1, a, a+1],
954
+ [a+1, 1, 1, a]])
955
+ ret = []
956
+ for column in d.columns():
957
+ ret.append(M * column)
958
+ # AES uses the column major ordering
959
+ return matrix(k, d.ncols(), d.nrows(), ret).transpose()
960
+
961
+ def add_round_key(self, d, key):
962
+ r"""
963
+ Perform the ``AddRoundKey`` operation on
964
+ ``d`` using ``key``.
965
+
966
+ INPUT:
967
+
968
+ - ``d`` -- state array or something coercible to a state array
969
+
970
+ - ``key`` -- state array or something coercible to a state array
971
+
972
+ EXAMPLES::
973
+
974
+ sage: sr = mq.SR(10, 4, 4, 4)
975
+ sage: D = sr.random_state_array()
976
+ sage: K = sr.random_state_array()
977
+ sage: sr.add_round_key(D, K) == K + D
978
+ True
979
+ """
980
+ d = self.state_array(d)
981
+ key = self.state_array(key)
982
+
983
+ return d+key
984
+
985
+ def state_array(self, d=None):
986
+ """
987
+ Convert the parameter to a state array.
988
+
989
+ INPUT:
990
+
991
+ - ``d`` -- a matrix, a list, or a tuple (default: ``None``)
992
+
993
+ EXAMPLES::
994
+
995
+ sage: sr = mq.SR(2, 2, 2, 4)
996
+ sage: k = sr.base_ring()
997
+ sage: e1 = [k.from_integer(e) for e in range(2*2)]; e1
998
+ [0, 1, a, a + 1]
999
+ sage: e2 = sr.phi( Matrix(k, 2*2, 1, e1) )
1000
+ sage: sr.state_array(e1) # note the column major ordering
1001
+ [ 0 a]
1002
+ [ 1 a + 1]
1003
+ sage: sr.state_array(e2)
1004
+ [ 0 a]
1005
+ [ 1 a + 1]
1006
+
1007
+ ::
1008
+
1009
+ sage: sr.state_array()
1010
+ [0 0]
1011
+ [0 0]
1012
+ """
1013
+ r = self.r
1014
+ c = self.c
1015
+ e = self.e
1016
+ k = self.base_ring()
1017
+
1018
+ if d is None:
1019
+ return matrix(k, r, c)
1020
+
1021
+ if isinstance(d, Matrix):
1022
+ if d.nrows() == r*c*e:
1023
+ return matrix(k, c, r, self.antiphi(d).list()).transpose()
1024
+ elif d.ncols() == c and d.nrows() == r and d.base_ring() == k:
1025
+ return d
1026
+
1027
+ if isinstance(d, tuple([list, tuple])):
1028
+ return matrix(k, c, r, d).transpose()
1029
+
1030
+ def is_state_array(self, d):
1031
+ """
1032
+ Return ``True`` if ``d`` is a state array, i.e. has the correct
1033
+ dimensions and base field.
1034
+
1035
+ EXAMPLES::
1036
+
1037
+ sage: sr = mq.SR(2, 2, 4, 8)
1038
+ sage: k = sr.base_ring()
1039
+ sage: sr.is_state_array( matrix(k, 2, 4) )
1040
+ True
1041
+
1042
+ ::
1043
+
1044
+ sage: sr = mq.SR(2, 2, 4, 8)
1045
+ sage: k = sr.base_ring()
1046
+ sage: sr.is_state_array( matrix(k, 4, 4) )
1047
+ False
1048
+ """
1049
+ return isinstance(d, Matrix) and \
1050
+ d.nrows() == self.r and \
1051
+ d.ncols() == self.c and \
1052
+ d.base_ring() == self.base_ring()
1053
+
1054
+ def random_state_array(self, *args, **kwds):
1055
+ r"""
1056
+ Return a random element in ``MatrixSpace(self.base_ring(),
1057
+ self.r, self.c)``.
1058
+
1059
+ EXAMPLES::
1060
+
1061
+ sage: sr = mq.SR(2, 2, 2, 4)
1062
+ sage: sr.random_state_array().parent()
1063
+ Full MatrixSpace of 2 by 2 dense matrices over Finite Field in a of size 2^4
1064
+ """
1065
+ return random_matrix(self.base_ring(), self._r, self._c, *args, **kwds)
1066
+
1067
+ def random_vector(self, *args, **kwds):
1068
+ r"""
1069
+ Return a random vector as it might appear in the algebraic
1070
+ expression of ``self``.
1071
+
1072
+ EXAMPLES::
1073
+
1074
+ sage: mq.SR(2, 2, 2, 4).random_vector().parent()
1075
+ Full MatrixSpace of 16 by 1 dense matrices over Finite Field in a of size 2^4
1076
+
1077
+ .. NOTE::
1078
+
1079
+ `\phi` was already applied to the result.
1080
+ """
1081
+ return self.vector(self.random_state_array(*args, **kwds))
1082
+
1083
+ def random_element(self, elem_type='vector', *args, **kwds):
1084
+ """
1085
+ Return a random element for ``self``. Other arguments and keywords are
1086
+ passed to random_* methods.
1087
+
1088
+ INPUT:
1089
+
1090
+ - ``elem_type`` -- either 'vector' or 'state array' (default: ``'vector'``)
1091
+
1092
+ EXAMPLES::
1093
+
1094
+ sage: sr = mq.SR()
1095
+ sage: sr.random_element().parent()
1096
+ Full MatrixSpace of 4 by 1 dense matrices over Finite Field in a of size 2^4
1097
+ sage: sr.random_element('state_array').parent()
1098
+ Full MatrixSpace of 1 by 1 dense matrices over Finite Field in a of size 2^4
1099
+
1100
+ Passes extra positional or keyword arguments through::
1101
+
1102
+ sage: sr.random_element(density=0)
1103
+ [0]
1104
+ [0]
1105
+ [0]
1106
+ [0]
1107
+ """
1108
+ if elem_type == "vector":
1109
+ return self.random_vector(*args, **kwds)
1110
+ elif elem_type == "state_array":
1111
+ return self.random_state_array(*args, **kwds)
1112
+ else:
1113
+ raise TypeError("parameter type not understood")
1114
+
1115
+ def key_schedule(self, kj, i):
1116
+ """
1117
+ Return `k_i` for a given `i` and `k_j`
1118
+ with `j = i-1`.
1119
+
1120
+ EXAMPLES::
1121
+
1122
+ sage: sr = mq.SR(10, 4, 4, 8, star=True, allow_zero_inversions=True)
1123
+ sage: ki = sr.state_array()
1124
+ sage: for i in range(10):
1125
+ ....: ki = sr.key_schedule(ki, i+1)
1126
+ sage: print(sr.hex_str_matrix(ki))
1127
+ B4 3E 23 6F
1128
+ EF 92 E9 8F
1129
+ 5B E2 51 18
1130
+ CB 11 CF 8E
1131
+ """
1132
+ if i < 0:
1133
+ raise TypeError("i must be >= i")
1134
+
1135
+ if i == 0:
1136
+ return kj
1137
+
1138
+ r = self.r
1139
+ c = self.c
1140
+ F = self.base_ring()
1141
+ a = F.gen()
1142
+ SubByte = self.sub_byte
1143
+
1144
+ rc = matrix(F, r, c, ([a**(i-1)] * c) + [F(0)]*((r-1)*c) )
1145
+ ki = matrix(F, r, c)
1146
+
1147
+ if r == 1:
1148
+ s0 = SubByte(kj[0, c-1])
1149
+
1150
+ if c > 1:
1151
+ for q in range(c):
1152
+ ki[0, q] = s0 + sum([kj[0, t] for t in range(q+1) ])
1153
+ else:
1154
+ ki[0, 0] = s0
1155
+
1156
+ elif r == 2:
1157
+ s0 = SubByte(kj[1, c-1])
1158
+ s1 = SubByte(kj[0, c-1])
1159
+
1160
+ if c > 1:
1161
+ for q in range(c):
1162
+ ki[0, q] = s0 + sum([ kj[0, t] for t in range(q+1) ])
1163
+ ki[1, q] = s1 + sum([ kj[1, t] for t in range(q+1) ])
1164
+ else:
1165
+ ki[0, 0] = s0
1166
+ ki[1, 0] = s1
1167
+
1168
+ elif r == 4:
1169
+
1170
+ if self._aes_mode:
1171
+ s0 = SubByte(kj[1, c-1])
1172
+ s1 = SubByte(kj[2, c-1])
1173
+ s2 = SubByte(kj[3, c-1])
1174
+ s3 = SubByte(kj[0, c-1])
1175
+ else:
1176
+ s0 = SubByte(kj[3, c-1])
1177
+ s1 = SubByte(kj[2, c-1])
1178
+ s2 = SubByte(kj[1, c-1])
1179
+ s3 = SubByte(kj[0, c-1])
1180
+
1181
+ if c > 1:
1182
+ for q in range(c):
1183
+ ki[0, q] = s0 + sum([ kj[0, t] for t in range(q+1) ])
1184
+ ki[1, q] = s1 + sum([ kj[1, t] for t in range(q+1) ])
1185
+ ki[2, q] = s2 + sum([ kj[2, t] for t in range(q+1) ])
1186
+ ki[3, q] = s3 + sum([ kj[3, t] for t in range(q+1) ])
1187
+
1188
+ else:
1189
+ ki[0, 0] = s0
1190
+ ki[1, 0] = s1
1191
+ ki[2, 0] = s2
1192
+ ki[3, 0] = s3
1193
+ ki += rc
1194
+
1195
+ return ki
1196
+
1197
+ def __call__(self, P, K):
1198
+ r"""
1199
+ Encrypts the plaintext `P` using the key `K`.
1200
+
1201
+ Both must be given as state arrays or coercible to state arrays.
1202
+
1203
+ INPUT:
1204
+
1205
+ - ``P`` -- plaintext as state array or something coercible to a
1206
+ qstate array
1207
+
1208
+ - ``K`` -- key as state array or something coercible to a state
1209
+ array
1210
+
1211
+ TESTS:
1212
+
1213
+ The official AES test vectors::
1214
+
1215
+ sage: sr = mq.SR(10, 4, 4, 8, star=True, allow_zero_inversions=True)
1216
+ sage: k = sr.base_ring()
1217
+ sage: plaintext = sr.state_array([k.from_integer(e) for e in range(16)])
1218
+ sage: key = sr.state_array([k.from_integer(e) for e in range(16)])
1219
+ sage: print(sr.hex_str_matrix( sr(plaintext, key) ))
1220
+ 0A 41 F1 C6
1221
+ 94 6E C3 53
1222
+ 0B F0 94 EA
1223
+ B5 45 58 5A
1224
+
1225
+ Brian Gladman's development vectors (dev_vec.txt)::
1226
+
1227
+ sage: sr = mq.SR(10, 4, 4, 8, star=True, allow_zero_inversions=True, aes_mode=True)
1228
+ sage: k = sr.base_ring()
1229
+ sage: plain = '3243f6a8885a308d313198a2e0370734'
1230
+ sage: key = '2b7e151628aed2a6abf7158809cf4f3c'
1231
+ sage: from sage.misc.verbose import set_verbose
1232
+ sage: set_verbose(2)
1233
+ sage: cipher = sr(plain, key)
1234
+ R[01].start 193DE3BEA0F4E22B9AC68D2AE9F84808
1235
+ R[01].s_box D42711AEE0BF98F1B8B45DE51E415230
1236
+ R[01].s_row D4BF5D30E0B452AEB84111F11E2798E5
1237
+ R[01].m_col 046681E5E0CB199A48F8D37A2806264C
1238
+ R[01].k_sch A0FAFE1788542CB123A339392A6C7605
1239
+ R[02].start A49C7FF2689F352B6B5BEA43026A5049
1240
+ R[02].s_box 49DED28945DB96F17F39871A7702533B
1241
+ R[02].s_row 49DB873B453953897F02D2F177DE961A
1242
+ R[02].m_col 584DCAF11B4B5AACDBE7CAA81B6BB0E5
1243
+ R[02].k_sch F2C295F27A96B9435935807A7359F67F
1244
+ R[03].start AA8F5F0361DDE3EF82D24AD26832469A
1245
+ R[03].s_box AC73CF7BEFC111DF13B5D6B545235AB8
1246
+ R[03].s_row ACC1D6B8EFB55A7B1323CFDF457311B5
1247
+ R[03].m_col 75EC0993200B633353C0CF7CBB25D0DC
1248
+ R[03].k_sch 3D80477D4716FE3E1E237E446D7A883B
1249
+ R[04].start 486C4EEE671D9D0D4DE3B138D65F58E7
1250
+ R[04].s_box 52502F2885A45ED7E311C807F6CF6A94
1251
+ R[04].s_row 52A4C89485116A28E3CF2FD7F6505E07
1252
+ R[04].m_col 0FD6DAA9603138BF6FC0106B5EB31301
1253
+ R[04].k_sch EF44A541A8525B7FB671253BDB0BAD00
1254
+ R[05].start E0927FE8C86363C0D9B1355085B8BE01
1255
+ R[05].s_box E14FD29BE8FBFBBA35C89653976CAE7C
1256
+ R[05].s_row E1FB967CE8C8AE9B356CD2BA974FFB53
1257
+ R[05].m_col 25D1A9ADBD11D168B63A338E4C4CC0B0
1258
+ R[05].k_sch D4D1C6F87C839D87CAF2B8BC11F915BC
1259
+ R[06].start F1006F55C1924CEF7CC88B325DB5D50C
1260
+ R[06].s_box A163A8FC784F29DF10E83D234CD503FE
1261
+ R[06].s_row A14F3DFE78E803FC10D5A8DF4C632923
1262
+ R[06].m_col 4B868D6D2C4A8980339DF4E837D218D8
1263
+ R[06].k_sch 6D88A37A110B3EFDDBF98641CA0093FD
1264
+ R[07].start 260E2E173D41B77DE86472A9FDD28B25
1265
+ R[07].s_box F7AB31F02783A9FF9B4340D354B53D3F
1266
+ R[07].s_row F783403F27433DF09BB531FF54ABA9D3
1267
+ R[07].m_col 1415B5BF461615EC274656D7342AD843
1268
+ R[07].k_sch 4E54F70E5F5FC9F384A64FB24EA6DC4F
1269
+ R[08].start 5A4142B11949DC1FA3E019657A8C040C
1270
+ R[08].s_box BE832CC8D43B86C00AE1D44DDA64F2FE
1271
+ R[08].s_row BE3BD4FED4E1F2C80A642CC0DA83864D
1272
+ R[08].m_col 00512FD1B1C889FF54766DCDFA1B99EA
1273
+ R[08].k_sch EAD27321B58DBAD2312BF5607F8D292F
1274
+ R[09].start EA835CF00445332D655D98AD8596B0C5
1275
+ R[09].s_box 87EC4A8CF26EC3D84D4C46959790E7A6
1276
+ R[09].s_row 876E46A6F24CE78C4D904AD897ECC395
1277
+ R[09].m_col 473794ED40D4E4A5A3703AA64C9F42BC
1278
+ R[09].k_sch AC7766F319FADC2128D12941575C006E
1279
+ R[10].s_box E9098972CB31075F3D327D94AF2E2CB5
1280
+ R[10].s_row E9317DB5CB322C723D2E895FAF090794
1281
+ R[10].k_sch D014F9A8C9EE2589E13F0CC8B6630CA6
1282
+ R[10].output 3925841D02DC09FBDC118597196A0B32
1283
+ sage: set_verbose(0)
1284
+ """
1285
+ r, c, e = self.r, self.c, self.e
1286
+ F = self.base_ring()
1287
+
1288
+ if isinstance(P, str):
1289
+ P = self.state_array([F.from_integer(ZZ(P[i: i + 2], 16)) for i in range(0, len(P), 2)])
1290
+ if isinstance(K, str):
1291
+ K = self.state_array([F.from_integer(ZZ(K[i: i + 2], 16)) for i in range(0, len(K), 2)])
1292
+
1293
+ if self.is_state_array(P) and self.is_state_array(K):
1294
+ _type = self.state_array
1295
+ elif self.is_vector(P) and self.is_vector(K):
1296
+ _type = self.vector
1297
+ elif isinstance(P, (list,tuple)) and isinstance(K, (list,tuple)):
1298
+ if len(P) == len(K) == r*c:
1299
+ _type = self.state_array
1300
+ elif len(P) == len(K) == r*c*e:
1301
+ _type = self.vector
1302
+ else:
1303
+ raise TypeError("length %d or %d doesn't match either %d or %d" % (len(P),len(K),r*c,r*c*e))
1304
+ else:
1305
+ raise TypeError("plaintext or key parameter not understood")
1306
+
1307
+ P = self.state_array(P)
1308
+ K = self.state_array(K)
1309
+
1310
+ AddRoundKey = self.add_round_key
1311
+ SubBytes = self.sub_bytes
1312
+ MixColumns = self.mix_columns
1313
+ ShiftRows = self.shift_rows
1314
+ KeyExpansion = self.key_schedule
1315
+
1316
+ P = AddRoundKey(P, K)
1317
+
1318
+ for r in range(self._n-1):
1319
+ if get_verbose() >= 2:
1320
+ print("R[%02d].start %s" % (r+1, self.hex_str_vector(P)))
1321
+
1322
+ P = SubBytes(P)
1323
+ if get_verbose() >= 2:
1324
+ print("R[%02d].s_box %s" % (r+1, self.hex_str_vector(P)))
1325
+
1326
+ P = ShiftRows(P)
1327
+ if get_verbose() >= 2:
1328
+ print("R[%02d].s_row %s" % (r+1, self.hex_str_vector(P)))
1329
+
1330
+ P = MixColumns(P)
1331
+ if get_verbose() >= 2:
1332
+ print("R[%02d].m_col %s" % (r+1, self.hex_str_vector(P)))
1333
+
1334
+ K = KeyExpansion(K, r+1)
1335
+ if get_verbose() >= 2:
1336
+ print("R[%02d].k_sch %s" % (r+1, self.hex_str_vector(K)))
1337
+
1338
+ P = AddRoundKey(P, K)
1339
+
1340
+ P = SubBytes(P)
1341
+ if get_verbose() >= 2:
1342
+ print("R[%02d].s_box %s" % (self.n, self.hex_str_vector(P)))
1343
+
1344
+ P = ShiftRows(P)
1345
+ if get_verbose() >= 2:
1346
+ print("R[%02d].s_row %s" % (self.n, self.hex_str_vector(P)))
1347
+
1348
+ if not self._star:
1349
+ P = MixColumns(P)
1350
+ if get_verbose() >= 2:
1351
+ print("R[%02d].m_col %s" % (self.n, self.hex_str_vector(P)))
1352
+
1353
+ K = KeyExpansion(K, self._n)
1354
+ if get_verbose() >= 2:
1355
+ print("R[%02d].k_sch %s" % (self.n, self.hex_str_vector(K)))
1356
+
1357
+ P = AddRoundKey(P, K)
1358
+ if get_verbose() >= 2:
1359
+ print("R[%02d].output %s" % (self.n, self.hex_str_vector(P)))
1360
+
1361
+ return _type(P)
1362
+
1363
+ def hex_str(self, M, typ='matrix'):
1364
+ r"""
1365
+ Return a hex string for the provided AES state array/matrix.
1366
+
1367
+ INPUT:
1368
+
1369
+ - ``M`` -- state array
1370
+
1371
+ - ``typ`` -- controls what to return, either 'matrix'
1372
+ or 'vector' (default: ``'matrix'``)
1373
+
1374
+ EXAMPLES::
1375
+
1376
+ sage: sr = mq.SR(2, 2, 2, 4)
1377
+ sage: k = sr.base_ring()
1378
+ sage: A = matrix(k, 2, 2, [1, k.gen(), 0, k.gen()^2])
1379
+ sage: sr.hex_str(A)
1380
+ ' 1 2 \n 0 4 \n'
1381
+
1382
+ ::
1383
+
1384
+ sage: sr.hex_str(A, typ='vector')
1385
+ '1024'
1386
+ """
1387
+ if typ == "matrix":
1388
+ return self.hex_str_matrix(M)
1389
+ elif typ == "vector":
1390
+ return self.hex_str_vector(M)
1391
+ else:
1392
+ raise TypeError("parameter type must either be 'matrix' or 'vector'")
1393
+
1394
+ def hex_str_matrix(self, M):
1395
+ r"""
1396
+ Return a two-dimensional AES-like representation of the matrix M.
1397
+
1398
+ That is, show the finite field elements as hex strings.
1399
+
1400
+ INPUT:
1401
+
1402
+ - ``M`` -- an AES state array
1403
+
1404
+ EXAMPLES::
1405
+
1406
+ sage: sr = mq.SR(2, 2, 2, 4)
1407
+ sage: k = sr.base_ring()
1408
+ sage: A = matrix(k, 2, 2, [1, k.gen(), 0, k.gen()^2])
1409
+ sage: sr.hex_str_matrix(A)
1410
+ ' 1 2 \n 0 4 \n'
1411
+ """
1412
+ e = M.base_ring().degree()
1413
+ st = [""]
1414
+ for x in range(M.nrows()):
1415
+ for y in range(M.ncols()):
1416
+ if e == 8:
1417
+ st.append("%02X" % M[x, y].to_integer())
1418
+ else:
1419
+ st.append("%X" % M[x, y].to_integer())
1420
+ st.append("\n")
1421
+ return " ".join(st)
1422
+
1423
+ def hex_str_vector(self, M):
1424
+ """
1425
+ Return a one-dimensional AES-like representation of the matrix M.
1426
+
1427
+ That is, show the finite field elements as hex strings.
1428
+
1429
+ INPUT:
1430
+
1431
+ - ``M`` -- an AES state array
1432
+
1433
+ EXAMPLES::
1434
+
1435
+ sage: sr = mq.SR(2, 2, 2, 4)
1436
+ sage: k = sr.base_ring()
1437
+ sage: A = matrix(k, 2, 2, [1, k.gen(), 0, k.gen()^2])
1438
+ sage: sr.hex_str_vector(A)
1439
+ '1024'
1440
+ """
1441
+ e = M.base_ring().degree()
1442
+ st = [""]
1443
+ for y in range(M.ncols()):
1444
+ for x in range(M.nrows()):
1445
+ if e == 8:
1446
+ st.append("%02X" % M[x, y].to_integer())
1447
+ else:
1448
+ st.append("%X" % M[x, y].to_integer())
1449
+ #st.append("\n")
1450
+ return "".join(st)
1451
+
1452
+ def _insert_matrix_into_matrix(self, dst, src, row, col):
1453
+ """
1454
+ Insert matrix src into matrix dst starting at row and col.
1455
+
1456
+ INPUT:
1457
+
1458
+ - ``dst`` -- a matrix
1459
+
1460
+ - ``src`` -- a matrix
1461
+
1462
+ - ``row`` -- offset row
1463
+
1464
+ - ``col`` -- offset columns
1465
+
1466
+ EXAMPLES::
1467
+
1468
+ sage: sr = mq.SR(10, 4, 4, 4)
1469
+ sage: a = sr.k.gen()
1470
+ sage: A = sr.state_array() + 1; A
1471
+ [1 0 0 0]
1472
+ [0 1 0 0]
1473
+ [0 0 1 0]
1474
+ [0 0 0 1]
1475
+ sage: B = Matrix(sr.base_ring(), 2, 2, [0, a, a+1, a^2]); B
1476
+ [ 0 a]
1477
+ [a + 1 a^2]
1478
+ sage: sr._insert_matrix_into_matrix(A, B, 1, 1)
1479
+ [ 1 0 0 0]
1480
+ [ 0 0 a 0]
1481
+ [ 0 a + 1 a^2 0]
1482
+ [ 0 0 0 1]
1483
+ """
1484
+ for i in range(src.nrows()):
1485
+ for j in range(src.ncols()):
1486
+ dst[row+i, col+j] = src[i, j]
1487
+ return dst
1488
+
1489
+ def varformatstr(self, name, n=None, rc=None, e=None):
1490
+ r"""
1491
+ Return a format string which is understood by print et al.
1492
+
1493
+ If a numerical value is omitted, the default value of ``self``
1494
+ is used. The numerical values (``n``, ``rc``, ``e``) are used
1495
+ to determine the width of the respective fields in the format
1496
+ string.
1497
+
1498
+ INPUT:
1499
+
1500
+ - ``name`` -- name of the variable
1501
+ - ``n`` -- number of rounds (default: ``None``)
1502
+ - ``rc`` -- number of rows \* number of cols (default: ``None``)
1503
+ - ``e`` -- exponent of base field (default: ``None``)
1504
+
1505
+ EXAMPLES::
1506
+
1507
+ sage: sr = mq.SR(1, 2, 2, 4)
1508
+ sage: sr.varformatstr('x')
1509
+ 'x%01d%01d%01d'
1510
+ sage: sr.varformatstr('x', n=1000)
1511
+ 'x%03d%03d%03d'
1512
+ """
1513
+ if n is None:
1514
+ n = self.n
1515
+ if rc is None:
1516
+ rc = self.r * self.c
1517
+ if e is None:
1518
+ e = self.e
1519
+
1520
+ l = str(max([ len(str(rc-1)), len(str(n-1)), len(str(e-1)) ] ))
1521
+ if name not in ("k", "s"):
1522
+ pf = self._postfix
1523
+ else:
1524
+ pf = ""
1525
+ format_string = name + pf + "%0" + l + "d" + "%0" + l + "d" + "%0" + l + "d"
1526
+ return format_string
1527
+
1528
+ def varstr(self, name, nr, rc, e):
1529
+ """
1530
+ Return a string representing a variable for the small scale
1531
+ AES subject to the given constraints.
1532
+
1533
+ INPUT:
1534
+
1535
+ - ``name`` -- variable name
1536
+ - ``nr`` -- number of round to create variable strings for
1537
+ - ``rc`` -- row*column index in state array
1538
+ - ``e`` -- exponent of base field
1539
+
1540
+ EXAMPLES::
1541
+
1542
+ sage: sr = mq.SR(10, 1, 2, 4)
1543
+ sage: sr.varstr('x', 2, 1, 1)
1544
+ 'x211'
1545
+ """
1546
+ format_string = self.varformatstr(name, self.n, self.r*self.c, self.e)
1547
+ return format_string % (nr, rc, e)
1548
+
1549
+ def varstrs(self, name, nr, rc=None, e=None):
1550
+ """
1551
+ Return a list of strings representing variables in ``self``.
1552
+
1553
+ INPUT:
1554
+
1555
+ - ``name`` -- variable name
1556
+ - ``nr`` -- number of round to create variable strings for
1557
+ - ``rc`` -- number of rows * number of columns in the state array (default: ``None``)
1558
+ - ``e`` -- exponent of base field (default: ``None``)
1559
+
1560
+ EXAMPLES::
1561
+
1562
+ sage: sr = mq.SR(10, 1, 2, 4)
1563
+ sage: sr.varstrs('x', 2)
1564
+ ('x200', 'x201', 'x202', 'x203', 'x210', 'x211', 'x212', 'x213')
1565
+ """
1566
+ if rc is None:
1567
+ rc = self.r * self.c
1568
+
1569
+ if e is None:
1570
+ e = self.e
1571
+
1572
+ n = self._n
1573
+
1574
+ format_string = self.varformatstr(name, n, rc, e)
1575
+
1576
+ return tuple([format_string % (nr, rci, ei) for rci in range(rc) for ei in range(e)])
1577
+
1578
+ def vars(self, name, nr, rc=None, e=None):
1579
+ """
1580
+ Return a list of variables in ``self``.
1581
+
1582
+ INPUT:
1583
+
1584
+ - ``name`` -- variable name
1585
+ - ``nr`` -- number of round to create variable strings for
1586
+ - ``rc`` -- number of rounds * number of columns in the state array (default: ``None``)
1587
+ - ``e`` -- exponent of base field (default: ``None``)
1588
+
1589
+ EXAMPLES::
1590
+
1591
+ sage: sr = mq.SR(10, 1, 2, 4)
1592
+ sage: sr.vars('x', 2)
1593
+ (x200, x201, x202, x203, x210, x211, x212, x213)
1594
+ """
1595
+ gd = self.variable_dict()
1596
+ return tuple([gd[s] for s in self.varstrs(name, nr, rc, e)])
1597
+
1598
+ def variable_dict(self):
1599
+ """
1600
+ Return a dictionary to access variables in ``self.R`` by their
1601
+ names.
1602
+
1603
+ EXAMPLES::
1604
+
1605
+ sage: sr = mq.SR(1,1,1,4)
1606
+ sage: sr.variable_dict()
1607
+ {'k000': k000,
1608
+ 'k001': k001,
1609
+ 'k002': k002,
1610
+ 'k003': k003,
1611
+ 'k100': k100,
1612
+ 'k101': k101,
1613
+ 'k102': k102,
1614
+ 'k103': k103,
1615
+ 's000': s000,
1616
+ 's001': s001,
1617
+ 's002': s002,
1618
+ 's003': s003,
1619
+ 'w100': w100,
1620
+ 'w101': w101,
1621
+ 'w102': w102,
1622
+ 'w103': w103,
1623
+ 'x100': x100,
1624
+ 'x101': x101,
1625
+ 'x102': x102,
1626
+ 'x103': x103}
1627
+
1628
+ sage: sr = mq.SR(1,1,1,4,gf2=True)
1629
+ sage: sr.variable_dict() # needs sage.rings.polynomial.pbori
1630
+ {'k000': k000,
1631
+ 'k001': k001,
1632
+ 'k002': k002,
1633
+ 'k003': k003,
1634
+ 'k100': k100,
1635
+ 'k101': k101,
1636
+ 'k102': k102,
1637
+ 'k103': k103,
1638
+ 's000': s000,
1639
+ 's001': s001,
1640
+ 's002': s002,
1641
+ 's003': s003,
1642
+ 'w100': w100,
1643
+ 'w101': w101,
1644
+ 'w102': w102,
1645
+ 'w103': w103,
1646
+ 'x100': x100,
1647
+ 'x101': x101,
1648
+ 'x102': x102,
1649
+ 'x103': x103}
1650
+ """
1651
+ try:
1652
+ R,gd = self._variable_dict
1653
+ if R is self.R:
1654
+ return gd
1655
+ else:
1656
+ pass
1657
+ except AttributeError:
1658
+ pass
1659
+
1660
+ gd = self.R.gens_dict()
1661
+ self._variable_dict = self.R,gd
1662
+ return gd
1663
+
1664
+ def block_order(self):
1665
+ """
1666
+ Return a block order for ``self`` where each round is a block.
1667
+
1668
+ EXAMPLES::
1669
+
1670
+ sage: sr = mq.SR(2, 1, 1, 4)
1671
+ sage: sr.block_order()
1672
+ Block term order with blocks:
1673
+ (Degree lexicographic term order of length 16,
1674
+ Degree lexicographic term order of length 16,
1675
+ Degree lexicographic term order of length 4)
1676
+
1677
+ ::
1678
+
1679
+ sage: P = sr.ring(order='block')
1680
+ sage: print(P.repr_long())
1681
+ Polynomial Ring
1682
+ Base Ring : Finite Field in a of size 2^4
1683
+ Size : 36 Variables
1684
+ Block 0 : Ordering : deglex
1685
+ Names : k200, k201, k202, k203, x200, x201, x202, x203, w200, w201, w202, w203, s100, s101, s102, s103
1686
+ Block 1 : Ordering : deglex
1687
+ Names : k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003
1688
+ Block 2 : Ordering : deglex
1689
+ Names : k000, k001, k002, k003
1690
+ """
1691
+ r = self.r
1692
+ c = self.c
1693
+ e = self.e
1694
+ n = self.n
1695
+
1696
+ T = None
1697
+ for _n in range(n):
1698
+ T = TermOrder('deglex', r*e + 3*r*c*e ) + T
1699
+
1700
+ T += TermOrder('deglex', r*c*e)
1701
+
1702
+ return T
1703
+
1704
+ def ring(self, order=None, reverse_variables=None):
1705
+ r"""
1706
+ Construct a ring as a base ring for the polynomial system.
1707
+
1708
+ By default, variables are ordered in the reverse of their natural
1709
+ ordering, i.e. the reverse of as they appear.
1710
+
1711
+ INPUT:
1712
+
1713
+ - ``order`` -- a monomial ordering (default: ``None``)
1714
+ - ``reverse_variables`` -- reverse rounds of variables (default: ``True``)
1715
+
1716
+ The variable assignment is as follows:
1717
+
1718
+ - `k_{i,j,l}` -- subkey round `i` word `j` conjugate/bit `l`
1719
+ - `s_{i,j,l}` -- subkey inverse round `i` word `j` conjugate/bit `l`
1720
+ - `w_{i,j,l}` -- inversion input round `i` word `j` conjugate/bit `l`
1721
+ - `x_{i,j,l}` -- inversion output round `i` word `j` conjugate/bit `l`
1722
+
1723
+
1724
+ Note that the variables are ordered in column major ordering
1725
+ in the state array and that the bits are ordered in little
1726
+ endian ordering.
1727
+
1728
+ For example, if `x_{0,1,0}` is a variable over `\GF{2}` for
1729
+ `r=2` and `c=2` then refers to the *most* significant bit of
1730
+ the entry in the position (1,0) in the state array matrix.
1731
+
1732
+ EXAMPLES::
1733
+
1734
+ sage: sr = mq.SR(2, 1, 1, 4)
1735
+ sage: P = sr.ring(order='block')
1736
+ sage: print(P.repr_long())
1737
+ Polynomial Ring
1738
+ Base Ring : Finite Field in a of size 2^4
1739
+ Size : 36 Variables
1740
+ Block 0 : Ordering : deglex
1741
+ Names : k200, k201, k202, k203, x200, x201, x202, x203, w200, w201, w202, w203, s100, s101, s102, s103
1742
+ Block 1 : Ordering : deglex
1743
+ Names : k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003
1744
+ Block 2 : Ordering : deglex
1745
+ Names : k000, k001, k002, k003
1746
+ """
1747
+ r = self.r
1748
+ c = self.c
1749
+ e = self.e
1750
+ n = self.n
1751
+ if not self._gf2:
1752
+ k = self.base_ring()
1753
+ else:
1754
+ k = GF(2)
1755
+
1756
+ if order is not None:
1757
+ self._order = order
1758
+ if self._order == 'block':
1759
+ self._order = self.block_order()
1760
+
1761
+ if reverse_variables is None:
1762
+ reverse_variables = self._reverse_variables
1763
+
1764
+ if reverse_variables:
1765
+ process = reversed
1766
+ else:
1767
+ process = lambda x: x
1768
+
1769
+ if reverse_variables:
1770
+ names = []
1771
+ else:
1772
+ names = self.varstrs("k", 0, r*c, e)
1773
+
1774
+ for _n in process(list(range(n))):
1775
+ names += self.varstrs("k", _n+1, r*c, e)
1776
+ names += self.varstrs("x", _n+1, r*c, e)
1777
+ names += self.varstrs("w", _n+1, r*c, e)
1778
+ names += self.varstrs("s", _n, r, e)
1779
+
1780
+ if reverse_variables:
1781
+ names += self.varstrs("k", 0, r*c, e)
1782
+
1783
+ #from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing
1784
+
1785
+ if self._gf2 and self._polybori:
1786
+ return BooleanPolynomialRing(2*n*r*c*e + (n+1)*r*c*e + n*r*e, names, order=self._order)
1787
+ else:
1788
+ return PolynomialRing(k, 2*n*r*c*e + (n+1)*r*c*e + n*r*e, names, order=self._order)
1789
+
1790
+ def round_polynomials(self, i, plaintext=None, ciphertext=None):
1791
+ r"""
1792
+ Return list of polynomials for a given round `i`.
1793
+
1794
+ If ``i == 0`` a plaintext must be provided, if ``i == n`` a
1795
+ ciphertext must be provided.
1796
+
1797
+ INPUT:
1798
+
1799
+ - ``i`` -- round number
1800
+
1801
+ - ``plaintext`` -- plaintext (optional, mandatory in first round)
1802
+
1803
+ - ``ciphertext`` -- ciphertext (optional, mandatory in last round)
1804
+
1805
+ OUTPUT: tuple
1806
+
1807
+ EXAMPLES::
1808
+
1809
+ sage: sr = mq.SR(1, 1, 1, 4)
1810
+ sage: k = sr.base_ring()
1811
+ sage: p = [k.random_element() for _ in range(sr.r*sr.c)]
1812
+ sage: sr.round_polynomials(0, plaintext=p)
1813
+ (w100 + k000..., w101 + k001..., w102 + k002..., w103 + k003...)
1814
+ """
1815
+ r = self._r
1816
+ c = self._c
1817
+ e = self._e
1818
+ n = self._n
1819
+ R = self.R
1820
+
1821
+ M = self.M
1822
+
1823
+ _vars = self.vars
1824
+
1825
+ if i == 0:
1826
+ w1 = matrix(R, r*c*e, 1, _vars("w", 1, r*c, e))
1827
+ k0 = matrix(R, r*c*e, 1, _vars("k", 0, r*c, e))
1828
+ if isinstance(plaintext, (tuple, list)) and len(plaintext) == r*c:
1829
+ plaintext = matrix(R, r*c*e, 1, self.phi(plaintext))
1830
+ return tuple((w1 + k0 + plaintext).list())
1831
+
1832
+ elif i > 0 and i <= n:
1833
+
1834
+ if self._star and i == n:
1835
+ M = self.Mstar
1836
+
1837
+ xj = matrix(R, r*c*e, 1, _vars("x", i, r*c, e))
1838
+ ki = matrix(R, r*c*e, 1, _vars("k", i, r*c, e))
1839
+ rcon = matrix(R, r*c*e, 1, self.phi([self.sbox_constant()]*r*c))
1840
+
1841
+ if i < n:
1842
+ wj = matrix(R, r*c*e, 1, _vars("w", i+1, r*c, e))
1843
+ if i == n:
1844
+ if isinstance(ciphertext, (tuple, list)) and len(ciphertext) == r*c:
1845
+ ciphertext = matrix(R, r*c*e, 1, self.phi(ciphertext))
1846
+ wj = ciphertext
1847
+
1848
+ lin = (wj + ki + M * xj + rcon).list()
1849
+
1850
+ wi = matrix(R, r*c*e, 1, _vars("w", i, r*c, e))
1851
+ xi = matrix(R, r*c*e, 1, _vars("x", i, r*c, e))
1852
+ sbox = []
1853
+ sbox += self.inversion_polynomials(xi, wi, r*c*e)
1854
+ sbox += self.field_polynomials("x", i)
1855
+ sbox += self.field_polynomials("w", i)
1856
+ return tuple(lin + sbox)
1857
+
1858
+ def key_schedule_polynomials(self, i):
1859
+ r"""
1860
+ Return polynomials for the `i`-th round of the key
1861
+ schedule.
1862
+
1863
+ INPUT:
1864
+
1865
+ - ``i`` -- round (`0 \leq i \leq n`)
1866
+
1867
+ EXAMPLES::
1868
+
1869
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=False)
1870
+
1871
+ The `0`-th subkey is the user provided key, so only conjugacy
1872
+ relations or field polynomials are added.::
1873
+
1874
+ sage: sr.key_schedule_polynomials(0)
1875
+ (k000^2 + k000, k001^2 + k001, k002^2 + k002, k003^2 + k003)
1876
+
1877
+ The 1st subkey is derived from the user provided key according to
1878
+ the key schedule which is non-linear.::
1879
+
1880
+ sage: sr.key_schedule_polynomials(1)
1881
+ (k100 + s000 + s002 + s003,
1882
+ k101 + s000 + s001 + s003 + 1,
1883
+ k102 + s000 + s001 + s002 + 1,
1884
+ k103 + s001 + s002 + s003 + 1,
1885
+ k100^2 + k100, k101^2 + k101, k102^2 + k102, k103^2 + k103,
1886
+ s000^2 + s000, s001^2 + s001, s002^2 + s002, s003^2 + s003,
1887
+ s000*k000 + s000*k003 + s001*k002 + s002*k001 + s003*k000,
1888
+ s000*k000 + s000*k001 + s001*k000 + s001*k003 + s002*k002 + s003*k001,
1889
+ s000*k001 + s000*k002 + s001*k000 + s001*k001 + s002*k000 + s002*k003 + s003*k002,
1890
+ s000*k000 + s000*k001 + s000*k003 + s001*k001 + s002*k000 + s002*k002 + s003*k000 + k000,
1891
+ s000*k002 + s001*k000 + s001*k001 + s001*k003 + s002*k001 + s003*k000 + s003*k002 + k001,
1892
+ s000*k000 + s000*k001 + s000*k002 + s001*k002 + s002*k000 + s002*k001 + s002*k003 + s003*k001 + k002,
1893
+ s000*k001 + s001*k000 + s001*k002 + s002*k000 + s003*k001 + s003*k003 + k003,
1894
+ s000*k000 + s000*k002 + s000*k003 + s001*k000 + s001*k001 + s002*k002 + s003*k000 + s000,
1895
+ s000*k001 + s000*k003 + s001*k001 + s001*k002 + s002*k000 + s002*k003 + s003*k001 + s001,
1896
+ s000*k000 + s000*k002 + s001*k000 + s001*k002 + s001*k003 + s002*k000 + s002*k001 + s003*k002 + s002,
1897
+ s000*k001 + s000*k002 + s001*k000 + s001*k003 + s002*k001 + s003*k003 + s003,
1898
+ s000*k002 + s001*k001 + s002*k000 + s003*k003 + 1)
1899
+ """
1900
+ R = self.R
1901
+ r = self.r
1902
+ e = self.e
1903
+ c = self.c
1904
+ k = self.k
1905
+ a = k.gen()
1906
+
1907
+ if i < 0:
1908
+ raise TypeError("i must by >= 0")
1909
+
1910
+ if i == 0:
1911
+ return tuple(self.field_polynomials("k", i, r*c))
1912
+ else:
1913
+ L = self.lin_matrix(r)
1914
+ ki = matrix(R, r*c*e, 1, self.vars("k", i , r*c, e))
1915
+ kj = matrix(R, r*c*e, 1, self.vars("k", i-1, r*c, e))
1916
+ si = matrix(R, r*e, 1, self.vars("s", i-1, r, e))
1917
+
1918
+ rc = matrix(R, r*e, 1, self.phi([a**(i-1)] + [k(0)]*(r-1)) )
1919
+ d = matrix(R, r*e, 1, self.phi([self.sbox_constant()]*r) )
1920
+
1921
+ sbox = []
1922
+
1923
+ sbox += self.field_polynomials("k", i)
1924
+ sbox += self.field_polynomials("s", i-1, r)
1925
+
1926
+ if r == 1:
1927
+ sbox += self.inversion_polynomials(kj[(c - 1)*e:(c - 1)*e + e], si[0:e], e)
1928
+ if r == 2:
1929
+ sbox += self.inversion_polynomials( kj[(2*c - 1)*e : (2*c - 1)*e + e] , si[0:1*e], e )
1930
+ sbox += self.inversion_polynomials( kj[(2*c - 2)*e : (2*c - 2)*e + e] , si[e:2*e], e )
1931
+ if r == 4:
1932
+ if self._aes_mode:
1933
+ sbox += self.inversion_polynomials( kj[(4*c-3)*e : (4*c-3)*e + e] , si[0*e : 1*e] , e )
1934
+ sbox += self.inversion_polynomials( kj[(4*c-2)*e : (4*c-2)*e + e] , si[1*e : 2*e] , e )
1935
+ sbox += self.inversion_polynomials( kj[(4*c-1)*e : (4*c-1)*e + e] , si[2*e : 3*e] , e )
1936
+ sbox += self.inversion_polynomials( kj[(4*c-4)*e : (4*c-4)*e + e] , si[3*e : 4*e] , e )
1937
+ else:
1938
+ sbox += self.inversion_polynomials( kj[(4*c-1)*e : (4*c-1)*e + e] , si[0*e : 1*e] , e )
1939
+ sbox += self.inversion_polynomials( kj[(4*c-2)*e : (4*c-2)*e + e] , si[1*e : 2*e] , e )
1940
+ sbox += self.inversion_polynomials( kj[(4*c-3)*e : (4*c-3)*e + e] , si[2*e : 3*e] , e )
1941
+ sbox += self.inversion_polynomials( kj[(4*c-4)*e : (4*c-4)*e + e] , si[3*e : 4*e] , e )
1942
+
1943
+ si = L * si + d + rc
1944
+ Sum = matrix(R, r*e, 1)
1945
+ lin = []
1946
+ if c > 1:
1947
+ for q in range(c):
1948
+ t = list(range(r*e*(q) , r*e*(q+1)))
1949
+ Sum += kj.matrix_from_rows(t)
1950
+ lin += (ki.matrix_from_rows(t) + si + Sum).list()
1951
+
1952
+ else:
1953
+ lin += (ki + si).list()
1954
+ return tuple(lin + sbox)
1955
+
1956
+ def polynomial_system(self, P=None, K=None, C=None):
1957
+ """
1958
+ Return a polynomial system for this small scale AES variant for a
1959
+ given plaintext-key pair.
1960
+
1961
+ If neither ``P``, ``K`` nor ``C`` are provided, a random pair
1962
+ (``P``, ``K``) will be generated. If ``P`` and ``C`` are
1963
+ provided no ``K`` needs to be provided.
1964
+
1965
+ INPUT:
1966
+
1967
+ - ``P`` -- vector, list, or tuple (default: ``None``)
1968
+ - ``K`` -- vector, list, or tuple (default: ``None``)
1969
+ - ``C`` -- vector, list, or tuple (default: ``None``)
1970
+
1971
+ EXAMPLES::
1972
+
1973
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True)
1974
+ sage: P = sr.vector([0, 0, 1, 0])
1975
+ sage: K = sr.vector([1, 0, 0, 1])
1976
+ sage: F, s = sr.polynomial_system(P, K) # needs sage.rings.polynomial.pbori
1977
+
1978
+ This returns a polynomial system::
1979
+
1980
+ sage: F # needs sage.rings.polynomial.pbori
1981
+ Polynomial Sequence with 36 Polynomials in 20 Variables
1982
+
1983
+ and a solution::
1984
+
1985
+ sage: s # random -- maybe we need a better doctest here? # needs sage.rings.polynomial.pbori
1986
+ {k000: 1, k001: 0, k003: 1, k002: 0}
1987
+
1988
+ This solution is not the only solution that we can learn from the
1989
+ Groebner basis of the system.
1990
+
1991
+ ::
1992
+
1993
+ sage: F.groebner_basis()[-3:] # needs sage.rings.polynomial.pbori
1994
+ [k000 + 1, k001, k003 + 1]
1995
+
1996
+ In particular we have two solutions::
1997
+
1998
+ sage: len(F.ideal().variety()) # needs sage.rings.polynomial.pbori
1999
+ 2
2000
+
2001
+ In the following example we provide ``C`` explicitly::
2002
+
2003
+ sage: C = sr(P,K)
2004
+ sage: F,s = sr.polynomial_system(P=P, C=C) # needs sage.rings.polynomial.pbori
2005
+ sage: F # needs sage.rings.polynomial.pbori
2006
+ Polynomial Sequence with 36 Polynomials in 20 Variables
2007
+
2008
+ Alternatively, we can use symbols for the ``P`` and
2009
+ ``C``. First, we have to create a polynomial ring::
2010
+
2011
+ sage: # needs sage.rings.polynomial.pbori
2012
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True)
2013
+ sage: R = sr.R
2014
+ sage: vn = sr.varstrs("P",0,1,4) + R.variable_names() + sr.varstrs("C",0,1,4)
2015
+ sage: R = BooleanPolynomialRing(len(vn),vn)
2016
+ sage: sr.R = R
2017
+
2018
+
2019
+ Now, we can construct the purely symbolic equation system::
2020
+
2021
+ sage: # needs sage.rings.polynomial.pbori
2022
+ sage: C = sr.vars("C",0); C
2023
+ (C000, C001, C002, C003)
2024
+ sage: P = sr.vars("P",0)
2025
+ sage: F,s = sr.polynomial_system(P=P,C=C)
2026
+ sage: F
2027
+ Polynomial Sequence with 36 Polynomials in 28 Variables
2028
+ sage: F.part(0)
2029
+ (P000 + w100 + k000, P001 + w101 + k001, P002 + w102 + k002, P003 + w103 + k003)
2030
+ sage: F.part(-2)
2031
+ (k100 + x100 + x102 + x103 + C000, k101 + x100 + x101 + x103 + C001 + 1, ...)
2032
+
2033
+ We show that the (returned) key is a solution to the returned system::
2034
+
2035
+ sage: sr = mq.SR(3,4,4,8, star=True, gf2=True, polybori=True)
2036
+ sage: while True: # workaround (see :issue:`31891`) # needs sage.rings.polynomial.pbori
2037
+ ....: try:
2038
+ ....: F, s = sr.polynomial_system()
2039
+ ....: break
2040
+ ....: except ZeroDivisionError:
2041
+ ....: pass
2042
+ sage: F.subs(s).groebner_basis() # long time # needs sage.rings.polynomial.pbori
2043
+ Polynomial Sequence with 1248 Polynomials in 1248 Variables
2044
+ """
2045
+ plaintext = P
2046
+ key = K
2047
+ ciphertext = C
2048
+
2049
+ system = []
2050
+ n = self._n
2051
+
2052
+ data = []
2053
+
2054
+ R = self.R
2055
+ r,c,e = self.r,self.c,self.e
2056
+
2057
+ for d in (plaintext, key, ciphertext):
2058
+ if d is None:
2059
+ data.append( None )
2060
+ elif isinstance(d, (tuple, list)):
2061
+ if isinstance(d[0], int):
2062
+ d = [GF(2)(_) for _ in d]
2063
+ if len(d) == r*c*e and (d[0].parent() is R or d[0].parent() == R):
2064
+ data.append( matrix(R,r*c*e,1,d) )
2065
+ continue
2066
+ try:
2067
+ data.append( self.phi(self.state_array(d)) )
2068
+ except ValueError: # GF2 vectors maybe?
2069
+ data.append( self.vector(d) )
2070
+ elif self.is_state_array(d):
2071
+ data.append( self.phi(d) )
2072
+ elif self.is_vector(d):
2073
+ data.append( d )
2074
+ else:
2075
+ data.append( False )
2076
+
2077
+ plaintext, key, ciphertext = data
2078
+
2079
+ if plaintext is False:
2080
+ raise TypeError("type %s of P not understood" % (type(plaintext)))
2081
+ elif plaintext is None:
2082
+ plaintext = self.random_element("vector")
2083
+
2084
+ if key is None:
2085
+ key = self.random_element("vector")
2086
+ elif key is False and ciphertext is False:
2087
+ raise TypeError("type %s of K not understood" % (type(key)))
2088
+
2089
+ if ciphertext is None:
2090
+ ciphertext = self(plaintext, key)
2091
+ elif ciphertext is False:
2092
+ raise TypeError("type %s of C not understood" % (type(ciphertext)))
2093
+
2094
+ for i in range(n+1):
2095
+ system.append( self.round_polynomials(i, plaintext, ciphertext) )
2096
+ system.append( self.key_schedule_polynomials(i) )
2097
+
2098
+ if key is not None:
2099
+ K = dict(zip(self.vars("k", 0), key.list()))
2100
+ else:
2101
+ K = None
2102
+ return PolynomialSequence(self.R, system), K
2103
+
2104
+
2105
+ class SR_gf2n(SR_generic):
2106
+ r"""
2107
+ Small Scale Variants of the AES polynomial system constructor over
2108
+ `\GF{2^n}`.
2109
+ """
2110
+ def vector(self, d=None):
2111
+ """
2112
+ Construct a vector suitable for the algebraic representation of
2113
+ SR, i.e. BES.
2114
+
2115
+ INPUT:
2116
+
2117
+ - ``d`` -- values for vector, must be understood by ``self.phi``
2118
+ (default: ``None``)
2119
+
2120
+ EXAMPLES::
2121
+
2122
+ sage: sr = mq.SR()
2123
+ sage: sr
2124
+ SR(1,1,1,4)
2125
+ sage: k = sr.base_ring()
2126
+ sage: A = Matrix(k, 1, 1, [k.gen()])
2127
+ sage: sr.vector(A)
2128
+ [ a]
2129
+ [ a^2]
2130
+ [ a + 1]
2131
+ [a^2 + 1]
2132
+ """
2133
+ r = self.r
2134
+ c = self.c
2135
+ e = self.e
2136
+ k = self.base_ring()
2137
+
2138
+ if d is None:
2139
+ return matrix(k, r*c*e, 1)
2140
+ elif d.ncols() == c and d.nrows() == r and d.base_ring() == k:
2141
+ return matrix(k, r*c*e, 1, self.phi(d).transpose().list())
2142
+
2143
+ def is_vector(self, d):
2144
+ """
2145
+ Return ``True`` if ``d`` can be used as a vector for ``self``.
2146
+
2147
+ EXAMPLES::
2148
+
2149
+ sage: sr = mq.SR()
2150
+ sage: sr
2151
+ SR(1,1,1,4)
2152
+ sage: k = sr.base_ring()
2153
+ sage: A = Matrix(k, 1, 1, [k.gen()])
2154
+ sage: B = sr.vector(A)
2155
+ sage: sr.is_vector(A)
2156
+ False
2157
+ sage: sr.is_vector(B)
2158
+ True
2159
+ """
2160
+ return isinstance(d, Matrix) and \
2161
+ d.nrows() == self.r*self.c*self.e and \
2162
+ d.ncols() == 1 and \
2163
+ d.base_ring() == self.base_ring()
2164
+
2165
+ def phi(self, l):
2166
+ r"""
2167
+ The operation `\phi` from [MR2002]_.
2168
+
2169
+ Projects state arrays to their algebraic representation.
2170
+
2171
+ INPUT:
2172
+
2173
+ - ``l`` -- element to perform `\phi` on
2174
+
2175
+ EXAMPLES::
2176
+
2177
+ sage: sr = mq.SR(2, 1, 2, 4)
2178
+ sage: k = sr.base_ring()
2179
+ sage: A = matrix(k, 1, 2, [k.gen(), 0] )
2180
+ sage: sr.phi(A)
2181
+ [ a 0]
2182
+ [ a^2 0]
2183
+ [ a + 1 0]
2184
+ [a^2 + 1 0]
2185
+ """
2186
+ ret = []
2187
+ if isinstance(l, Matrix):
2188
+ for e in l.transpose().list():
2189
+ ret += [e**(2**i) for i in range(self.e)]
2190
+ else:
2191
+ for e in l:
2192
+ ret += [e**(2**i) for i in range(self.e)]
2193
+ if isinstance(l, list):
2194
+ return ret
2195
+ elif isinstance(l, tuple):
2196
+ return tuple(ret)
2197
+ elif isinstance(l, Matrix):
2198
+ return matrix(l.base_ring(), l.ncols(), l.nrows()*self.e, ret).transpose()
2199
+ else:
2200
+ raise TypeError
2201
+
2202
+ def antiphi(self, l):
2203
+ r"""
2204
+ The operation `\phi^{-1}` from [MR2002]_ or the inverse of ``self.phi``.
2205
+
2206
+ INPUT:
2207
+
2208
+ - ``l`` -- a vector in the sense of :meth:`is_vector`
2209
+
2210
+ EXAMPLES::
2211
+
2212
+ sage: sr = mq.SR()
2213
+ sage: A = sr.random_state_array()
2214
+ sage: sr.antiphi(sr.phi(A)) == A
2215
+ True
2216
+ """
2217
+ if isinstance(l, Matrix):
2218
+ ret = l.transpose().list()[0:-1:self.e]
2219
+ else:
2220
+ ret = l[0:-1:self.e]
2221
+
2222
+ if isinstance(l, list):
2223
+ return ret
2224
+ elif isinstance(l, tuple):
2225
+ return tuple(ret)
2226
+ elif isinstance(l, Matrix):
2227
+ return matrix(self.base_ring(), l.ncols(), l.nrows() // self.e,
2228
+ ret).transpose()
2229
+ else:
2230
+ raise TypeError
2231
+
2232
+ def shift_rows_matrix(self):
2233
+ """
2234
+ Return the ``ShiftRows`` matrix.
2235
+
2236
+ EXAMPLES::
2237
+
2238
+ sage: sr = mq.SR(1, 2, 2, 4)
2239
+ sage: s = sr.random_state_array()
2240
+ sage: r1 = sr.shift_rows(s)
2241
+ sage: r2 = sr.state_array( sr.shift_rows_matrix() * sr.vector(s) )
2242
+ sage: r1 == r2
2243
+ True
2244
+ """
2245
+ e = self.e
2246
+ r = self.r
2247
+ c = self.c
2248
+ k = self.base_ring()
2249
+ bs = r*c*e
2250
+ shift_rows = matrix(k, bs, bs)
2251
+ I = MatrixSpace(k, e, e)(1)
2252
+ for x in range(c):
2253
+ for y in range(r):
2254
+ _r = ((x*r)+y) * e
2255
+ _c = (((x*r)+((r+1)*y)) * e) % bs
2256
+ self._insert_matrix_into_matrix(shift_rows, I, _r, _c)
2257
+
2258
+ return shift_rows
2259
+
2260
+ def lin_matrix(self, length=None):
2261
+ """
2262
+ Return the ``Lin`` matrix.
2263
+
2264
+ If no ``length`` is provided, the standard state space size is
2265
+ used. The key schedule calls this method with an explicit
2266
+ length argument because only ``self.r`` S-Box applications are
2267
+ performed in the key schedule.
2268
+
2269
+ INPUT:
2270
+
2271
+ - ``length`` -- length of state space (default: ``None``)
2272
+
2273
+ EXAMPLES::
2274
+
2275
+ sage: sr = mq.SR(1, 1, 1, 4)
2276
+ sage: sr.lin_matrix()
2277
+ [ a^2 + 1 1 a^3 + a^2 a^2 + 1]
2278
+ [ a a 1 a^3 + a^2 + a + 1]
2279
+ [ a^3 + a a^2 a^2 1]
2280
+ [ 1 a^3 a + 1 a + 1]
2281
+ """
2282
+ r = self.r
2283
+ c = self.c
2284
+ e = self.e
2285
+ k = self.k
2286
+
2287
+ if length is None:
2288
+ length = r*c
2289
+
2290
+ lin = matrix(self.base_ring(), length*e, length*e)
2291
+ if e == 4:
2292
+ l = [k.from_integer(x) for x in (5, 1, 12, 5)]
2293
+ for k in range( 0, length ):
2294
+ for i in range(4):
2295
+ for j in range(4):
2296
+ lin[k*4+j, k*4+i] = l[(i-j) % 4] ** (2**j)
2297
+ elif e == 8:
2298
+ l = [k.from_integer(x) for x in (5, 9, 249, 37, 244, 1, 181, 143)]
2299
+ for k in range( 0, length ):
2300
+ for i in range(8):
2301
+ for j in range(8):
2302
+ lin[k*8+j, k*8+i] = l[(i-j) % 8] ** (2**j)
2303
+
2304
+ return lin
2305
+
2306
+ def mix_columns_matrix(self):
2307
+ """
2308
+ Return the ``MixColumns`` matrix.
2309
+
2310
+ EXAMPLES::
2311
+
2312
+ sage: sr = mq.SR(1, 2, 2, 4)
2313
+ sage: s = sr.random_state_array()
2314
+ sage: r1 = sr.mix_columns(s)
2315
+ sage: r2 = sr.state_array(sr.mix_columns_matrix() * sr.vector(s))
2316
+ sage: r1 == r2
2317
+ True
2318
+ """
2319
+
2320
+ def D(b):
2321
+ """
2322
+ Return the `e x e` matrix `D` with `b^i` along the
2323
+ diagonal.
2324
+
2325
+ EXAMPLES::
2326
+
2327
+ sage: sr = mq.SR(1, 2, 1, 4)
2328
+ sage: sr.mix_columns_matrix() # indirect doctest
2329
+ [ a + 1 0 0 0 a 0 0 0]
2330
+ [ 0 a^2 + 1 0 0 0 a^2 0 0]
2331
+ [ 0 0 a 0 0 0 a + 1 0]
2332
+ [ 0 0 0 a^2 0 0 0 a^2 + 1]
2333
+ [ a 0 0 0 a + 1 0 0 0]
2334
+ [ 0 a^2 0 0 0 a^2 + 1 0 0]
2335
+ [ 0 0 a + 1 0 0 0 a 0]
2336
+ [ 0 0 0 a^2 + 1 0 0 0 a^2]
2337
+ """
2338
+ D = matrix(self.base_ring(), self._e, self._e)
2339
+ for i in range(self._e):
2340
+ D[i, i] = b**(2**i)
2341
+ return D
2342
+
2343
+ r = self.r
2344
+ c = self.c
2345
+ e = self.e
2346
+ k = self.k
2347
+ a = k.gen()
2348
+
2349
+ M = matrix(k, r*e, r*e)
2350
+
2351
+ if r == 1:
2352
+ self._insert_matrix_into_matrix(M, D(1), 0, 0)
2353
+
2354
+ elif r == 2:
2355
+ self._insert_matrix_into_matrix(M, D(a+1), 0, 0)
2356
+ self._insert_matrix_into_matrix(M, D(a+1), e, e)
2357
+ self._insert_matrix_into_matrix(M, D(a), e, 0)
2358
+ self._insert_matrix_into_matrix(M, D(a), 0, e)
2359
+
2360
+ elif r == 4:
2361
+ self._insert_matrix_into_matrix(M, D(a), 0, 0)
2362
+ self._insert_matrix_into_matrix(M, D(a), e, e)
2363
+ self._insert_matrix_into_matrix(M, D(a), 2*e, 2*e)
2364
+ self._insert_matrix_into_matrix(M, D(a), 3*e, 3*e)
2365
+
2366
+ self._insert_matrix_into_matrix(M, D(a+1), 0, e)
2367
+ self._insert_matrix_into_matrix(M, D(a+1), e, 2*e)
2368
+ self._insert_matrix_into_matrix(M, D(a+1), 2*e, 3*e)
2369
+ self._insert_matrix_into_matrix(M, D(a+1), 3*e, 0)
2370
+
2371
+ self._insert_matrix_into_matrix(M, D(1), 0, 2*e)
2372
+ self._insert_matrix_into_matrix(M, D(1), e, 3*e)
2373
+ self._insert_matrix_into_matrix(M, D(1), 2*e, 0)
2374
+ self._insert_matrix_into_matrix(M, D(1), 3*e, 1*e)
2375
+
2376
+ self._insert_matrix_into_matrix(M, D(1), 0, 3*e)
2377
+ self._insert_matrix_into_matrix(M, D(1), e, 0)
2378
+ self._insert_matrix_into_matrix(M, D(1), 2*e, 1*e)
2379
+ self._insert_matrix_into_matrix(M, D(1), 3*e, 2*e)
2380
+
2381
+ mix_columns = matrix(k, r*c*e, r*c*e)
2382
+
2383
+ for i in range(c):
2384
+ self._insert_matrix_into_matrix(mix_columns, M, r*e*i, r*e*i)
2385
+
2386
+ return mix_columns
2387
+
2388
+ def inversion_polynomials(self, xi, wi, length):
2389
+ """
2390
+ Return polynomials to represent the inversion in the AES S-Box.
2391
+
2392
+ INPUT:
2393
+
2394
+ - ``xi`` -- output variables
2395
+
2396
+ - ``wi`` -- input variables
2397
+
2398
+ - ``length`` -- length of both lists
2399
+
2400
+ EXAMPLES::
2401
+
2402
+ sage: sr = mq.SR(1, 1, 1, 8)
2403
+ sage: R = sr.ring()
2404
+ sage: xi = Matrix(R, 8, 1, sr.vars('x', 1))
2405
+ sage: wi = Matrix(R, 8, 1, sr.vars('w', 1))
2406
+ sage: sr.inversion_polynomials(xi, wi, 8)
2407
+ [x100*w100 + 1,
2408
+ x101*w101 + 1,
2409
+ x102*w102 + 1,
2410
+ x103*w103 + 1,
2411
+ x104*w104 + 1,
2412
+ x105*w105 + 1,
2413
+ x106*w106 + 1,
2414
+ x107*w107 + 1]
2415
+ """
2416
+ return [xi[j, 0]*wi[j, 0] + 1 for j in range(length)]
2417
+
2418
+ def field_polynomials(self, name, i, l=None):
2419
+ r"""
2420
+ Return list of conjugacy polynomials for a given round ``i``
2421
+ and name ``name``.
2422
+
2423
+ INPUT:
2424
+
2425
+ - ``name`` -- variable name
2426
+ - ``i`` -- round number
2427
+ - ``l`` -- r\*c (default: ``None``)
2428
+
2429
+ EXAMPLES::
2430
+
2431
+ sage: sr = mq.SR(3, 1, 1, 8)
2432
+ sage: sr.field_polynomials('x', 2)
2433
+ [x200^2 + x201,
2434
+ x201^2 + x202,
2435
+ x202^2 + x203,
2436
+ x203^2 + x204,
2437
+ x204^2 + x205,
2438
+ x205^2 + x206,
2439
+ x206^2 + x207,
2440
+ x207^2 + x200]
2441
+ """
2442
+ r = self._r
2443
+ c = self._c
2444
+ e = self._e
2445
+
2446
+ if l is None:
2447
+ l = r*c
2448
+
2449
+ _vars = self.vars(name, i, l, e)
2450
+ return [_vars[e*j+k]**2 - _vars[e*j+(k+1) % e] for j in range(l) for k in range(e)]
2451
+
2452
+
2453
+ class SR_gf2(SR_generic):
2454
+ def __init__(self, n=1, r=1, c=1, e=4, star=False, **kwargs):
2455
+ r"""
2456
+ Small Scale Variants of the AES polynomial system constructor over
2457
+ `\GF{2}`. See help for SR.
2458
+
2459
+ EXAMPLES::
2460
+
2461
+ sage: sr = mq.SR(gf2=True)
2462
+ sage: sr
2463
+ SR(1,1,1,4)
2464
+ """
2465
+ SR_generic.__init__(self, n, r, c, e, star, **kwargs)
2466
+ self._correct_only = kwargs.get("correct_only", False)
2467
+ self._biaffine_only = kwargs.get("biaffine_only", True)
2468
+
2469
+ def vector(self, d=None):
2470
+ """
2471
+ Construct a vector suitable for the algebraic representation of
2472
+ SR.
2473
+
2474
+ INPUT:
2475
+
2476
+ - ``d`` -- values for vector (default: ``None``)
2477
+
2478
+ EXAMPLES::
2479
+
2480
+ sage: sr = mq.SR(gf2=True)
2481
+ sage: sr
2482
+ SR(1,1,1,4)
2483
+ sage: k = sr.base_ring()
2484
+ sage: A = Matrix(k, 1, 1, [k.gen()])
2485
+ sage: sr.vector(A)
2486
+ [0]
2487
+ [0]
2488
+ [1]
2489
+ [0]
2490
+ """
2491
+ r = self.r
2492
+ c = self.c
2493
+ e = self.e
2494
+ k = GF(2)
2495
+
2496
+ if d is None:
2497
+ return matrix(k, r*c*e, 1)
2498
+ elif isinstance(d, Matrix) and d.ncols() == c and d.nrows() == r and d.base_ring() == self.k:
2499
+ l = flatten([self.phi(x) for x in d.transpose().list()], (Vector_modn_dense,list,tuple))
2500
+ return matrix(k, r*c*e, 1, l)
2501
+ elif isinstance(d, (list, tuple)):
2502
+ if len(d) == self.r*self.c:
2503
+ l = flatten([self.phi(x) for x in d], (Vector_modn_dense,list,tuple))
2504
+ return matrix(k, r*c*e, 1, l)
2505
+ elif len(d) == self.r*self.c*self.e:
2506
+ return matrix(k, r*c*e, 1, d)
2507
+ else:
2508
+ raise TypeError
2509
+ else:
2510
+ raise TypeError
2511
+
2512
+ def is_vector(self, d):
2513
+ """
2514
+ Return ``True`` if the given matrix satisfies the conditions
2515
+ for a vector as it appears in the algebraic expression of
2516
+ ``self``.
2517
+
2518
+ INPUT:
2519
+
2520
+ - ``d`` -- matrix
2521
+
2522
+ EXAMPLES::
2523
+
2524
+ sage: sr = mq.SR(gf2=True)
2525
+ sage: sr
2526
+ SR(1,1,1,4)
2527
+ sage: k = sr.base_ring()
2528
+ sage: A = Matrix(k, 1, 1, [k.gen()])
2529
+ sage: B = sr.vector(A)
2530
+ sage: sr.is_vector(A)
2531
+ False
2532
+ sage: sr.is_vector(B)
2533
+ True
2534
+ """
2535
+ return isinstance(d, Matrix) and \
2536
+ d.nrows() == self.r*self.c*self.e and \
2537
+ d.ncols() == 1 and \
2538
+ d.base_ring() == GF(2)
2539
+
2540
+ def phi(self, l, diffusion_matrix=False):
2541
+ r"""
2542
+ The operation `\phi` from [MR2002]_.
2543
+
2544
+ Given a list/matrix of elements in `\GF{2^e}`, return a
2545
+ matching list/matrix of elements in `\GF{2}`.
2546
+
2547
+ INPUT:
2548
+
2549
+ - ``l`` -- element to perform `\phi` on
2550
+ - ``diffusion_matrix`` -- if ``True``, the given matrix ``l`` is
2551
+ transformed to a matrix which performs the same operation
2552
+ over `\GF{2}` as ``l`` over `\GF{2^n}` (default: ``False``).
2553
+
2554
+ EXAMPLES::
2555
+
2556
+ sage: sr = mq.SR(2, 1, 2, 4, gf2=True)
2557
+ sage: k = sr.base_ring()
2558
+ sage: A = matrix(k, 1, 2, [k.gen(), 0] )
2559
+ sage: sr.phi(A) # needs sage.libs.gap
2560
+ [0 0]
2561
+ [0 0]
2562
+ [1 0]
2563
+ [0 0]
2564
+ """
2565
+ ret = []
2566
+ r, c, e = self.r, self.c, self.e
2567
+
2568
+ # handle diffusion layer matrices first
2569
+ if isinstance(l, Matrix) and diffusion_matrix and \
2570
+ l.nrows() == r*c and l.ncols() == r*c and \
2571
+ l.base_ring() == self.k:
2572
+ B = matrix(GF(2), r*c*e, r*c*e)
2573
+ for x in range(r*c):
2574
+ for y in range(r*c):
2575
+ T = self._mul_matrix(l[x, y])
2576
+ self._insert_matrix_into_matrix(B, T, x*e, y*e)
2577
+ return B
2578
+
2579
+ # ground field elements
2580
+ if l in self.k:
2581
+ return list(reversed(l._vector_()))
2582
+
2583
+ # remaining matrices
2584
+ if isinstance(l, Matrix):
2585
+ for x in l.transpose().list():
2586
+ ret += list(reversed(x._vector_()))
2587
+ # or lists
2588
+ else:
2589
+ for x in l:
2590
+ ret += list(reversed(x._vector_()))
2591
+
2592
+ if isinstance(l, list):
2593
+ return ret
2594
+ elif isinstance(l, tuple):
2595
+ return tuple(ret)
2596
+ elif isinstance(l, Matrix):
2597
+ return matrix(GF(2), l.ncols(), l.nrows()*self.e, ret).transpose()
2598
+ else:
2599
+ raise TypeError
2600
+
2601
+ def antiphi(self, l):
2602
+ r"""
2603
+ The operation `\phi^{-1}` from [MR2002]_ or the inverse of ``self.phi``.
2604
+
2605
+ INPUT:
2606
+
2607
+ - ``l`` -- a vector in the sense of ``self.is_vector``
2608
+
2609
+ EXAMPLES::
2610
+
2611
+ sage: sr = mq.SR(gf2=True)
2612
+ sage: A = sr.random_state_array()
2613
+ sage: sr.antiphi(sr.phi(A)) == A # needs sage.libs.gap
2614
+ True
2615
+ """
2616
+ e = self.e
2617
+ V = self.k.vector_space(map=False)
2618
+
2619
+ if isinstance(l, Matrix):
2620
+ l2 = l.transpose().list()
2621
+ else:
2622
+ l2 = l
2623
+
2624
+ ret = []
2625
+ for i in range(0, len(l2), e):
2626
+ ret.append( self.k(V(list(reversed(l2[i:i+e])))) )
2627
+
2628
+ if isinstance(l, list):
2629
+ return ret
2630
+ elif isinstance(l, tuple):
2631
+ return tuple(ret)
2632
+ elif isinstance(l, Matrix):
2633
+ return matrix(self.base_ring(), self.r * self.c, 1, ret)
2634
+ else:
2635
+ raise TypeError
2636
+
2637
+ def shift_rows_matrix(self):
2638
+ """
2639
+ Return the ``ShiftRows`` matrix.
2640
+
2641
+ EXAMPLES::
2642
+
2643
+ sage: sr = mq.SR(1, 2, 2, 4, gf2=True)
2644
+ sage: s = sr.random_state_array()
2645
+ sage: r1 = sr.shift_rows(s)
2646
+ sage: r2 = sr.state_array( sr.shift_rows_matrix() * sr.vector(s) )
2647
+ sage: r1 == r2
2648
+ True
2649
+ """
2650
+ r = self.r
2651
+ c = self.c
2652
+ k = self.k
2653
+ bs = r*c
2654
+ shift_rows = matrix(k, r*c, r*c)
2655
+ for x in range(c):
2656
+ for y in range(r):
2657
+ _r = ((x*r)+y)
2658
+ _c = ((x*r)+((r+1)*y)) % bs
2659
+ shift_rows[_r, _c] = 1
2660
+ return self.phi(shift_rows, diffusion_matrix=True)
2661
+
2662
+ def mix_columns_matrix(self):
2663
+ """
2664
+ Return the ``MixColumns`` matrix.
2665
+
2666
+ EXAMPLES::
2667
+
2668
+ sage: sr = mq.SR(1, 2, 2, 4, gf2=True)
2669
+ sage: s = sr.random_state_array()
2670
+ sage: r1 = sr.mix_columns(s)
2671
+ sage: r2 = sr.state_array(sr.mix_columns_matrix() * sr.vector(s))
2672
+ sage: r1 == r2
2673
+ True
2674
+ """
2675
+ r = self.r
2676
+ c = self.c
2677
+ k = self.k
2678
+ a = k.gen()
2679
+
2680
+ if r == 1:
2681
+ M = matrix(k, r, r, 1)
2682
+
2683
+ elif r == 2:
2684
+ M = matrix(k, r, r, [a+1, a, a, a+1])
2685
+
2686
+ elif r == 4:
2687
+ M = matrix(k, r, [a, a+1, 1, 1,
2688
+ 1, a, a+1, 1,
2689
+ 1, 1, a, a+1,
2690
+ a+1, 1, 1, a])
2691
+
2692
+ mix_columns = matrix(k, r*c, r*c)
2693
+
2694
+ for i in range(c):
2695
+ self._insert_matrix_into_matrix(mix_columns, M, r*i, r*i)
2696
+
2697
+ return self.phi(mix_columns, diffusion_matrix=True)
2698
+
2699
+ def lin_matrix(self, length=None):
2700
+ """
2701
+ Return the ``Lin`` matrix.
2702
+
2703
+ If no ``length`` is provided, the standard state space size is
2704
+ used. The key schedule calls this method with an explicit
2705
+ length argument because only ``self.r`` S-Box applications are
2706
+ performed in the key schedule.
2707
+
2708
+ INPUT:
2709
+
2710
+ - ``length`` -- length of state space (default: ``None``)
2711
+
2712
+ EXAMPLES::
2713
+
2714
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True)
2715
+ sage: sr.lin_matrix()
2716
+ [1 0 1 1]
2717
+ [1 1 0 1]
2718
+ [1 1 1 0]
2719
+ [0 1 1 1]
2720
+ """
2721
+ r, c, e = self.r, self.c, self.e
2722
+
2723
+ if length is None:
2724
+ length = r*c
2725
+
2726
+ if e == 8:
2727
+ Z = matrix(GF(2), 8, 8, [1, 0, 0, 0, 1, 1, 1, 1,
2728
+ 1, 1, 0, 0, 0, 1, 1, 1,
2729
+ 1, 1, 1, 0, 0, 0, 1, 1,
2730
+ 1, 1, 1, 1, 0, 0, 0, 1,
2731
+ 1, 1, 1, 1, 1, 0, 0, 0,
2732
+ 0, 1, 1, 1, 1, 1, 0, 0,
2733
+ 0, 0, 1, 1, 1, 1, 1, 0,
2734
+ 0, 0, 0, 1, 1, 1, 1, 1])
2735
+ else:
2736
+ Z = matrix(GF(2), 4, 4, [1, 1, 1, 0,
2737
+ 0, 1, 1, 1,
2738
+ 1, 0, 1, 1,
2739
+ 1, 1, 0, 1])
2740
+
2741
+ Z = Z.transpose() # account for endianess mismatch
2742
+
2743
+ lin = matrix(GF(2), length*e, length*e)
2744
+
2745
+ for i in range(length):
2746
+ self._insert_matrix_into_matrix(lin, Z, i*e, i*e)
2747
+ return lin
2748
+
2749
+ def _mul_matrix(self, x):
2750
+ r"""
2751
+ Given an element `x` in self.base_ring(), return a matrix
2752
+ which performs the same operation on a when interpreted over
2753
+ `\GF{2^e}` as `x` over `\GF{2^e}`.
2754
+
2755
+ INPUT:
2756
+
2757
+ - ``x`` -- an element in self.base_ring()
2758
+
2759
+ EXAMPLES::
2760
+
2761
+ sage: sr = mq.SR(gf2=True)
2762
+ sage: a = sr.k.gen()
2763
+ sage: A = sr._mul_matrix(a^2+1)
2764
+ sage: sr.antiphi( A * sr.vector([a+1]) )
2765
+ [a^3 + a^2 + a + 1]
2766
+
2767
+ ::
2768
+
2769
+ sage: (a^2 + 1)*(a+1)
2770
+ a^3 + a^2 + a + 1
2771
+ """
2772
+ k = self.k
2773
+ e = self.e
2774
+ a = k.gen()
2775
+
2776
+ columns = [list(reversed((x * a**i)._vector_()))
2777
+ for i in reversed(range(e))]
2778
+ return matrix(GF(2), e, e, columns).transpose()
2779
+
2780
+ def _square_matrix(self):
2781
+ """
2782
+ Return a matrix of dimension self.e x self.e which performs the
2783
+ squaring operation over `GF(2^n)` on vectors of length e.
2784
+
2785
+ EXAMPLES::
2786
+
2787
+ sage: sr = mq.SR(gf2=True)
2788
+ sage: a = sr.k.gen()
2789
+ sage: S = sr._square_matrix()
2790
+ sage: sr.antiphi( S * sr.vector([a^3+1]) )
2791
+ [a^3 + a^2 + 1]
2792
+
2793
+ ::
2794
+
2795
+ sage: (a^3 + 1)^2
2796
+ a^3 + a^2 + 1
2797
+ """
2798
+ a = self.k.gen()
2799
+ e = self.e
2800
+
2801
+ columns = []
2802
+ for i in reversed(range(e)):
2803
+ columns.append( list(reversed(((a**i)**2)._vector_())) )
2804
+ return matrix(GF(2), e , e, columns).transpose()
2805
+
2806
+ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, correct_only=None):
2807
+ """
2808
+ Return inversion polynomials of a single S-Box.
2809
+
2810
+ INPUT:
2811
+
2812
+ - ``xi`` -- output variables
2813
+ - ``wi`` -- input variables
2814
+ - ``length`` -- length of both lists
2815
+
2816
+ EXAMPLES::
2817
+
2818
+ sage: sr = mq.SR(1, 1, 1, 8, gf2=True)
2819
+ sage: len(sr.inversion_polynomials_single_sbox())
2820
+ 24
2821
+ sage: len(sr.inversion_polynomials_single_sbox(correct_only=True))
2822
+ 23
2823
+ sage: len(sr.inversion_polynomials_single_sbox(biaffine_only=False))
2824
+ 40
2825
+ sage: len(sr.inversion_polynomials_single_sbox(biaffine_only=False, correct_only=True))
2826
+ 39
2827
+
2828
+
2829
+ sage: sr = mq.SR(1, 1, 1, 8, gf2=True)
2830
+ sage: l0 = sr.inversion_polynomials_single_sbox(); len(l0)
2831
+ 24
2832
+ sage: l1 = sr.inversion_polynomials_single_sbox(correct_only=True); len(l1)
2833
+ 23
2834
+ sage: l2 = sr.inversion_polynomials_single_sbox(biaffine_only=False); len(l2)
2835
+ 40
2836
+ sage: l3 = sr.inversion_polynomials_single_sbox(biaffine_only=False, correct_only=True); len(l3)
2837
+ 39
2838
+
2839
+ sage: set(l0) == set(sr._inversion_polynomials_single_sbox())
2840
+ True
2841
+ sage: set(l1) == set(sr._inversion_polynomials_single_sbox(correct_only=True))
2842
+ True
2843
+ sage: set(l2) == set(sr._inversion_polynomials_single_sbox(biaffine_only=False))
2844
+ True
2845
+ sage: set(l3) == set(sr._inversion_polynomials_single_sbox(biaffine_only=False, correct_only=True))
2846
+ True
2847
+
2848
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True)
2849
+ sage: l0 = sr.inversion_polynomials_single_sbox(); len(l0)
2850
+ 12
2851
+ sage: l1 = sr.inversion_polynomials_single_sbox(correct_only=True); len(l1)
2852
+ 11
2853
+ sage: l2 = sr.inversion_polynomials_single_sbox(biaffine_only=False); len(l2)
2854
+ 20
2855
+ sage: l3 = sr.inversion_polynomials_single_sbox(biaffine_only=False, correct_only=True); len(l3)
2856
+ 19
2857
+
2858
+ sage: set(l0) == set(sr._inversion_polynomials_single_sbox())
2859
+ True
2860
+ sage: set(l1) == set(sr._inversion_polynomials_single_sbox(correct_only=True))
2861
+ True
2862
+ sage: set(l2) == set(sr._inversion_polynomials_single_sbox(biaffine_only=False))
2863
+ True
2864
+ sage: set(l3) == set(sr._inversion_polynomials_single_sbox(biaffine_only=False, correct_only=True))
2865
+ True
2866
+ """
2867
+ e = self.e
2868
+
2869
+ if biaffine_only is None:
2870
+ biaffine_only = self._biaffine_only
2871
+ if correct_only is None:
2872
+ correct_only = self._correct_only
2873
+
2874
+ if x is None and w is None:
2875
+ # make sure it prints like in the book.
2876
+ names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))]
2877
+ P = PolynomialRing(GF(2), e*2, names, order='lex')
2878
+ x = P.gens()[e:]
2879
+ w = P.gens()[:e]
2880
+ else:
2881
+ if isinstance(x, (tuple, list)):
2882
+ P = x[0].parent()
2883
+ elif isinstance(x, Matrix):
2884
+ P = x.base_ring()
2885
+ else:
2886
+ raise TypeError("x not understood")
2887
+
2888
+ if isinstance(x, Matrix):
2889
+ x = x.column(0).list()
2890
+ if isinstance(w, Matrix):
2891
+ w = w.column(0).list()
2892
+
2893
+ if e == 4:
2894
+ w3,w2,w1,w0 = w
2895
+ x3,x2,x1,x0 = x
2896
+
2897
+ l = [w3*x3 + w3*x0 + w2*x1 + w1*x2 + w0*x3,
2898
+ w3*x3 + w3*x2 + w2*x3 + w2*x0 + w1*x1 + w0*x2,
2899
+ w3*x2 + w3*x1 + w2*x3 + w2*x2 + w1*x3 + w1*x0 + w0*x1,
2900
+ w3*x3 + w3*x2 + w3*x0 + w2*x2 + w1*x3 + w1*x1 + w0*x3 + x3,
2901
+ w3*x1 + w2*x3 + w2*x2 + w2*x0 + w1*x2 + w0*x3 + w0*x1 + x2,
2902
+ w3*x3 + w3*x2 + w3*x1 + w2*x1 + w1*x3 + w1*x2 + w1*x0 + w0*x2 + x1,
2903
+ w3*x2 + w2*x3 + w2*x1 + w1*x3 + w0*x2 + w0*x0 + x0,
2904
+ w3*x3 + w3*x1 + w3*x0 + w3 + w2*x3 + w2*x2 + w1*x1 + w0*x3,
2905
+ w3*x2 + w3*x0 + w2*x2 + w2*x1 + w2 + w1*x3 + w1*x0 + w0*x2,
2906
+ w3*x3 + w3*x1 + w2*x3 + w2*x1 + w2*x0 + w1*x3 + w1*x2 + w1 + w0*x1,
2907
+ w3*x2 + w3*x1 + w2*x3 + w2*x0 + w1*x2 + w0*x0 + w0]
2908
+
2909
+ if not correct_only:
2910
+ l.append(w3*x1 + w2*x2 + w1*x3 + w0*x0 + 1)
2911
+
2912
+ if not biaffine_only:
2913
+ l.extend([w3*x2 + w3*x1 + w3*x0 + w2*x3 + w2*x1 + w1*x3 + w1*x2 + w0*x3 + x3**2 + x3*x2 + x3*x1 + x2**2 + x1**2,
2914
+ w3*x2 + w2*x2 + w2*x1 + w2*x0 + w1*x3 + w1*x1 + w0*x3 + w0*x2 + x3*x2 + x3*x1 + x3*x0 + x2**2 + x2*x1 + x2*x0 + x1*x0,
2915
+ w3*x2 + w3*x1 + w2*x2 + w1*x2 + w1*x1 + w1*x0 + w0*x3 + w0*x1 + x3**2 + x3*x2 + x2*x0 + x1*x0,
2916
+ w3*x3 + w3*x1 + w2*x3 + w2*x2 + w1*x3 + w0*x3 + w0*x2 + w0*x1 + w0*x0 + x3*x1 + x2*x1 + x2*x0 + x0**2,
2917
+ w3**2 + w3*w2 + w3*w1 + w3*x2 + w3*x1 + w3*x0 + w2**2 + w2*x3 + w2*x1 + w1**2 + w1*x3 + w1*x2 + w0*x3,
2918
+ w3*w2 + w3*w1 + w3*w0 + w3*x1 + w3*x0 + w2**2 + w2*w1 + w2*w0 + w2*x3 + w2*x2 + w2*x0 + w1*w0 + w1*x2 + w1*x1 + w0*x2,
2919
+ w3**2 + w3*w2 + w3*x0 + w2*w0 + w2*x3 + w2*x2 + w2*x1 + w1*w0 + w1*x3 + w1*x1 + w1*x0 + w0*x1,
2920
+ w3*w1 + w3*x3 + w3*x2 + w3*x1 + w3*x0 + w2*w1 + w2*w0 + w2*x2 + w2*x0 + w1*x3 + w1*x0 + w0**2 + w0*x0])
2921
+ return l
2922
+
2923
+ else:
2924
+ w7,w6,w5,w4,w3,w2,w1,w0 = w
2925
+ x7,x6,x5,x4,x3,x2,x1,x0 = x
2926
+
2927
+ l = [w7*x7 + w7*x5 + w7*x4 + w7*x0 + w6*x6 + w6*x5 + w6*x1 + w5*x7 + w5*x6 + w5*x2 + w4*x7 + w4*x3 + w3*x4 + w2*x5 + w1*x6 + w0*x7,
2928
+ w7*x6 + w7*x4 + w7*x3 + w6*x7 + w6*x5 + w6*x4 + w6*x0 + w5*x6 + w5*x5 + w5*x1 + w4*x7 + w4*x6 + w4*x2 + w3*x7 + w3*x3 + w2*x4 + w1*x5 + w0*x6,
2929
+ w7*x5 + w7*x3 + w7*x2 + w6*x6 + w6*x4 + w6*x3 + w5*x7 + w5*x5 + w5*x4 + w5*x0 + w4*x6 + w4*x5 + w4*x1 + w3*x7 + w3*x6 + w3*x2 + w2*x7 + w2*x3 + w1*x4 + w0*x5,
2930
+ w7*x7 + w7*x4 + w7*x2 + w7*x1 + w6*x5 + w6*x3 + w6*x2 + w5*x6 + w5*x4 + w5*x3 + w4*x7 + w4*x5 + w4*x4 + w4*x0 + w3*x6 + w3*x5 + w3*x1 + w2*x7 + w2*x6 + w2*x2 + w1*x7 + w1*x3 + w0*x4,
2931
+ w7*x7 + w7*x6 + w7*x5 + w7*x4 + w7*x3 + w7*x1 + w6*x7 + w6*x6 + w6*x5 + w6*x4 + w6*x2 + w5*x7 + w5*x6 + w5*x5 + w5*x3 + w4*x7 + w4*x6 + w4*x4 + w3*x7 + w3*x5 + w3*x0 + w2*x6 + w2*x1
2932
+ + w1*x7 + w1*x2 + w0*x3,
2933
+ w7*x6 + w7*x3 + w7*x2 + w6*x7 + w6*x4 + w6*x3 + w5*x5 + w5*x4 + w4*x6 + w4*x5 + w3*x7 + w3*x6 + w2*x7 + w2*x0 + w1*x1 + w0*x2,
2934
+ w7*x7 + w7*x5 + w7*x2 + w7*x1 + w6*x6 + w6*x3 + w6*x2 + w5*x7 + w5*x4 + w5*x3 + w4*x5 + w4*x4 + w3*x6 + w3*x5 + w2*x7 + w2*x6 + w1*x7 + w1*x0 + w0*x1,
2935
+ w7*x6 + w7*x5 + w7*x2 + w7*x0 + w6*x7 + w6*x4 + w6*x3 + w5*x7 + w5*x6 + w5*x3 + w5*x1 + w4*x5 + w4*x4 + w3*x7 + w3*x4 + w3*x2 + w2*x6 + w2*x5 + w1*x5 + w1*x3 + w0*x7 + w0*x6 + x7,
2936
+ w7*x6 + w7*x3 + w7*x2 + w6*x6 + w6*x5 + w6*x2 + w6*x0 + w5*x7 + w5*x4 + w5*x3 + w4*x7 + w4*x6 + w4*x3 + w4*x1 + w3*x5 + w3*x4 + w2*x7 + w2*x4 + w2*x2 + w1*x6 + w1*x5 + w0*x5 + w0*x3
2937
+ + x6,
2938
+ w7*x7 + w7*x5 + w7*x4 + w7*x1 + w6*x6 + w6*x3 + w6*x2 + w5*x6 + w5*x5 + w5*x2 + w5*x0 + w4*x7 + w4*x4 + w4*x3 + w3*x7 + w3*x6 + w3*x3 + w3*x1 + w2*x5 + w2*x4 + w1*x7 + w1*x4 + w1*x2
2939
+ + w0*x6 + w0*x5 + x5,
2940
+ w7*x7 + w7*x5 + w7*x2 + w7*x1 + w6*x7 + w6*x5 + w6*x4 + w6*x1 + w5*x6 + w5*x3 + w5*x2 + w4*x6 + w4*x5 + w4*x2 + w4*x0 + w3*x7 + w3*x4 + w3*x3 + w2*x7 + w2*x6 + w2*x3 + w2*x1 + w1*x5
2941
+ + w1*x4 + w0*x7 + w0*x4 + w0*x2 + x4,
2942
+ w7*x5 + w7*x4 + w7*x3 + w7*x2 + w6*x5 + w6*x4 + w6*x3 + w6*x2 + w6*x1 + w5*x6 + w5*x5 + w5*x4 + w5*x3 + w4*x6 + w4*x5 + w4*x4 + w4*x3 + w4*x2 + w3*x7 + w3*x6 + w3*x5 + w3*x4 + w3*x0
2943
+ + w2*x7 + w2*x6 + w2*x5 + w2*x4 + w2*x3 + w1*x7 + w1*x6 + w1*x5 + w1*x1 + w0*x7 + w0*x6 + w0*x5 + w0*x4 + x3,
2944
+ w7*x7 + w7*x6 + w7*x5 + w7*x4 + w7*x3 + w7*x1 + w6*x7 + w6*x5 + w6*x2 + w5*x7 + w5*x6 + w5*x5 + w5*x4 + w5*x2 + w4*x6 + w4*x3 + w3*x7 + w3*x6 + w3*x5 + w3*x3 + w2*x7 + w2*x4 + w2*x0
2945
+ + w1*x7 + w1*x6 + w1*x4 + w0*x5 + w0*x1 + x2,
2946
+ w7*x6 + w7*x4 + w7*x1 + w6*x7 + w6*x6 + w6*x5 + w6*x4 + w6*x3 + w6*x1 + w5*x7 + w5*x5 + w5*x2 + w4*x7 + w4*x6 + w4*x5 + w4*x4 + w4*x2 + w3*x6 + w3*x3 + w2*x7 + w2*x6 + w2*x5 + w2*x3
2947
+ + w1*x7 + w1*x4 + w1*x0 + w0*x7 + w0*x6 + w0*x4 + x1,
2948
+ w7*x7 + w7*x4 + w7*x3 + w6*x7 + w6*x6 + w6*x3 + w6*x1 + w5*x5 + w5*x4 + w4*x7 + w4*x4 + w4*x2 + w3*x6 + w3*x5 + w2*x5 + w2*x3 + w1*x7 + w1*x6 + w0*x6 + w0*x4 + w0*x0 + x0,
2949
+ w7*x6 + w7*x5 + w7*x3 + w7*x0 + w7 + w6*x7 + w6*x5 + w6*x2 + w6*x0 + w5*x7 + w5*x4 + w5*x2 + w5*x1 + w4*x6 + w4*x4 + w4*x3 + w3*x6 + w3*x5 + w3*x1 + w2*x7 + w2*x3 + w1*x5 + w0*x7,
2950
+ w7*x5 + w7*x4 + w7*x2 + w6*x7 + w6*x6 + w6*x4 + w6*x1 + w6 + w5*x6 + w5*x3 + w5*x1 + w5*x0 + w4*x5 + w4*x3 + w4*x2 + w3*x7 + w3*x5 + w3*x4 + w3*x0 + w2*x7 + w2*x6 + w2*x2 + w1*x4
2951
+ + w0*x6,
2952
+ w7*x7 + w7*x4 + w7*x3 + w7*x1 + w6*x6 + w6*x5 + w6*x3 + w6*x0 + w5*x7 + w5*x5 + w5*x2 + w5*x0 + w5 + w4*x7 + w4*x4 + w4*x2 + w4*x1 + w3*x6 + w3*x4 + w3*x3 + w2*x6 + w2*x5 + w2*x1
2953
+ + w1*x7 + w1*x3 + w0*x5,
2954
+ w7*x7 + w7*x6 + w7*x3 + w7*x2 + w7*x0 + w6*x5 + w6*x4 + w6*x2 + w5*x7 + w5*x6 + w5*x4 + w5*x1 + w4*x6 + w4*x3 + w4*x1 + w4*x0 + w4 + w3*x5 + w3*x3 + w3*x2 + w2*x7 + w2*x5 + w2*x4
2955
+ + w2*x0 + w1*x7 + w1*x6 + w1*x2 + w0*x4,
2956
+ w7*x3 + w7*x2 + w7*x1 + w7*x0 + w6*x5 + w6*x4 + w6*x3 + w6*x2 + w6*x1 + w6*x0 + w5*x7 + w5*x6 + w5*x5 + w5*x4 + w5*x3 + w5*x2 + w5*x1 + w5*x0 + w4*x7 + w4*x6 + w4*x5 + w4*x4
2957
+ + w4*x3 + w4*x2 + w4*x0 + w3*x7 + w3*x6 + w3*x5 + w3*x4 + w3*x2 + w3 + w2*x7 + w2*x6 + w2*x4 + w1*x6 + w1*x1 + w0*x3,
2958
+ w7*x7 + w7*x6 + w7*x5 + w7*x3 + w7*x2 + w7*x1 + w6*x7 + w6*x5 + w6*x4 + w6*x3 + w6*x1 + w5*x7 + w5*x6 + w5*x5 + w5*x3 + w5*x0 + w4*x7 + w4*x5 + w4*x2 + w4*x1 + w3*x7 + w3*x4
2959
+ + w3*x3 + w2*x6 + w2*x5 + w2 + w1*x7 + w1*x0 + w0*x2,
2960
+ w7*x6 + w7*x5 + w7*x4 + w7*x2 + w7*x1 + w7*x0 + w6*x7 + w6*x6 + w6*x4 + w6*x3 + w6*x2 + w6*x0 + w5*x6 + w5*x5 + w5*x4 + w5*x2 + w4*x7 + w4*x6 + w4*x4 + w4*x1 + w4*x0 + w3*x6
2961
+ + w3*x3 + w3*x2 + w2*x5 + w2*x4 + w1*x7 + w1*x6 + w1 + w0*x1,
2962
+ w7*x7 + w7*x6 + w7*x4 + w7*x1 + w6*x6 + w6*x3 + w6*x1 + w6*x0 + w5*x5 + w5*x3 + w5*x2 + w4*x7 + w4*x5 + w4*x4 + w4*x0 + w3*x7 + w3*x6 + w3*x2 + w2*x4 + w1*x6 + w0*x0 + w0]
2963
+
2964
+ if not correct_only:
2965
+ l.append(w7*x6 + w7*x5 + w7*x1 + w6*x7 + w6*x6 + w6*x2 + w5*x7 + w5*x3 + w4*x4 + w3*x5 + w2*x6 + w1*x7 + w0*x0 + 1)
2966
+
2967
+ if not biaffine_only:
2968
+ l.extend([w7**2 + w7*w6 + w7*w3 + w7*w1 + w7*x7 + w7*x6 + w7*x5 + w7*x2 + w7*x1 + w7*x0 + w6**2 + w6*w0 + w6*x6 + w6*x5 + w6*x4 + w6*x3 + w6*x1 + w6*x0 + w5**2 + w5*w4 + w5*w3
2969
+ + w5*w2 + w5*x7 + w5*x5 + w5*x4 + w5*x1 + w5*x0 + w4**2 + w4*w2 + w4*w0 + w4*x5 + w4*x4 + w4*x2 + w3*w2 + w3*x6 + w3*x3 + w3*x1 + w3*x0 + w2*x7 + w2*x5 + w2*x4
2970
+ + w2*x0 + w1*x4 + w0**2 + w0*x0,
2971
+ w7*x6 + w7*x4 + w7*x1 + w6*x7 + w6*x6 + w6*x5 + w6*x2 + w5*x7 + w5*x6 + w5*x5 + w5*x4 + w5*x3 + w5*x1 + w4*x5 + w4*x4 + w4*x3 + w4*x1 + w4*x0 + w3*x7 + w3*x5 + w3*x2
2972
+ + w2*x7 + w2*x6 + w2*x3 + w1*x7 + w1*x6 + w1*x5 + w1*x4 + w1*x2 + w0*x6 + w0*x5 + w0*x4 + w0*x2 + w0*x1 + x7**2 + x7*x6 + x7*x5 + x7*x3 + x7*x1 + x7*x0 + x6*x2
2973
+ + x6*x1 + x5*x4 + x5*x3 + x5*x2 + x5*x1 + x4*x3 + x4*x2 + x4*x1 + x3**2 + x3*x2 + x2*x1 + x2*x0,
2974
+ w7*x5 + w7*x4 + w7*x3 + w7*x1 + w7*x0 + w6*x7 + w6*x5 + w6*x2 + w5*x7 + w5*x6 + w5*x3 + w4*x7 + w4*x6 + w4*x5 + w4*x4 + w4*x2 + w3*x6 + w3*x5 + w3*x4 + w3*x2 + w3*x1
2975
+ + w2*x6 + w2*x3 + w1*x7 + w1*x4 + w0*x7 + w0*x6 + w0*x5 + w0*x3 + x7*x3 + x7*x2 + x6*x5 + x6*x4 + x6*x3 + x6*x2 + x6*x0 + x5*x4 + x5*x3 + x5*x2 + x4**2 + x4*x3
2976
+ + x3*x2 + x3*x1,
2977
+ w7*w3 + w7*w2 + w7*x6 + w7*x5 + w7*x4 + w7*x1 + w7*x0 + w6*w5 + w6*w4 + w6*w3 + w6*w2 + w6*w0 + w6*x5 + w6*x4 + w6*x3 + w6*x2 + w6*x0 + w5*w4 + w5*w3 + w5*w2 + w5*x7
2978
+ + w5*x6 + w5*x4 + w5*x3 + w5*x0 + w4**2 + w4*w3 + w4*x7 + w4*x4 + w4*x3 + w4*x1 + w3*w2 + w3*w1 + w3*x7 + w3*x5 + w3*x2 + w3*x0 + w2*x6 + w2*x4 + w2*x3 + w1*x7
2979
+ + w1*x3 + w0*x7,
2980
+ w7*x5 + w7*x2 + w7*x1 + w6*x7 + w6*x6 + w6*x5 + w6*x4 + w6*x2 + w6*x1 + w5*x5 + w5*x3 + w5*x2 + w4*x3 + w4*x2 + w4*x1 + w3*x6 + w3*x3 + w3*x2 + w3*x0 + w2*x7 + w2*x6
2981
+ + w2*x5 + w2*x3 + w2*x2 + w1*x6 + w1*x4 + w1*x3 + w0*x4 + w0*x3 + w0*x2 + x7*x5 + x7*x4 + x7*x1 + x7*x0 + x6*x0 + x5**2 + x5*x2 + x5*x1 + x5*x0 + x4**2 + x4*x0
2982
+ + x3*x2 + x3*x0 + x1**2,
2983
+ w7*w6 + w7*w5 + w7*w4 + w7*w3 + w7*x7 + w7*x5 + w7*x4 + w7*x3 + w7*x0 + w6**2 + w6*w5 + w6*w4 + w6*w2 + w6*w1 + w6*w0 + w6*x7 + w6*x4 + w6*x3 + w6*x2 + w6*x1 + w5*w4
2984
+ + w5*w1 + w5*w0 + w5*x7 + w5*x6 + w5*x5 + w5*x3 + w5*x2 + w4*w2 + w4*w1 + w4*x7 + w4*x6 + w4*x3 + w4*x2 + w4*x0 + w3*w0 + w3*x7 + w3*x6 + w3*x4 + w3*x1 + w2**2
2985
+ + w2*x5 + w2*x3 + w2*x2 + w1*x7 + w1*x6 + w1*x2 + w0*x6,
2986
+ w7*w5 + w7*w4 + w7*w1 + w7*w0 + w7*x6 + w7*x2 + w6*w0 + w6*x6 + w6*x3 + w6*x2 + w6*x1 + w5**2 + w5*w2 + w5*w1 + w5*w0 + w5*x7 + w5*x6 + w5*x5 + w5*x2 + w4**2 + w4*w0
2987
+ + w4*x6 + w4*x1 + w4*x0 + w3*w2 + w3*w0 + w3*x5 + w3*x4 + w3*x3 + w3*x2 + w3*x1 + w3*x0 + w2*x7 + w2*x6 + w2*x5 + w2*x4 + w2*x3 + w2*x2 + w2*x0 + w1**2 + w1*x7
2988
+ + w1*x6 + w1*x4 + w0*x3,
2989
+ w7*x7 + w7*x6 + w7*x5 + w7*x2 + w6*x7 + w6*x6 + w6*x5 + w6*x4 + w6*x3 + w6*x1 + w5*x5 + w5*x4 + w5*x3 + w5*x1 + w5*x0 + w4*x7 + w4*x5 + w4*x2 + w3*x7 + w3*x6 + w3*x3
2990
+ + w2*x7 + w2*x6 + w2*x5 + w2*x4 + w2*x2 + w1*x6 + w1*x5 + w1*x4 + w1*x2 + w1*x1 + w0*x6 + w0*x3 + x7**2 + x7*x5 + x7*x3 + x6**2 + x6*x5 + x6*x2 + x6*x0 + x5**2
2991
+ + x4**2 + x4*x3 + x4*x2 + x4*x1 + x3**2 + x3*x1 + x2*x1,
2992
+ w7**2 + w7*w6 + w7*w5 + w7*w3 + w7*w1 + w7*w0 + w7*x6 + w7*x5 + w7*x3 + w7*x2 + w7*x1 + w6*w2 + w6*w1 + w6*x7 + w6*x6 + w6*x5 + w6*x2 + w6*x1 + w6*x0 + w5*w4 + w5*w3
2993
+ + w5*w2 + w5*w1 + w5*x6 + w5*x5 + w5*x4 + w5*x3 + w5*x1 + w5*x0 + w4*w3 + w4*w2 + w4*w1 + w4*x7 + w4*x5 + w4*x4 + w4*x1 + w4*x0 + w3**2 + w3*w2 + w3*x5 + w3*x4
2994
+ + w3*x2 + w2*w1 + w2*w0 + w2*x6 + w2*x3 + w2*x1 + w2*x0 + w1*x7 + w1*x5 + w1*x4 + w1*x0 + w0*x4,
2995
+ w7*x7 + w7*x5 + w7*x2 + w6*x7 + w6*x6 + w6*x3 + w5*x7 + w5*x6 + w5*x5 + w5*x4 + w5*x2 + w4*x6 + w4*x5 + w4*x4 + w4*x2 + w4*x1 + w3*x6 + w3*x3 + w2*x7 + w2*x4 + w1*x7
2996
+ + w1*x6 + w1*x5 + w1*x3 + w0*x7 + w0*x6 + w0*x5 + w0*x3 + w0*x2 + w0*x0 + x7**2 + x7*x6 + x7*x3 + x7*x1 + x6**2 + x6*x0 + x5**2 + x5*x4 + x5*x3 + x5*x2 + x4**2
2997
+ + x4*x2 + x4*x0 + x3*x2 + x0**2,
2998
+ w7*x7 + w7*x6 + w7*x5 + w7*x4 + w7*x3 + w7*x1 + w6*x5 + w6*x4 + w6*x3 + w6*x1 + w6*x0 + w5*x7 + w5*x5 + w5*x2 + w4*x7 + w4*x6 + w4*x3 + w3*x7 + w3*x6 + w3*x5 + w3*x4
2999
+ + w3*x2 + w2*x6 + w2*x5 + w2*x4 + w2*x2 + w2*x1 + w1*x6 + w1*x3 + w0*x7 + w0*x4 + x7*x6 + x7*x5 + x7*x4 + x7*x3 + x6**2 + x6*x5 + x6*x4 + x6*x2 + x6*x1 + x6*x0
3000
+ + x5*x4 + x5*x1 + x5*x0 + x4*x2 + x4*x1 + x3*x0 + x2**2,
3001
+ w7*x5 + w7*x4 + w7*x3 + w7*x2 + w6*x7 + w6*x1 + w5*x5 + w5*x4 + w5*x3 + w5*x2 + w5*x1 + w4*x7 + w4*x6 + w4*x4 + w4*x3 + w3*x6 + w3*x5 + w3*x4 + w3*x3 + w2*x2 + w2*x0
3002
+ + w1*x6 + w1*x5 + w1*x4 + w1*x3 + w1*x2 + w0*x7 + w0*x5 + w0*x4 + x7**2 + x7*x4 + x7*x2 + x6*x4 + x6*x3 + x6*x2 + x6*x1 + x5**2 + x5*x4 + x5*x3 + x5*x2 + x5*x0
3003
+ + x4*x3 + x4*x2 + x4*x1 + x3**2 + x2*x0 + x1*x0,
3004
+ w7*x6 + w7*x5 + w7*x3 + w7*x2 + w6*x5 + w6*x4 + w6*x3 + w6*x2 + w5*x7 + w5*x1 + w4*x5 + w4*x4 + w4*x3 + w4*x2 + w4*x1 + w3*x7 + w3*x6 + w3*x4 + w3*x3 + w2*x6 + w2*x5
3005
+ + w2*x4 + w2*x3 + w1*x2 + w1*x0 + w0*x6 + w0*x5 + w0*x4 + w0*x3 + w0*x2 + x7*x5 + x7*x2 + x7*x0 + x6**2 + x6*x5 + x6*x2 + x6*x1 + x6*x0 + x5**2 + x5*x4 + x4**2
3006
+ + x4*x2 + x4*x1 + x4*x0 + x3**2 + x3*x2 + x1*x0,
3007
+ w7**2 + w7*w5 + w7*w3 + w7*x7 + w7*x6 + w7*x4 + w7*x3 + w7*x2 + w6**2 + w6*w5 + w6*w2 + w6*w0 + w6*x7 + w6*x6 + w6*x3 + w6*x2 + w6*x1 + w6*x0 + w5**2 + w5*x7 + w5*x6
3008
+ + w5*x5 + w5*x4 + w5*x2 + w5*x1 + w4**2 + w4*w3 + w4*w2 + w4*w1 + w4*x6 + w4*x5 + w4*x2 + w4*x1 + w3**2 + w3*w1 + w3*x6 + w3*x5 + w3*x3 + w3*x0 + w2*w1 + w2*x7
3009
+ + w2*x4 + w2*x2 + w2*x1 + w1*x6 + w1*x5 + w1*x1 + w0*x5,
3010
+ w7*w5 + w7*w2 + w7*w0 + w7*x5 + w7*x3 + w6**2 + w6*w5 + w6*w2 + w6*w1 + w6*w0 + w6*x7 + w6*x3 + w6*x2 + w6*x0 + w5**2 + w5*w4 + w5*x7 + w5*x6 + w5*x4 + w5*x2 + w5*x0
3011
+ + w4**2 + w4*w2 + w4*w1 + w4*w0 + w4*x6 + w4*x4 + w4*x3 + w4*x2 + w4*x0 + w3**2 + w3*w2 + w3*x7 + w3*x6 + w3*x4 + w3*x3 + w3*x2 + w3*x0 + w2*x7 + w2*x6 + w2*x4
3012
+ + w2*x1 + w2*x0 + w1*w0 + w1*x5 + w1*x4 + w0*x1,
3013
+ w7**2 + w7*w4 + w7*w2 + w7*x6 + w7*x4 + w7*x0 + w6*w4 + w6*w3 + w6*w2 + w6*w1 + w6*x4 + w6*x3 + w6*x1 + w5**2 + w5*w4 + w5*w3 + w5*w2 + w5*w0 + w5*x7 + w5*x5 + w5*x3
3014
+ + w5*x1 + w5*x0 + w4*w3 + w4*w2 + w4*w1 + w4*x7 + w4*x5 + w4*x4 + w4*x3 + w4*x1 + w4*x0 + w3**2 + w3*x7 + w3*x5 + w3*x4 + w3*x3 + w3*x1 + w2*w0 + w2*x7 + w2*x5
3015
+ + w2*x2 + w2*x1 + w1*w0 + w1*x6 + w1*x5 + w0*x2])
3016
+
3017
+ return l
3018
+
3019
+ def _inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, correct_only=None):
3020
+ """
3021
+ Generate inversion polynomials of a single S-box.
3022
+
3023
+ INPUT:
3024
+
3025
+ - ``x`` -- output variables (default: ``None``)
3026
+ - ``w`` -- input variables (default: ``None``)
3027
+ - ``biaffine_only`` -- only include biaffine polynomials (default: object default)
3028
+ - ``correct_only`` -- only include correct polynomials (default: object default)
3029
+
3030
+ EXAMPLES::
3031
+
3032
+ sage: sr = mq.SR(1, 1, 1, 8, gf2=True)
3033
+ sage: len(sr._inversion_polynomials_single_sbox())
3034
+ 24
3035
+ sage: len(sr._inversion_polynomials_single_sbox(correct_only=True))
3036
+ 23
3037
+ sage: len(sr._inversion_polynomials_single_sbox(biaffine_only=False))
3038
+ 40
3039
+ sage: len(sr._inversion_polynomials_single_sbox(biaffine_only=False, correct_only=True))
3040
+ 39
3041
+ """
3042
+ e = self.e
3043
+
3044
+ if biaffine_only is None:
3045
+ biaffine_only = self._biaffine_only
3046
+ if correct_only is None:
3047
+ correct_only = self._correct_only
3048
+
3049
+ if x is None and w is None:
3050
+ # make sure it prints like in the book.
3051
+ names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))]
3052
+ P = PolynomialRing(GF(2), e*2, names, order='lex')
3053
+ x = matrix(P, e, 1, P.gens()[e:])
3054
+ w = matrix(P, e, 1, P.gens()[:e])
3055
+ else:
3056
+ if isinstance(x, (tuple, list)):
3057
+ P = x[0].parent()
3058
+ elif isinstance(x, Matrix):
3059
+ P = x.base_ring()
3060
+ else:
3061
+ raise TypeError("x not understood")
3062
+
3063
+ if isinstance(x, (tuple, list)):
3064
+ x = matrix(P, e, 1, x)
3065
+ if isinstance(w, (tuple, list)):
3066
+ w = matrix(P, e, 1, w)
3067
+
3068
+ T = self._mul_matrix(self.k.gen())
3069
+ o = matrix(P, e, 1, [0]*(e-1) + [1])
3070
+
3071
+ columns = []
3072
+ for i in reversed(range(e)):
3073
+ columns.append((T**i * w).list())
3074
+ Cw = matrix(P, e, e, columns).transpose()
3075
+
3076
+ columns = []
3077
+ for i in reversed(range(e)):
3078
+ columns.append((T**i * x).list())
3079
+ Cx = matrix(P, e, e, columns).transpose()
3080
+
3081
+ S = self._square_matrix()
3082
+
3083
+ l = []
3084
+ if correct_only:
3085
+ l.append( (Cw * x + o).list()[:-1] )
3086
+ else:
3087
+ l.append( (Cw * x + o).list() )
3088
+ l.append( (Cw * S * x + x).list() )
3089
+ l.append( (Cx * S * w + w).list() )
3090
+ if not biaffine_only:
3091
+ l.append( ((Cw * S**2 + Cx*S)*x).list() )
3092
+ l.append( ((Cx * S**2 + Cw*S)*w).list() )
3093
+
3094
+ return sum(l, [])
3095
+
3096
+ def inversion_polynomials(self, xi, wi, length):
3097
+ """
3098
+ Return polynomials to represent the inversion in the AES S-Box.
3099
+
3100
+ INPUT:
3101
+
3102
+ - ``xi`` -- output variables
3103
+
3104
+ - ``wi`` -- input variables
3105
+
3106
+ - ``length`` -- length of both lists
3107
+
3108
+ EXAMPLES::
3109
+
3110
+ sage: sr = mq.SR(1, 1, 1, 8, gf2=True)
3111
+ sage: xi = sr.vars('x', 1) # needs sage.rings.polynomial.pbori
3112
+ sage: wi = sr.vars('w', 1) # needs sage.rings.polynomial.pbori
3113
+ sage: sr.inversion_polynomials(xi, wi, len(xi))[:3] # needs sage.rings.polynomial.pbori
3114
+ [x100*w100 + x100*w102 + x100*w103 + x100*w107 + x101*w101 + x101*w102 + x101*w106 + x102*w100 + x102*w101 + x102*w105 + x103*w100 + x103*w104 + x104*w103 + x105*w102 + x106*w101 + x107*w100,
3115
+ x100*w101 + x100*w103 + x100*w104 + x101*w100 + x101*w102 + x101*w103 + x101*w107 + x102*w101 + x102*w102 + x102*w106 + x103*w100 + x103*w101 + x103*w105 + x104*w100 + x104*w104 + x105*w103 + x106*w102 + x107*w101,
3116
+ x100*w102 + x100*w104 + x100*w105 + x101*w101 + x101*w103 + x101*w104 + x102*w100 + x102*w102 + x102*w103 + x102*w107 + x103*w101 + x103*w102 + x103*w106 + x104*w100 + x104*w101 + x104*w105 + x105*w100 + x105*w104 + x106*w103 + x107*w102]
3117
+ """
3118
+ if isinstance(xi, Matrix):
3119
+ xi = xi.list()
3120
+ if isinstance(wi, Matrix):
3121
+ wi = wi.list()
3122
+
3123
+ e = self.e
3124
+ l = []
3125
+ for j in range(0, length, e):
3126
+ l += self.inversion_polynomials_single_sbox(xi[j:j+e], wi[j:j+e])
3127
+ return l
3128
+
3129
+ def field_polynomials(self, name, i, l=None):
3130
+ r"""
3131
+ Return list of field polynomials for a given round ``i`` and
3132
+ name ``name``.
3133
+
3134
+ INPUT:
3135
+
3136
+ - ``name`` -- variable name
3137
+ - ``i`` -- round number
3138
+ - ``l`` -- length of variable list (default: ``None`` = r\*c)
3139
+
3140
+ EXAMPLES::
3141
+
3142
+ sage: sr = mq.SR(3, 1, 1, 8, gf2=True, polybori=False)
3143
+ sage: sr.field_polynomials('x', 2)
3144
+ [x200^2 + x200, x201^2 + x201,
3145
+ x202^2 + x202, x203^2 + x203,
3146
+ x204^2 + x204, x205^2 + x205,
3147
+ x206^2 + x206, x207^2 + x207]
3148
+
3149
+ ::
3150
+
3151
+ sage: sr = mq.SR(3, 1, 1, 8, gf2=True, polybori=True)
3152
+ sage: sr.field_polynomials('x', 2)
3153
+ []
3154
+ """
3155
+ r = self._r
3156
+ c = self._c
3157
+ e = self._e
3158
+
3159
+ if l is None:
3160
+ l = r*c
3161
+
3162
+ if self._polybori:
3163
+ return []
3164
+ _vars = self.vars(name, i, l, e)
3165
+ return [_vars[e*j+k]**2 - _vars[e*j+k] for j in range(l) for k in range(e)]
3166
+
3167
+
3168
+ class SR_gf2_2(SR_gf2):
3169
+ """
3170
+ This is an example how to customize the SR constructor.
3171
+
3172
+ In this example, we replace the S-Box inversion polynomials by the
3173
+ polynomials generated by the S-Box class.
3174
+ """
3175
+ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, correct_only=None, groebner=False):
3176
+ """
3177
+ Return inversion polynomials of a single S-Box.
3178
+
3179
+ INPUT:
3180
+
3181
+ - ``x`` -- output variables (default: ``None``)
3182
+ - ``w`` -- input variables (default: ``None``)
3183
+ - ``biaffine_only`` -- ignored (always ``False``)
3184
+ - ``correct_only`` -- ignored (always ``True``)
3185
+ - ``groebner`` -- precompute the Groebner basis for this S-Box (default: ``False``)
3186
+
3187
+ EXAMPLES::
3188
+
3189
+ sage: from sage.crypto.mq.sr import SR_gf2_2
3190
+ sage: e = 4
3191
+ sage: sr = SR_gf2_2(1, 1, 1, e)
3192
+ sage: P = PolynomialRing(GF(2),['x%d'%i for i in range(e)] + ['w%d'%i for i in range(e)],order='lex')
3193
+ sage: X,W = P.gens()[:e],P.gens()[e:]
3194
+ sage: sr.inversion_polynomials_single_sbox(X, W, groebner=True) # needs sage.libs.singular
3195
+ [x0 + w0*w1*w2 + w0*w1 + w0*w2 + w0*w3 + w0 + w1 + w2,
3196
+ x1 + w0*w1*w3 + w0*w3 + w0 + w1*w3 + w1 + w2*w3,
3197
+ x2 + w0*w2*w3 + w0*w2 + w0 + w1*w2 + w1*w3 + w2*w3,
3198
+ x3 + w0*w1*w2 + w0 + w1*w2*w3 + w1*w2 + w1*w3 + w1 + w2 + w3]
3199
+
3200
+ sage: from sage.crypto.mq.sr import SR_gf2_2
3201
+ sage: e = 4
3202
+ sage: sr = SR_gf2_2(1, 1, 1, e)
3203
+ sage: sr.inversion_polynomials_single_sbox() # needs sage.libs.singular
3204
+ [w3*w1 + w3*w0 + w3*x2 + w3*x1 + w3 + w2*w1 + w1 + x3 + x2 + x1,
3205
+ w3*w2 + w3*w1 + w3*x3 + w2 + w1 + x3,
3206
+ w3*w2 + w3*w1 + w3*x2 + w3 + w2*x3 + x2 + x1,
3207
+ w3*w2 + w3*w1 + w3*x3 + w3*x2 + w3*x1 + w3 + w2*x2 + w0 + x3 + x2 + x1 + x0,
3208
+ w3*w2 + w3*w1 + w3*x1 + w3*x0 + w2*x1 + w0 + x3 + x0,
3209
+ w3*w2 + w3*w1 + w3*w0 + w3*x2 + w3*x1 + w2*w0 + w2*x0 + w0 + x3 + x2 + x1 + x0,
3210
+ w3*w2 + w3*x1 + w3 + w2*w0 + w1*w0 + w1 + x3 + x2,
3211
+ w3*w2 + w3*w1 + w3*x1 + w1*x3 + x3 + x2 + x1,
3212
+ w3*x3 + w3*x2 + w3*x0 + w3 + w1*x2 + w1 + w0 + x2 + x0,
3213
+ w3*w2 + w3*w1 + w3*x2 + w3*x1 + w1*x1 + w1 + w0 + x2 + x0,
3214
+ w3*w2 + w3*w1 + w3*w0 + w3*x3 + w3*x1 + w2*w0 + w1*x0 + x3 + x2,
3215
+ w3*w2 + w3*w1 + w3*x2 + w3*x1 + w3*x0 + w3 + w1 + w0*x3 + x3 + x2,
3216
+ w3*w2 + w3*w1 + w3*w0 + w3*x3 + w3 + w2*w0 + w1 + w0*x2 + x3 + x2,
3217
+ w3*w0 + w3*x2 + w2*w0 + w0*x1 + w0 + x3 + x1 + x0,
3218
+ w3*w0 + w3*x3 + w3*x0 + w2*w0 + w1 + w0*x0 + w0 + x3 + x2,
3219
+ w3*w2 + w3 + w1 + x3*x2 + x3 + x1,
3220
+ w3*w2 + w3*x3 + w1 + x3*x1 + x3 + x2,
3221
+ w3*w2 + w3*w0 + w3*x3 + w3*x2 + w3*x1 + w0 + x3*x0 + x1 + x0,
3222
+ w3*w2 + w3*w1 + w3*w0 + w3*x3 + w1 + w0 + x2*x1 + x2 + x0,
3223
+ w3*w2 + w2*w0 + w1 + x3 + x2*x0,
3224
+ w3*x3 + w3*x1 + w2*w0 + w1 + x3 + x2 + x1*x0 + x1]
3225
+
3226
+ TESTS:
3227
+
3228
+ Note that ``biaffine_only`` and ``correct_only`` are always
3229
+ ignored. The former is always false while the second is always
3230
+ true. They are only accepted for compatibility with the base
3231
+ class.
3232
+
3233
+ sage: from sage.crypto.mq.sr import SR_gf2_2
3234
+ sage: e = 4
3235
+ sage: sr = SR_gf2_2(1, 1, 1, e)
3236
+ sage: l = sr.inversion_polynomials_single_sbox() # needs sage.libs.singular
3237
+ sage: l == sr.inversion_polynomials_single_sbox(biaffine_only=True, correct_only=False) # needs sage.libs.singular
3238
+ True
3239
+ """
3240
+ e = self.e
3241
+ if x is None and w is None:
3242
+ # make sure it prints like in the book.
3243
+ names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))]
3244
+ P = PolynomialRing(GF(2), e*2, names, order='lex')
3245
+ x = P.gens()[e:]
3246
+ w = P.gens()[:e]
3247
+
3248
+ S = self.sbox(inversion_only=True)
3249
+ F = S.polynomials(w, x, degree=e-2, groebner=groebner)
3250
+ return F
3251
+
3252
+
3253
+ class AllowZeroInversionsContext:
3254
+ """
3255
+ Temporarily allow zero inversion.
3256
+ """
3257
+ def __init__(self, sr):
3258
+ """
3259
+ EXAMPLES::
3260
+
3261
+ sage: from sage.crypto.mq.sr import AllowZeroInversionsContext
3262
+ sage: sr = mq.SR(1,2,2,4)
3263
+ sage: with AllowZeroInversionsContext(sr):
3264
+ ....: sr.sub_byte(0)
3265
+ a^2 + a
3266
+ """
3267
+ self.sr = sr
3268
+
3269
+ def __enter__(self):
3270
+ """
3271
+ EXAMPLES::
3272
+
3273
+ sage: from sage.crypto.mq.sr import AllowZeroInversionsContext
3274
+ sage: sr = mq.SR(1,2,2,4)
3275
+ sage: sr.sub_byte(0)
3276
+ Traceback (most recent call last):
3277
+ ...
3278
+ ZeroDivisionError: A zero inversion occurred during an encryption or key schedule.
3279
+
3280
+ sage: with AllowZeroInversionsContext(sr):
3281
+ ....: sr.sub_byte(0)
3282
+ a^2 + a
3283
+ """
3284
+ self.allow_zero_inversions = self.sr._allow_zero_inversions
3285
+ self.sr._allow_zero_inversions = True
3286
+
3287
+ def __exit__(self, typ, value, tb):
3288
+ """
3289
+ EXAMPLES::
3290
+
3291
+ sage: from sage.crypto.mq.sr import AllowZeroInversionsContext
3292
+ sage: sr = mq.SR(1,2,2,4)
3293
+ sage: with AllowZeroInversionsContext(sr):
3294
+ ....: sr.sub_byte(0)
3295
+ a^2 + a
3296
+ sage: sr._allow_zero_inversions
3297
+ False
3298
+ """
3299
+ self.sr._allow_zero_inversions = self.allow_zero_inversions
3300
+
3301
+
3302
+ def test_consistency(max_n=2, **kwargs):
3303
+ r"""
3304
+ Test all combinations of ``r``, ``c``, ``e`` and ``n`` in ``(1,
3305
+ 2)`` for consistency of random encryptions and their polynomial
3306
+ systems. `\GF{2}` and `\GF{2^e}` systems are tested. This test takes
3307
+ a while.
3308
+
3309
+ INPUT:
3310
+
3311
+ - ``max_n`` -- maximal number of rounds to consider (default: 2)
3312
+ - ``kwargs`` -- are passed to the SR constructor
3313
+
3314
+ TESTS:
3315
+
3316
+ The following test called with ``max_n`` = 2 requires a LOT of RAM
3317
+ (much more than 2GB). Since this might cause the doctest to fail
3318
+ on machines with "only" 2GB of RAM, we test ``max_n`` = 1, which
3319
+ has a more reasonable memory usage. ::
3320
+
3321
+ sage: from sage.crypto.mq.sr import test_consistency
3322
+ sage: test_consistency(1) # needs sage.rings.polynomial.pbori, long time (65s on sage.math, 2012)
3323
+ True
3324
+ """
3325
+ consistent = True
3326
+ for r in (1, 2, 4):
3327
+ for c in (1, 2, 4):
3328
+ for e in (4, 8):
3329
+ for n in range(1, max_n+1):
3330
+ for gf2 in (True, False):
3331
+ zero_division = True
3332
+ while zero_division:
3333
+ sr = SR(n, r, c, e, gf2=gf2, **kwargs)
3334
+ try:
3335
+ F, s = sr.polynomial_system()
3336
+ F = F.subs(s)
3337
+ consistent &= (F.groebner_basis()[0] != 1)
3338
+ if not consistent:
3339
+ print(str(sr) + " is not consistent")
3340
+ zero_division = False
3341
+
3342
+ except ZeroDivisionError:
3343
+ pass
3344
+ return consistent