m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3361 lines
87 KiB

7 months ago
  1. """
  2. This file contains some classical ciphers and routines
  3. implementing a linear-feedback shift register (LFSR)
  4. and the Diffie-Hellman key exchange.
  5. .. warning::
  6. This module is intended for educational purposes only. Do not use the
  7. functions in this module for real cryptographic applications. If you wish
  8. to encrypt real data, we recommend using something like the `cryptography
  9. <https://cryptography.io/en/latest/>`_ module.
  10. """
  11. from string import whitespace, ascii_uppercase as uppercase, printable
  12. from functools import reduce
  13. import warnings
  14. from itertools import cycle
  15. from sympy.ntheory.generate import nextprime
  16. from sympy.core import Rational, Symbol
  17. from sympy.core.numbers import igcdex, mod_inverse, igcd
  18. from sympy.matrices import Matrix
  19. from sympy.ntheory import isprime, primitive_root, factorint
  20. from sympy.polys.domains import FF
  21. from sympy.polys.polytools import gcd, Poly
  22. from sympy.utilities.misc import as_int, filldedent, translate
  23. from sympy.utilities.iterables import uniq, multiset
  24. from sympy.core.random import _randrange, _randint
  25. class NonInvertibleCipherWarning(RuntimeWarning):
  26. """A warning raised if the cipher is not invertible."""
  27. def __init__(self, msg):
  28. self.fullMessage = msg
  29. def __str__(self):
  30. return '\n\t' + self.fullMessage
  31. def warn(self, stacklevel=3):
  32. warnings.warn(self, stacklevel=stacklevel)
  33. def AZ(s=None):
  34. """Return the letters of ``s`` in uppercase. In case more than
  35. one string is passed, each of them will be processed and a list
  36. of upper case strings will be returned.
  37. Examples
  38. ========
  39. >>> from sympy.crypto.crypto import AZ
  40. >>> AZ('Hello, world!')
  41. 'HELLOWORLD'
  42. >>> AZ('Hello, world!'.split())
  43. ['HELLO', 'WORLD']
  44. See Also
  45. ========
  46. check_and_join
  47. """
  48. if not s:
  49. return uppercase
  50. t = isinstance(s, str)
  51. if t:
  52. s = [s]
  53. rv = [check_and_join(i.upper().split(), uppercase, filter=True)
  54. for i in s]
  55. if t:
  56. return rv[0]
  57. return rv
  58. bifid5 = AZ().replace('J', '')
  59. bifid6 = AZ() + '0123456789'
  60. bifid10 = printable
  61. def padded_key(key, symbols):
  62. """Return a string of the distinct characters of ``symbols`` with
  63. those of ``key`` appearing first. A ValueError is raised if
  64. a) there are duplicate characters in ``symbols`` or
  65. b) there are characters in ``key`` that are not in ``symbols``.
  66. Examples
  67. ========
  68. >>> from sympy.crypto.crypto import padded_key
  69. >>> padded_key('PUPPY', 'OPQRSTUVWXY')
  70. 'PUYOQRSTVWX'
  71. >>> padded_key('RSA', 'ARTIST')
  72. Traceback (most recent call last):
  73. ...
  74. ValueError: duplicate characters in symbols: T
  75. """
  76. syms = list(uniq(symbols))
  77. if len(syms) != len(symbols):
  78. extra = ''.join(sorted({
  79. i for i in symbols if symbols.count(i) > 1}))
  80. raise ValueError('duplicate characters in symbols: %s' % extra)
  81. extra = set(key) - set(syms)
  82. if extra:
  83. raise ValueError(
  84. 'characters in key but not symbols: %s' % ''.join(
  85. sorted(extra)))
  86. key0 = ''.join(list(uniq(key)))
  87. # remove from syms characters in key0
  88. return key0 + translate(''.join(syms), None, key0)
  89. def check_and_join(phrase, symbols=None, filter=None):
  90. """
  91. Joins characters of ``phrase`` and if ``symbols`` is given, raises
  92. an error if any character in ``phrase`` is not in ``symbols``.
  93. Parameters
  94. ==========
  95. phrase
  96. String or list of strings to be returned as a string.
  97. symbols
  98. Iterable of characters allowed in ``phrase``.
  99. If ``symbols`` is ``None``, no checking is performed.
  100. Examples
  101. ========
  102. >>> from sympy.crypto.crypto import check_and_join
  103. >>> check_and_join('a phrase')
  104. 'a phrase'
  105. >>> check_and_join('a phrase'.upper().split())
  106. 'APHRASE'
  107. >>> check_and_join('a phrase!'.upper().split(), 'ARE', filter=True)
  108. 'ARAE'
  109. >>> check_and_join('a phrase!'.upper().split(), 'ARE')
  110. Traceback (most recent call last):
  111. ...
  112. ValueError: characters in phrase but not symbols: "!HPS"
  113. """
  114. rv = ''.join(''.join(phrase))
  115. if symbols is not None:
  116. symbols = check_and_join(symbols)
  117. missing = ''.join(list(sorted(set(rv) - set(symbols))))
  118. if missing:
  119. if not filter:
  120. raise ValueError(
  121. 'characters in phrase but not symbols: "%s"' % missing)
  122. rv = translate(rv, None, missing)
  123. return rv
  124. def _prep(msg, key, alp, default=None):
  125. if not alp:
  126. if not default:
  127. alp = AZ()
  128. msg = AZ(msg)
  129. key = AZ(key)
  130. else:
  131. alp = default
  132. else:
  133. alp = ''.join(alp)
  134. key = check_and_join(key, alp, filter=True)
  135. msg = check_and_join(msg, alp, filter=True)
  136. return msg, key, alp
  137. def cycle_list(k, n):
  138. """
  139. Returns the elements of the list ``range(n)`` shifted to the
  140. left by ``k`` (so the list starts with ``k`` (mod ``n``)).
  141. Examples
  142. ========
  143. >>> from sympy.crypto.crypto import cycle_list
  144. >>> cycle_list(3, 10)
  145. [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]
  146. """
  147. k = k % n
  148. return list(range(k, n)) + list(range(k))
  149. ######## shift cipher examples ############
  150. def encipher_shift(msg, key, symbols=None):
  151. """
  152. Performs shift cipher encryption on plaintext msg, and returns the
  153. ciphertext.
  154. Parameters
  155. ==========
  156. key : int
  157. The secret key.
  158. msg : str
  159. Plaintext of upper-case letters.
  160. Returns
  161. =======
  162. str
  163. Ciphertext of upper-case letters.
  164. Examples
  165. ========
  166. >>> from sympy.crypto.crypto import encipher_shift, decipher_shift
  167. >>> msg = "GONAVYBEATARMY"
  168. >>> ct = encipher_shift(msg, 1); ct
  169. 'HPOBWZCFBUBSNZ'
  170. To decipher the shifted text, change the sign of the key:
  171. >>> encipher_shift(ct, -1)
  172. 'GONAVYBEATARMY'
  173. There is also a convenience function that does this with the
  174. original key:
  175. >>> decipher_shift(ct, 1)
  176. 'GONAVYBEATARMY'
  177. Notes
  178. =====
  179. ALGORITHM:
  180. STEPS:
  181. 0. Number the letters of the alphabet from 0, ..., N
  182. 1. Compute from the string ``msg`` a list ``L1`` of
  183. corresponding integers.
  184. 2. Compute from the list ``L1`` a new list ``L2``, given by
  185. adding ``(k mod 26)`` to each element in ``L1``.
  186. 3. Compute from the list ``L2`` a string ``ct`` of
  187. corresponding letters.
  188. The shift cipher is also called the Caesar cipher, after
  189. Julius Caesar, who, according to Suetonius, used it with a
  190. shift of three to protect messages of military significance.
  191. Caesar's nephew Augustus reportedly used a similar cipher, but
  192. with a right shift of 1.
  193. References
  194. ==========
  195. .. [1] https://en.wikipedia.org/wiki/Caesar_cipher
  196. .. [2] http://mathworld.wolfram.com/CaesarsMethod.html
  197. See Also
  198. ========
  199. decipher_shift
  200. """
  201. msg, _, A = _prep(msg, '', symbols)
  202. shift = len(A) - key % len(A)
  203. key = A[shift:] + A[:shift]
  204. return translate(msg, key, A)
  205. def decipher_shift(msg, key, symbols=None):
  206. """
  207. Return the text by shifting the characters of ``msg`` to the
  208. left by the amount given by ``key``.
  209. Examples
  210. ========
  211. >>> from sympy.crypto.crypto import encipher_shift, decipher_shift
  212. >>> msg = "GONAVYBEATARMY"
  213. >>> ct = encipher_shift(msg, 1); ct
  214. 'HPOBWZCFBUBSNZ'
  215. To decipher the shifted text, change the sign of the key:
  216. >>> encipher_shift(ct, -1)
  217. 'GONAVYBEATARMY'
  218. Or use this function with the original key:
  219. >>> decipher_shift(ct, 1)
  220. 'GONAVYBEATARMY'
  221. """
  222. return encipher_shift(msg, -key, symbols)
  223. def encipher_rot13(msg, symbols=None):
  224. """
  225. Performs the ROT13 encryption on a given plaintext ``msg``.
  226. Explanation
  227. ===========
  228. ROT13 is a substitution cipher which substitutes each letter
  229. in the plaintext message for the letter furthest away from it
  230. in the English alphabet.
  231. Equivalently, it is just a Caeser (shift) cipher with a shift
  232. key of 13 (midway point of the alphabet).
  233. References
  234. ==========
  235. .. [1] https://en.wikipedia.org/wiki/ROT13
  236. See Also
  237. ========
  238. decipher_rot13
  239. encipher_shift
  240. """
  241. return encipher_shift(msg, 13, symbols)
  242. def decipher_rot13(msg, symbols=None):
  243. """
  244. Performs the ROT13 decryption on a given plaintext ``msg``.
  245. Explanation
  246. ============
  247. ``decipher_rot13`` is equivalent to ``encipher_rot13`` as both
  248. ``decipher_shift`` with a key of 13 and ``encipher_shift`` key with a
  249. key of 13 will return the same results. Nonetheless,
  250. ``decipher_rot13`` has nonetheless been explicitly defined here for
  251. consistency.
  252. Examples
  253. ========
  254. >>> from sympy.crypto.crypto import encipher_rot13, decipher_rot13
  255. >>> msg = 'GONAVYBEATARMY'
  256. >>> ciphertext = encipher_rot13(msg);ciphertext
  257. 'TBANILORNGNEZL'
  258. >>> decipher_rot13(ciphertext)
  259. 'GONAVYBEATARMY'
  260. >>> encipher_rot13(msg) == decipher_rot13(msg)
  261. True
  262. >>> msg == decipher_rot13(ciphertext)
  263. True
  264. """
  265. return decipher_shift(msg, 13, symbols)
  266. ######## affine cipher examples ############
  267. def encipher_affine(msg, key, symbols=None, _inverse=False):
  268. r"""
  269. Performs the affine cipher encryption on plaintext ``msg``, and
  270. returns the ciphertext.
  271. Explanation
  272. ===========
  273. Encryption is based on the map `x \rightarrow ax+b` (mod `N`)
  274. where ``N`` is the number of characters in the alphabet.
  275. Decryption is based on the map `x \rightarrow cx+d` (mod `N`),
  276. where `c = a^{-1}` (mod `N`) and `d = -a^{-1}b` (mod `N`).
  277. In particular, for the map to be invertible, we need
  278. `\mathrm{gcd}(a, N) = 1` and an error will be raised if this is
  279. not true.
  280. Parameters
  281. ==========
  282. msg : str
  283. Characters that appear in ``symbols``.
  284. a, b : int, int
  285. A pair integers, with ``gcd(a, N) = 1`` (the secret key).
  286. symbols
  287. String of characters (default = uppercase letters).
  288. When no symbols are given, ``msg`` is converted to upper case
  289. letters and all other characters are ignored.
  290. Returns
  291. =======
  292. ct
  293. String of characters (the ciphertext message)
  294. Notes
  295. =====
  296. ALGORITHM:
  297. STEPS:
  298. 0. Number the letters of the alphabet from 0, ..., N
  299. 1. Compute from the string ``msg`` a list ``L1`` of
  300. corresponding integers.
  301. 2. Compute from the list ``L1`` a new list ``L2``, given by
  302. replacing ``x`` by ``a*x + b (mod N)``, for each element
  303. ``x`` in ``L1``.
  304. 3. Compute from the list ``L2`` a string ``ct`` of
  305. corresponding letters.
  306. This is a straightforward generalization of the shift cipher with
  307. the added complexity of requiring 2 characters to be deciphered in
  308. order to recover the key.
  309. References
  310. ==========
  311. .. [1] https://en.wikipedia.org/wiki/Affine_cipher
  312. See Also
  313. ========
  314. decipher_affine
  315. """
  316. msg, _, A = _prep(msg, '', symbols)
  317. N = len(A)
  318. a, b = key
  319. assert gcd(a, N) == 1
  320. if _inverse:
  321. c = mod_inverse(a, N)
  322. d = -b*c
  323. a, b = c, d
  324. B = ''.join([A[(a*i + b) % N] for i in range(N)])
  325. return translate(msg, A, B)
  326. def decipher_affine(msg, key, symbols=None):
  327. r"""
  328. Return the deciphered text that was made from the mapping,
  329. `x \rightarrow ax+b` (mod `N`), where ``N`` is the
  330. number of characters in the alphabet. Deciphering is done by
  331. reciphering with a new key: `x \rightarrow cx+d` (mod `N`),
  332. where `c = a^{-1}` (mod `N`) and `d = -a^{-1}b` (mod `N`).
  333. Examples
  334. ========
  335. >>> from sympy.crypto.crypto import encipher_affine, decipher_affine
  336. >>> msg = "GO NAVY BEAT ARMY"
  337. >>> key = (3, 1)
  338. >>> encipher_affine(msg, key)
  339. 'TROBMVENBGBALV'
  340. >>> decipher_affine(_, key)
  341. 'GONAVYBEATARMY'
  342. See Also
  343. ========
  344. encipher_affine
  345. """
  346. return encipher_affine(msg, key, symbols, _inverse=True)
  347. def encipher_atbash(msg, symbols=None):
  348. r"""
  349. Enciphers a given ``msg`` into its Atbash ciphertext and returns it.
  350. Explanation
  351. ===========
  352. Atbash is a substitution cipher originally used to encrypt the Hebrew
  353. alphabet. Atbash works on the principle of mapping each alphabet to its
  354. reverse / counterpart (i.e. a would map to z, b to y etc.)
  355. Atbash is functionally equivalent to the affine cipher with ``a = 25``
  356. and ``b = 25``
  357. See Also
  358. ========
  359. decipher_atbash
  360. """
  361. return encipher_affine(msg, (25, 25), symbols)
  362. def decipher_atbash(msg, symbols=None):
  363. r"""
  364. Deciphers a given ``msg`` using Atbash cipher and returns it.
  365. Explanation
  366. ===========
  367. ``decipher_atbash`` is functionally equivalent to ``encipher_atbash``.
  368. However, it has still been added as a separate function to maintain
  369. consistency.
  370. Examples
  371. ========
  372. >>> from sympy.crypto.crypto import encipher_atbash, decipher_atbash
  373. >>> msg = 'GONAVYBEATARMY'
  374. >>> encipher_atbash(msg)
  375. 'TLMZEBYVZGZINB'
  376. >>> decipher_atbash(msg)
  377. 'TLMZEBYVZGZINB'
  378. >>> encipher_atbash(msg) == decipher_atbash(msg)
  379. True
  380. >>> msg == encipher_atbash(encipher_atbash(msg))
  381. True
  382. References
  383. ==========
  384. .. [1] https://en.wikipedia.org/wiki/Atbash
  385. See Also
  386. ========
  387. encipher_atbash
  388. """
  389. return decipher_affine(msg, (25, 25), symbols)
  390. #################### substitution cipher ###########################
  391. def encipher_substitution(msg, old, new=None):
  392. r"""
  393. Returns the ciphertext obtained by replacing each character that
  394. appears in ``old`` with the corresponding character in ``new``.
  395. If ``old`` is a mapping, then new is ignored and the replacements
  396. defined by ``old`` are used.
  397. Explanation
  398. ===========
  399. This is a more general than the affine cipher in that the key can
  400. only be recovered by determining the mapping for each symbol.
  401. Though in practice, once a few symbols are recognized the mappings
  402. for other characters can be quickly guessed.
  403. Examples
  404. ========
  405. >>> from sympy.crypto.crypto import encipher_substitution, AZ
  406. >>> old = 'OEYAG'
  407. >>> new = '034^6'
  408. >>> msg = AZ("go navy! beat army!")
  409. >>> ct = encipher_substitution(msg, old, new); ct
  410. '60N^V4B3^T^RM4'
  411. To decrypt a substitution, reverse the last two arguments:
  412. >>> encipher_substitution(ct, new, old)
  413. 'GONAVYBEATARMY'
  414. In the special case where ``old`` and ``new`` are a permutation of
  415. order 2 (representing a transposition of characters) their order
  416. is immaterial:
  417. >>> old = 'NAVY'
  418. >>> new = 'ANYV'
  419. >>> encipher = lambda x: encipher_substitution(x, old, new)
  420. >>> encipher('NAVY')
  421. 'ANYV'
  422. >>> encipher(_)
  423. 'NAVY'
  424. The substitution cipher, in general, is a method
  425. whereby "units" (not necessarily single characters) of plaintext
  426. are replaced with ciphertext according to a regular system.
  427. >>> ords = dict(zip('abc', ['\\%i' % ord(i) for i in 'abc']))
  428. >>> print(encipher_substitution('abc', ords))
  429. \97\98\99
  430. References
  431. ==========
  432. .. [1] https://en.wikipedia.org/wiki/Substitution_cipher
  433. """
  434. return translate(msg, old, new)
  435. ######################################################################
  436. #################### Vigenere cipher examples ########################
  437. ######################################################################
  438. def encipher_vigenere(msg, key, symbols=None):
  439. """
  440. Performs the Vigenere cipher encryption on plaintext ``msg``, and
  441. returns the ciphertext.
  442. Examples
  443. ========
  444. >>> from sympy.crypto.crypto import encipher_vigenere, AZ
  445. >>> key = "encrypt"
  446. >>> msg = "meet me on monday"
  447. >>> encipher_vigenere(msg, key)
  448. 'QRGKKTHRZQEBPR'
  449. Section 1 of the Kryptos sculpture at the CIA headquarters
  450. uses this cipher and also changes the order of the
  451. alphabet [2]_. Here is the first line of that section of
  452. the sculpture:
  453. >>> from sympy.crypto.crypto import decipher_vigenere, padded_key
  454. >>> alp = padded_key('KRYPTOS', AZ())
  455. >>> key = 'PALIMPSEST'
  456. >>> msg = 'EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJ'
  457. >>> decipher_vigenere(msg, key, alp)
  458. 'BETWEENSUBTLESHADINGANDTHEABSENC'
  459. Explanation
  460. ===========
  461. The Vigenere cipher is named after Blaise de Vigenere, a sixteenth
  462. century diplomat and cryptographer, by a historical accident.
  463. Vigenere actually invented a different and more complicated cipher.
  464. The so-called *Vigenere cipher* was actually invented
  465. by Giovan Batista Belaso in 1553.
  466. This cipher was used in the 1800's, for example, during the American
  467. Civil War. The Confederacy used a brass cipher disk to implement the
  468. Vigenere cipher (now on display in the NSA Museum in Fort
  469. Meade) [1]_.
  470. The Vigenere cipher is a generalization of the shift cipher.
  471. Whereas the shift cipher shifts each letter by the same amount
  472. (that amount being the key of the shift cipher) the Vigenere
  473. cipher shifts a letter by an amount determined by the key (which is
  474. a word or phrase known only to the sender and receiver).
  475. For example, if the key was a single letter, such as "C", then the
  476. so-called Vigenere cipher is actually a shift cipher with a
  477. shift of `2` (since "C" is the 2nd letter of the alphabet, if
  478. you start counting at `0`). If the key was a word with two
  479. letters, such as "CA", then the so-called Vigenere cipher will
  480. shift letters in even positions by `2` and letters in odd positions
  481. are left alone (shifted by `0`, since "A" is the 0th letter, if
  482. you start counting at `0`).
  483. ALGORITHM:
  484. INPUT:
  485. ``msg``: string of characters that appear in ``symbols``
  486. (the plaintext)
  487. ``key``: a string of characters that appear in ``symbols``
  488. (the secret key)
  489. ``symbols``: a string of letters defining the alphabet
  490. OUTPUT:
  491. ``ct``: string of characters (the ciphertext message)
  492. STEPS:
  493. 0. Number the letters of the alphabet from 0, ..., N
  494. 1. Compute from the string ``key`` a list ``L1`` of
  495. corresponding integers. Let ``n1 = len(L1)``.
  496. 2. Compute from the string ``msg`` a list ``L2`` of
  497. corresponding integers. Let ``n2 = len(L2)``.
  498. 3. Break ``L2`` up sequentially into sublists of size
  499. ``n1``; the last sublist may be smaller than ``n1``
  500. 4. For each of these sublists ``L`` of ``L2``, compute a
  501. new list ``C`` given by ``C[i] = L[i] + L1[i] (mod N)``
  502. to the ``i``-th element in the sublist, for each ``i``.
  503. 5. Assemble these lists ``C`` by concatenation into a new
  504. list of length ``n2``.
  505. 6. Compute from the new list a string ``ct`` of
  506. corresponding letters.
  507. Once it is known that the key is, say, `n` characters long,
  508. frequency analysis can be applied to every `n`-th letter of
  509. the ciphertext to determine the plaintext. This method is
  510. called *Kasiski examination* (although it was first discovered
  511. by Babbage). If they key is as long as the message and is
  512. comprised of randomly selected characters -- a one-time pad -- the
  513. message is theoretically unbreakable.
  514. The cipher Vigenere actually discovered is an "auto-key" cipher
  515. described as follows.
  516. ALGORITHM:
  517. INPUT:
  518. ``key``: a string of letters (the secret key)
  519. ``msg``: string of letters (the plaintext message)
  520. OUTPUT:
  521. ``ct``: string of upper-case letters (the ciphertext message)
  522. STEPS:
  523. 0. Number the letters of the alphabet from 0, ..., N
  524. 1. Compute from the string ``msg`` a list ``L2`` of
  525. corresponding integers. Let ``n2 = len(L2)``.
  526. 2. Let ``n1`` be the length of the key. Append to the
  527. string ``key`` the first ``n2 - n1`` characters of
  528. the plaintext message. Compute from this string (also of
  529. length ``n2``) a list ``L1`` of integers corresponding
  530. to the letter numbers in the first step.
  531. 3. Compute a new list ``C`` given by
  532. ``C[i] = L1[i] + L2[i] (mod N)``.
  533. 4. Compute from the new list a string ``ct`` of letters
  534. corresponding to the new integers.
  535. To decipher the auto-key ciphertext, the key is used to decipher
  536. the first ``n1`` characters and then those characters become the
  537. key to decipher the next ``n1`` characters, etc...:
  538. >>> m = AZ('go navy, beat army! yes you can'); m
  539. 'GONAVYBEATARMYYESYOUCAN'
  540. >>> key = AZ('gold bug'); n1 = len(key); n2 = len(m)
  541. >>> auto_key = key + m[:n2 - n1]; auto_key
  542. 'GOLDBUGGONAVYBEATARMYYE'
  543. >>> ct = encipher_vigenere(m, auto_key); ct
  544. 'MCYDWSHKOGAMKZCELYFGAYR'
  545. >>> n1 = len(key)
  546. >>> pt = []
  547. >>> while ct:
  548. ... part, ct = ct[:n1], ct[n1:]
  549. ... pt.append(decipher_vigenere(part, key))
  550. ... key = pt[-1]
  551. ...
  552. >>> ''.join(pt) == m
  553. True
  554. References
  555. ==========
  556. .. [1] https://en.wikipedia.org/wiki/Vigenere_cipher
  557. .. [2] http://web.archive.org/web/20071116100808/
  558. .. [3] http://filebox.vt.edu/users/batman/kryptos.html
  559. (short URL: https://goo.gl/ijr22d)
  560. """
  561. msg, key, A = _prep(msg, key, symbols)
  562. map = {c: i for i, c in enumerate(A)}
  563. key = [map[c] for c in key]
  564. N = len(map)
  565. k = len(key)
  566. rv = []
  567. for i, m in enumerate(msg):
  568. rv.append(A[(map[m] + key[i % k]) % N])
  569. rv = ''.join(rv)
  570. return rv
  571. def decipher_vigenere(msg, key, symbols=None):
  572. """
  573. Decode using the Vigenere cipher.
  574. Examples
  575. ========
  576. >>> from sympy.crypto.crypto import decipher_vigenere
  577. >>> key = "encrypt"
  578. >>> ct = "QRGK kt HRZQE BPR"
  579. >>> decipher_vigenere(ct, key)
  580. 'MEETMEONMONDAY'
  581. """
  582. msg, key, A = _prep(msg, key, symbols)
  583. map = {c: i for i, c in enumerate(A)}
  584. N = len(A) # normally, 26
  585. K = [map[c] for c in key]
  586. n = len(K)
  587. C = [map[c] for c in msg]
  588. rv = ''.join([A[(-K[i % n] + c) % N] for i, c in enumerate(C)])
  589. return rv
  590. #################### Hill cipher ########################
  591. def encipher_hill(msg, key, symbols=None, pad="Q"):
  592. r"""
  593. Return the Hill cipher encryption of ``msg``.
  594. Explanation
  595. ===========
  596. The Hill cipher [1]_, invented by Lester S. Hill in the 1920's [2]_,
  597. was the first polygraphic cipher in which it was practical
  598. (though barely) to operate on more than three symbols at once.
  599. The following discussion assumes an elementary knowledge of
  600. matrices.
  601. First, each letter is first encoded as a number starting with 0.
  602. Suppose your message `msg` consists of `n` capital letters, with no
  603. spaces. This may be regarded an `n`-tuple M of elements of
  604. `Z_{26}` (if the letters are those of the English alphabet). A key
  605. in the Hill cipher is a `k x k` matrix `K`, all of whose entries
  606. are in `Z_{26}`, such that the matrix `K` is invertible (i.e., the
  607. linear transformation `K: Z_{N}^k \rightarrow Z_{N}^k`
  608. is one-to-one).
  609. Parameters
  610. ==========
  611. msg
  612. Plaintext message of `n` upper-case letters.
  613. key
  614. A `k \times k` invertible matrix `K`, all of whose entries are
  615. in `Z_{26}` (or whatever number of symbols are being used).
  616. pad
  617. Character (default "Q") to use to make length of text be a
  618. multiple of ``k``.
  619. Returns
  620. =======
  621. ct
  622. Ciphertext of upper-case letters.
  623. Notes
  624. =====
  625. ALGORITHM:
  626. STEPS:
  627. 0. Number the letters of the alphabet from 0, ..., N
  628. 1. Compute from the string ``msg`` a list ``L`` of
  629. corresponding integers. Let ``n = len(L)``.
  630. 2. Break the list ``L`` up into ``t = ceiling(n/k)``
  631. sublists ``L_1``, ..., ``L_t`` of size ``k`` (with
  632. the last list "padded" to ensure its size is
  633. ``k``).
  634. 3. Compute new list ``C_1``, ..., ``C_t`` given by
  635. ``C[i] = K*L_i`` (arithmetic is done mod N), for each
  636. ``i``.
  637. 4. Concatenate these into a list ``C = C_1 + ... + C_t``.
  638. 5. Compute from ``C`` a string ``ct`` of corresponding
  639. letters. This has length ``k*t``.
  640. References
  641. ==========
  642. .. [1] https://en.wikipedia.org/wiki/Hill_cipher
  643. .. [2] Lester S. Hill, Cryptography in an Algebraic Alphabet,
  644. The American Mathematical Monthly Vol.36, June-July 1929,
  645. pp.306-312.
  646. See Also
  647. ========
  648. decipher_hill
  649. """
  650. assert key.is_square
  651. assert len(pad) == 1
  652. msg, pad, A = _prep(msg, pad, symbols)
  653. map = {c: i for i, c in enumerate(A)}
  654. P = [map[c] for c in msg]
  655. N = len(A)
  656. k = key.cols
  657. n = len(P)
  658. m, r = divmod(n, k)
  659. if r:
  660. P = P + [map[pad]]*(k - r)
  661. m += 1
  662. rv = ''.join([A[c % N] for j in range(m) for c in
  663. list(key*Matrix(k, 1, [P[i]
  664. for i in range(k*j, k*(j + 1))]))])
  665. return rv
  666. def decipher_hill(msg, key, symbols=None):
  667. """
  668. Deciphering is the same as enciphering but using the inverse of the
  669. key matrix.
  670. Examples
  671. ========
  672. >>> from sympy.crypto.crypto import encipher_hill, decipher_hill
  673. >>> from sympy import Matrix
  674. >>> key = Matrix([[1, 2], [3, 5]])
  675. >>> encipher_hill("meet me on monday", key)
  676. 'UEQDUEODOCTCWQ'
  677. >>> decipher_hill(_, key)
  678. 'MEETMEONMONDAY'
  679. When the length of the plaintext (stripped of invalid characters)
  680. is not a multiple of the key dimension, extra characters will
  681. appear at the end of the enciphered and deciphered text. In order to
  682. decipher the text, those characters must be included in the text to
  683. be deciphered. In the following, the key has a dimension of 4 but
  684. the text is 2 short of being a multiple of 4 so two characters will
  685. be added.
  686. >>> key = Matrix([[1, 1, 1, 2], [0, 1, 1, 0],
  687. ... [2, 2, 3, 4], [1, 1, 0, 1]])
  688. >>> msg = "ST"
  689. >>> encipher_hill(msg, key)
  690. 'HJEB'
  691. >>> decipher_hill(_, key)
  692. 'STQQ'
  693. >>> encipher_hill(msg, key, pad="Z")
  694. 'ISPK'
  695. >>> decipher_hill(_, key)
  696. 'STZZ'
  697. If the last two characters of the ciphertext were ignored in
  698. either case, the wrong plaintext would be recovered:
  699. >>> decipher_hill("HD", key)
  700. 'ORMV'
  701. >>> decipher_hill("IS", key)
  702. 'UIKY'
  703. See Also
  704. ========
  705. encipher_hill
  706. """
  707. assert key.is_square
  708. msg, _, A = _prep(msg, '', symbols)
  709. map = {c: i for i, c in enumerate(A)}
  710. C = [map[c] for c in msg]
  711. N = len(A)
  712. k = key.cols
  713. n = len(C)
  714. m, r = divmod(n, k)
  715. if r:
  716. C = C + [0]*(k - r)
  717. m += 1
  718. key_inv = key.inv_mod(N)
  719. rv = ''.join([A[p % N] for j in range(m) for p in
  720. list(key_inv*Matrix(
  721. k, 1, [C[i] for i in range(k*j, k*(j + 1))]))])
  722. return rv
  723. #################### Bifid cipher ########################
  724. def encipher_bifid(msg, key, symbols=None):
  725. r"""
  726. Performs the Bifid cipher encryption on plaintext ``msg``, and
  727. returns the ciphertext.
  728. This is the version of the Bifid cipher that uses an `n \times n`
  729. Polybius square.
  730. Parameters
  731. ==========
  732. msg
  733. Plaintext string.
  734. key
  735. Short string for key.
  736. Duplicate characters are ignored and then it is padded with the
  737. characters in ``symbols`` that were not in the short key.
  738. symbols
  739. `n \times n` characters defining the alphabet.
  740. (default is string.printable)
  741. Returns
  742. =======
  743. ciphertext
  744. Ciphertext using Bifid5 cipher without spaces.
  745. See Also
  746. ========
  747. decipher_bifid, encipher_bifid5, encipher_bifid6
  748. References
  749. ==========
  750. .. [1] https://en.wikipedia.org/wiki/Bifid_cipher
  751. """
  752. msg, key, A = _prep(msg, key, symbols, bifid10)
  753. long_key = ''.join(uniq(key)) or A
  754. n = len(A)**.5
  755. if n != int(n):
  756. raise ValueError(
  757. 'Length of alphabet (%s) is not a square number.' % len(A))
  758. N = int(n)
  759. if len(long_key) < N**2:
  760. long_key = list(long_key) + [x for x in A if x not in long_key]
  761. # the fractionalization
  762. row_col = {ch: divmod(i, N) for i, ch in enumerate(long_key)}
  763. r, c = zip(*[row_col[x] for x in msg])
  764. rc = r + c
  765. ch = {i: ch for ch, i in row_col.items()}
  766. rv = ''.join(ch[i] for i in zip(rc[::2], rc[1::2]))
  767. return rv
  768. def decipher_bifid(msg, key, symbols=None):
  769. r"""
  770. Performs the Bifid cipher decryption on ciphertext ``msg``, and
  771. returns the plaintext.
  772. This is the version of the Bifid cipher that uses the `n \times n`
  773. Polybius square.
  774. Parameters
  775. ==========
  776. msg
  777. Ciphertext string.
  778. key
  779. Short string for key.
  780. Duplicate characters are ignored and then it is padded with the
  781. characters in symbols that were not in the short key.
  782. symbols
  783. `n \times n` characters defining the alphabet.
  784. (default=string.printable, a `10 \times 10` matrix)
  785. Returns
  786. =======
  787. deciphered
  788. Deciphered text.
  789. Examples
  790. ========
  791. >>> from sympy.crypto.crypto import (
  792. ... encipher_bifid, decipher_bifid, AZ)
  793. Do an encryption using the bifid5 alphabet:
  794. >>> alp = AZ().replace('J', '')
  795. >>> ct = AZ("meet me on monday!")
  796. >>> key = AZ("gold bug")
  797. >>> encipher_bifid(ct, key, alp)
  798. 'IEILHHFSTSFQYE'
  799. When entering the text or ciphertext, spaces are ignored so it
  800. can be formatted as desired. Re-entering the ciphertext from the
  801. preceding, putting 4 characters per line and padding with an extra
  802. J, does not cause problems for the deciphering:
  803. >>> decipher_bifid('''
  804. ... IEILH
  805. ... HFSTS
  806. ... FQYEJ''', key, alp)
  807. 'MEETMEONMONDAY'
  808. When no alphabet is given, all 100 printable characters will be
  809. used:
  810. >>> key = ''
  811. >>> encipher_bifid('hello world!', key)
  812. 'bmtwmg-bIo*w'
  813. >>> decipher_bifid(_, key)
  814. 'hello world!'
  815. If the key is changed, a different encryption is obtained:
  816. >>> key = 'gold bug'
  817. >>> encipher_bifid('hello world!', 'gold_bug')
  818. 'hg2sfuei7t}w'
  819. And if the key used to decrypt the message is not exact, the
  820. original text will not be perfectly obtained:
  821. >>> decipher_bifid(_, 'gold pug')
  822. 'heldo~wor6d!'
  823. """
  824. msg, _, A = _prep(msg, '', symbols, bifid10)
  825. long_key = ''.join(uniq(key)) or A
  826. n = len(A)**.5
  827. if n != int(n):
  828. raise ValueError(
  829. 'Length of alphabet (%s) is not a square number.' % len(A))
  830. N = int(n)
  831. if len(long_key) < N**2:
  832. long_key = list(long_key) + [x for x in A if x not in long_key]
  833. # the reverse fractionalization
  834. row_col = {
  835. ch: divmod(i, N) for i, ch in enumerate(long_key)}
  836. rc = [i for c in msg for i in row_col[c]]
  837. n = len(msg)
  838. rc = zip(*(rc[:n], rc[n:]))
  839. ch = {i: ch for ch, i in row_col.items()}
  840. rv = ''.join(ch[i] for i in rc)
  841. return rv
  842. def bifid_square(key):
  843. """Return characters of ``key`` arranged in a square.
  844. Examples
  845. ========
  846. >>> from sympy.crypto.crypto import (
  847. ... bifid_square, AZ, padded_key, bifid5)
  848. >>> bifid_square(AZ().replace('J', ''))
  849. Matrix([
  850. [A, B, C, D, E],
  851. [F, G, H, I, K],
  852. [L, M, N, O, P],
  853. [Q, R, S, T, U],
  854. [V, W, X, Y, Z]])
  855. >>> bifid_square(padded_key(AZ('gold bug!'), bifid5))
  856. Matrix([
  857. [G, O, L, D, B],
  858. [U, A, C, E, F],
  859. [H, I, K, M, N],
  860. [P, Q, R, S, T],
  861. [V, W, X, Y, Z]])
  862. See Also
  863. ========
  864. padded_key
  865. """
  866. A = ''.join(uniq(''.join(key)))
  867. n = len(A)**.5
  868. if n != int(n):
  869. raise ValueError(
  870. 'Length of alphabet (%s) is not a square number.' % len(A))
  871. n = int(n)
  872. f = lambda i, j: Symbol(A[n*i + j])
  873. rv = Matrix(n, n, f)
  874. return rv
  875. def encipher_bifid5(msg, key):
  876. r"""
  877. Performs the Bifid cipher encryption on plaintext ``msg``, and
  878. returns the ciphertext.
  879. Explanation
  880. ===========
  881. This is the version of the Bifid cipher that uses the `5 \times 5`
  882. Polybius square. The letter "J" is ignored so it must be replaced
  883. with something else (traditionally an "I") before encryption.
  884. ALGORITHM: (5x5 case)
  885. STEPS:
  886. 0. Create the `5 \times 5` Polybius square ``S`` associated
  887. to ``key`` as follows:
  888. a) moving from left-to-right, top-to-bottom,
  889. place the letters of the key into a `5 \times 5`
  890. matrix,
  891. b) if the key has less than 25 letters, add the
  892. letters of the alphabet not in the key until the
  893. `5 \times 5` square is filled.
  894. 1. Create a list ``P`` of pairs of numbers which are the
  895. coordinates in the Polybius square of the letters in
  896. ``msg``.
  897. 2. Let ``L1`` be the list of all first coordinates of ``P``
  898. (length of ``L1 = n``), let ``L2`` be the list of all
  899. second coordinates of ``P`` (so the length of ``L2``
  900. is also ``n``).
  901. 3. Let ``L`` be the concatenation of ``L1`` and ``L2``
  902. (length ``L = 2*n``), except that consecutive numbers
  903. are paired ``(L[2*i], L[2*i + 1])``. You can regard
  904. ``L`` as a list of pairs of length ``n``.
  905. 4. Let ``C`` be the list of all letters which are of the
  906. form ``S[i, j]``, for all ``(i, j)`` in ``L``. As a
  907. string, this is the ciphertext of ``msg``.
  908. Parameters
  909. ==========
  910. msg : str
  911. Plaintext string.
  912. Converted to upper case and filtered of anything but all letters
  913. except J.
  914. key
  915. Short string for key; non-alphabetic letters, J and duplicated
  916. characters are ignored and then, if the length is less than 25
  917. characters, it is padded with other letters of the alphabet
  918. (in alphabetical order).
  919. Returns
  920. =======
  921. ct
  922. Ciphertext (all caps, no spaces).
  923. Examples
  924. ========
  925. >>> from sympy.crypto.crypto import (
  926. ... encipher_bifid5, decipher_bifid5)
  927. "J" will be omitted unless it is replaced with something else:
  928. >>> round_trip = lambda m, k: \
  929. ... decipher_bifid5(encipher_bifid5(m, k), k)
  930. >>> key = 'a'
  931. >>> msg = "JOSIE"
  932. >>> round_trip(msg, key)
  933. 'OSIE'
  934. >>> round_trip(msg.replace("J", "I"), key)
  935. 'IOSIE'
  936. >>> j = "QIQ"
  937. >>> round_trip(msg.replace("J", j), key).replace(j, "J")
  938. 'JOSIE'
  939. Notes
  940. =====
  941. The Bifid cipher was invented around 1901 by Felix Delastelle.
  942. It is a *fractional substitution* cipher, where letters are
  943. replaced by pairs of symbols from a smaller alphabet. The
  944. cipher uses a `5 \times 5` square filled with some ordering of the
  945. alphabet, except that "J" is replaced with "I" (this is a so-called
  946. Polybius square; there is a `6 \times 6` analog if you add back in
  947. "J" and also append onto the usual 26 letter alphabet, the digits
  948. 0, 1, ..., 9).
  949. According to Helen Gaines' book *Cryptanalysis*, this type of cipher
  950. was used in the field by the German Army during World War I.
  951. See Also
  952. ========
  953. decipher_bifid5, encipher_bifid
  954. """
  955. msg, key, _ = _prep(msg.upper(), key.upper(), None, bifid5)
  956. key = padded_key(key, bifid5)
  957. return encipher_bifid(msg, '', key)
  958. def decipher_bifid5(msg, key):
  959. r"""
  960. Return the Bifid cipher decryption of ``msg``.
  961. Explanation
  962. ===========
  963. This is the version of the Bifid cipher that uses the `5 \times 5`
  964. Polybius square; the letter "J" is ignored unless a ``key`` of
  965. length 25 is used.
  966. Parameters
  967. ==========
  968. msg
  969. Ciphertext string.
  970. key
  971. Short string for key; duplicated characters are ignored and if
  972. the length is less then 25 characters, it will be padded with
  973. other letters from the alphabet omitting "J".
  974. Non-alphabetic characters are ignored.
  975. Returns
  976. =======
  977. plaintext
  978. Plaintext from Bifid5 cipher (all caps, no spaces).
  979. Examples
  980. ========
  981. >>> from sympy.crypto.crypto import encipher_bifid5, decipher_bifid5
  982. >>> key = "gold bug"
  983. >>> encipher_bifid5('meet me on friday', key)
  984. 'IEILEHFSTSFXEE'
  985. >>> encipher_bifid5('meet me on monday', key)
  986. 'IEILHHFSTSFQYE'
  987. >>> decipher_bifid5(_, key)
  988. 'MEETMEONMONDAY'
  989. """
  990. msg, key, _ = _prep(msg.upper(), key.upper(), None, bifid5)
  991. key = padded_key(key, bifid5)
  992. return decipher_bifid(msg, '', key)
  993. def bifid5_square(key=None):
  994. r"""
  995. 5x5 Polybius square.
  996. Produce the Polybius square for the `5 \times 5` Bifid cipher.
  997. Examples
  998. ========
  999. >>> from sympy.crypto.crypto import bifid5_square
  1000. >>> bifid5_square("gold bug")
  1001. Matrix([
  1002. [G, O, L, D, B],
  1003. [U, A, C, E, F],
  1004. [H, I, K, M, N],
  1005. [P, Q, R, S, T],
  1006. [V, W, X, Y, Z]])
  1007. """
  1008. if not key:
  1009. key = bifid5
  1010. else:
  1011. _, key, _ = _prep('', key.upper(), None, bifid5)
  1012. key = padded_key(key, bifid5)
  1013. return bifid_square(key)
  1014. def encipher_bifid6(msg, key):
  1015. r"""
  1016. Performs the Bifid cipher encryption on plaintext ``msg``, and
  1017. returns the ciphertext.
  1018. This is the version of the Bifid cipher that uses the `6 \times 6`
  1019. Polybius square.
  1020. Parameters
  1021. ==========
  1022. msg
  1023. Plaintext string (digits okay).
  1024. key
  1025. Short string for key (digits okay).
  1026. If ``key`` is less than 36 characters long, the square will be
  1027. filled with letters A through Z and digits 0 through 9.
  1028. Returns
  1029. =======
  1030. ciphertext
  1031. Ciphertext from Bifid cipher (all caps, no spaces).
  1032. See Also
  1033. ========
  1034. decipher_bifid6, encipher_bifid
  1035. """
  1036. msg, key, _ = _prep(msg.upper(), key.upper(), None, bifid6)
  1037. key = padded_key(key, bifid6)
  1038. return encipher_bifid(msg, '', key)
  1039. def decipher_bifid6(msg, key):
  1040. r"""
  1041. Performs the Bifid cipher decryption on ciphertext ``msg``, and
  1042. returns the plaintext.
  1043. This is the version of the Bifid cipher that uses the `6 \times 6`
  1044. Polybius square.
  1045. Parameters
  1046. ==========
  1047. msg
  1048. Ciphertext string (digits okay); converted to upper case
  1049. key
  1050. Short string for key (digits okay).
  1051. If ``key`` is less than 36 characters long, the square will be
  1052. filled with letters A through Z and digits 0 through 9.
  1053. All letters are converted to uppercase.
  1054. Returns
  1055. =======
  1056. plaintext
  1057. Plaintext from Bifid cipher (all caps, no spaces).
  1058. Examples
  1059. ========
  1060. >>> from sympy.crypto.crypto import encipher_bifid6, decipher_bifid6
  1061. >>> key = "gold bug"
  1062. >>> encipher_bifid6('meet me on monday at 8am', key)
  1063. 'KFKLJJHF5MMMKTFRGPL'
  1064. >>> decipher_bifid6(_, key)
  1065. 'MEETMEONMONDAYAT8AM'
  1066. """
  1067. msg, key, _ = _prep(msg.upper(), key.upper(), None, bifid6)
  1068. key = padded_key(key, bifid6)
  1069. return decipher_bifid(msg, '', key)
  1070. def bifid6_square(key=None):
  1071. r"""
  1072. 6x6 Polybius square.
  1073. Produces the Polybius square for the `6 \times 6` Bifid cipher.
  1074. Assumes alphabet of symbols is "A", ..., "Z", "0", ..., "9".
  1075. Examples
  1076. ========
  1077. >>> from sympy.crypto.crypto import bifid6_square
  1078. >>> key = "gold bug"
  1079. >>> bifid6_square(key)
  1080. Matrix([
  1081. [G, O, L, D, B, U],
  1082. [A, C, E, F, H, I],
  1083. [J, K, M, N, P, Q],
  1084. [R, S, T, V, W, X],
  1085. [Y, Z, 0, 1, 2, 3],
  1086. [4, 5, 6, 7, 8, 9]])
  1087. """
  1088. if not key:
  1089. key = bifid6
  1090. else:
  1091. _, key, _ = _prep('', key.upper(), None, bifid6)
  1092. key = padded_key(key, bifid6)
  1093. return bifid_square(key)
  1094. #################### RSA #############################
  1095. def _decipher_rsa_crt(i, d, factors):
  1096. """Decipher RSA using chinese remainder theorem from the information
  1097. of the relatively-prime factors of the modulus.
  1098. Parameters
  1099. ==========
  1100. i : integer
  1101. Ciphertext
  1102. d : integer
  1103. The exponent component.
  1104. factors : list of relatively-prime integers
  1105. The integers given must be coprime and the product must equal
  1106. the modulus component of the original RSA key.
  1107. Examples
  1108. ========
  1109. How to decrypt RSA with CRT:
  1110. >>> from sympy.crypto.crypto import rsa_public_key, rsa_private_key
  1111. >>> primes = [61, 53]
  1112. >>> e = 17
  1113. >>> args = primes + [e]
  1114. >>> puk = rsa_public_key(*args)
  1115. >>> prk = rsa_private_key(*args)
  1116. >>> from sympy.crypto.crypto import encipher_rsa, _decipher_rsa_crt
  1117. >>> msg = 65
  1118. >>> crt_primes = primes
  1119. >>> encrypted = encipher_rsa(msg, puk)
  1120. >>> decrypted = _decipher_rsa_crt(encrypted, prk[1], primes)
  1121. >>> decrypted
  1122. 65
  1123. """
  1124. from sympy.ntheory.modular import crt
  1125. moduluses = [pow(i, d, p) for p in factors]
  1126. result = crt(factors, moduluses)
  1127. if not result:
  1128. raise ValueError("CRT failed")
  1129. return result[0]
  1130. def _rsa_key(*args, public=True, private=True, totient='Euler', index=None, multipower=None):
  1131. r"""A private subroutine to generate RSA key
  1132. Parameters
  1133. ==========
  1134. public, private : bool, optional
  1135. Flag to generate either a public key, a private key.
  1136. totient : 'Euler' or 'Carmichael'
  1137. Different notation used for totient.
  1138. multipower : bool, optional
  1139. Flag to bypass warning for multipower RSA.
  1140. """
  1141. from sympy.ntheory import totient as _euler
  1142. from sympy.ntheory import reduced_totient as _carmichael
  1143. if len(args) < 2:
  1144. return False
  1145. if totient not in ('Euler', 'Carmichael'):
  1146. raise ValueError(
  1147. "The argument totient={} should either be " \
  1148. "'Euler', 'Carmichalel'." \
  1149. .format(totient))
  1150. if totient == 'Euler':
  1151. _totient = _euler
  1152. else:
  1153. _totient = _carmichael
  1154. if index is not None:
  1155. index = as_int(index)
  1156. if totient != 'Carmichael':
  1157. raise ValueError(
  1158. "Setting the 'index' keyword argument requires totient"
  1159. "notation to be specified as 'Carmichael'.")
  1160. primes, e = args[:-1], args[-1]
  1161. if not all(isprime(p) for p in primes):
  1162. new_primes = []
  1163. for i in primes:
  1164. new_primes.extend(factorint(i, multiple=True))
  1165. primes = new_primes
  1166. n = reduce(lambda i, j: i*j, primes)
  1167. tally = multiset(primes)
  1168. if all(v == 1 for v in tally.values()):
  1169. multiple = list(tally.keys())
  1170. phi = _totient._from_distinct_primes(*multiple)
  1171. else:
  1172. if not multipower:
  1173. NonInvertibleCipherWarning(
  1174. 'Non-distinctive primes found in the factors {}. '
  1175. 'The cipher may not be decryptable for some numbers '
  1176. 'in the complete residue system Z[{}], but the cipher '
  1177. 'can still be valid if you restrict the domain to be '
  1178. 'the reduced residue system Z*[{}]. You can pass '
  1179. 'the flag multipower=True if you want to suppress this '
  1180. 'warning.'
  1181. .format(primes, n, n)
  1182. # stacklevel=4 because most users will call a function that
  1183. # calls this function
  1184. ).warn(stacklevel=4)
  1185. phi = _totient._from_factors(tally)
  1186. if igcd(e, phi) == 1:
  1187. if public and not private:
  1188. if isinstance(index, int):
  1189. e = e % phi
  1190. e += index * phi
  1191. return n, e
  1192. if private and not public:
  1193. d = mod_inverse(e, phi)
  1194. if isinstance(index, int):
  1195. d += index * phi
  1196. return n, d
  1197. return False
  1198. def rsa_public_key(*args, **kwargs):
  1199. r"""Return the RSA *public key* pair, `(n, e)`
  1200. Parameters
  1201. ==========
  1202. args : naturals
  1203. If specified as `p, q, e` where `p` and `q` are distinct primes
  1204. and `e` is a desired public exponent of the RSA, `n = p q` and
  1205. `e` will be verified against the totient
  1206. `\phi(n)` (Euler totient) or `\lambda(n)` (Carmichael totient)
  1207. to be `\gcd(e, \phi(n)) = 1` or `\gcd(e, \lambda(n)) = 1`.
  1208. If specified as `p_1, p_2, \dots, p_n, e` where
  1209. `p_1, p_2, \dots, p_n` are specified as primes,
  1210. and `e` is specified as a desired public exponent of the RSA,
  1211. it will be able to form a multi-prime RSA, which is a more
  1212. generalized form of the popular 2-prime RSA.
  1213. It can also be possible to form a single-prime RSA by specifying
  1214. the argument as `p, e`, which can be considered a trivial case
  1215. of a multiprime RSA.
  1216. Furthermore, it can be possible to form a multi-power RSA by
  1217. specifying two or more pairs of the primes to be same.
  1218. However, unlike the two-distinct prime RSA or multi-prime
  1219. RSA, not every numbers in the complete residue system
  1220. (`\mathbb{Z}_n`) will be decryptable since the mapping
  1221. `\mathbb{Z}_{n} \rightarrow \mathbb{Z}_{n}`
  1222. will not be bijective.
  1223. (Only except for the trivial case when
  1224. `e = 1`
  1225. or more generally,
  1226. .. math::
  1227. e \in \left \{ 1 + k \lambda(n)
  1228. \mid k \in \mathbb{Z} \land k \geq 0 \right \}
  1229. when RSA reduces to the identity.)
  1230. However, the RSA can still be decryptable for the numbers in the
  1231. reduced residue system (`\mathbb{Z}_n^{\times}`), since the
  1232. mapping
  1233. `\mathbb{Z}_{n}^{\times} \rightarrow \mathbb{Z}_{n}^{\times}`
  1234. can still be bijective.
  1235. If you pass a non-prime integer to the arguments
  1236. `p_1, p_2, \dots, p_n`, the particular number will be
  1237. prime-factored and it will become either a multi-prime RSA or a
  1238. multi-power RSA in its canonical form, depending on whether the
  1239. product equals its radical or not.
  1240. `p_1 p_2 \dots p_n = \text{rad}(p_1 p_2 \dots p_n)`
  1241. totient : bool, optional
  1242. If ``'Euler'``, it uses Euler's totient `\phi(n)` which is
  1243. :meth:`sympy.ntheory.factor_.totient` in SymPy.
  1244. If ``'Carmichael'``, it uses Carmichael's totient `\lambda(n)`
  1245. which is :meth:`sympy.ntheory.factor_.reduced_totient` in SymPy.
  1246. Unlike private key generation, this is a trivial keyword for
  1247. public key generation because
  1248. `\gcd(e, \phi(n)) = 1 \iff \gcd(e, \lambda(n)) = 1`.
  1249. index : nonnegative integer, optional
  1250. Returns an arbitrary solution of a RSA public key at the index
  1251. specified at `0, 1, 2, \dots`. This parameter needs to be
  1252. specified along with ``totient='Carmichael'``.
  1253. Similarly to the non-uniquenss of a RSA private key as described
  1254. in the ``index`` parameter documentation in
  1255. :meth:`rsa_private_key`, RSA public key is also not unique and
  1256. there is an infinite number of RSA public exponents which
  1257. can behave in the same manner.
  1258. From any given RSA public exponent `e`, there are can be an
  1259. another RSA public exponent `e + k \lambda(n)` where `k` is an
  1260. integer, `\lambda` is a Carmichael's totient function.
  1261. However, considering only the positive cases, there can be
  1262. a principal solution of a RSA public exponent `e_0` in
  1263. `0 < e_0 < \lambda(n)`, and all the other solutions
  1264. can be canonicalzed in a form of `e_0 + k \lambda(n)`.
  1265. ``index`` specifies the `k` notation to yield any possible value
  1266. an RSA public key can have.
  1267. An example of computing any arbitrary RSA public key:
  1268. >>> from sympy.crypto.crypto import rsa_public_key
  1269. >>> rsa_public_key(61, 53, 17, totient='Carmichael', index=0)
  1270. (3233, 17)
  1271. >>> rsa_public_key(61, 53, 17, totient='Carmichael', index=1)
  1272. (3233, 797)
  1273. >>> rsa_public_key(61, 53, 17, totient='Carmichael', index=2)
  1274. (3233, 1577)
  1275. multipower : bool, optional
  1276. Any pair of non-distinct primes found in the RSA specification
  1277. will restrict the domain of the cryptosystem, as noted in the
  1278. explanation of the parameter ``args``.
  1279. SymPy RSA key generator may give a warning before dispatching it
  1280. as a multi-power RSA, however, you can disable the warning if
  1281. you pass ``True`` to this keyword.
  1282. Returns
  1283. =======
  1284. (n, e) : int, int
  1285. `n` is a product of any arbitrary number of primes given as
  1286. the argument.
  1287. `e` is relatively prime (coprime) to the Euler totient
  1288. `\phi(n)`.
  1289. False
  1290. Returned if less than two arguments are given, or `e` is
  1291. not relatively prime to the modulus.
  1292. Examples
  1293. ========
  1294. >>> from sympy.crypto.crypto import rsa_public_key
  1295. A public key of a two-prime RSA:
  1296. >>> p, q, e = 3, 5, 7
  1297. >>> rsa_public_key(p, q, e)
  1298. (15, 7)
  1299. >>> rsa_public_key(p, q, 30)
  1300. False
  1301. A public key of a multiprime RSA:
  1302. >>> primes = [2, 3, 5, 7, 11, 13]
  1303. >>> e = 7
  1304. >>> args = primes + [e]
  1305. >>> rsa_public_key(*args)
  1306. (30030, 7)
  1307. Notes
  1308. =====
  1309. Although the RSA can be generalized over any modulus `n`, using
  1310. two large primes had became the most popular specification because a
  1311. product of two large primes is usually the hardest to factor
  1312. relatively to the digits of `n` can have.
  1313. However, it may need further understanding of the time complexities
  1314. of each prime-factoring algorithms to verify the claim.
  1315. See Also
  1316. ========
  1317. rsa_private_key
  1318. encipher_rsa
  1319. decipher_rsa
  1320. References
  1321. ==========
  1322. .. [1] https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29
  1323. .. [2] http://cacr.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
  1324. .. [3] https://link.springer.com/content/pdf/10.1007%2FBFb0055738.pdf
  1325. .. [4] http://www.itiis.org/digital-library/manuscript/1381
  1326. """
  1327. return _rsa_key(*args, public=True, private=False, **kwargs)
  1328. def rsa_private_key(*args, **kwargs):
  1329. r"""Return the RSA *private key* pair, `(n, d)`
  1330. Parameters
  1331. ==========
  1332. args : naturals
  1333. The keyword is identical to the ``args`` in
  1334. :meth:`rsa_public_key`.
  1335. totient : bool, optional
  1336. If ``'Euler'``, it uses Euler's totient convention `\phi(n)`
  1337. which is :meth:`sympy.ntheory.factor_.totient` in SymPy.
  1338. If ``'Carmichael'``, it uses Carmichael's totient convention
  1339. `\lambda(n)` which is
  1340. :meth:`sympy.ntheory.factor_.reduced_totient` in SymPy.
  1341. There can be some output differences for private key generation
  1342. as examples below.
  1343. Example using Euler's totient:
  1344. >>> from sympy.crypto.crypto import rsa_private_key
  1345. >>> rsa_private_key(61, 53, 17, totient='Euler')
  1346. (3233, 2753)
  1347. Example using Carmichael's totient:
  1348. >>> from sympy.crypto.crypto import rsa_private_key
  1349. >>> rsa_private_key(61, 53, 17, totient='Carmichael')
  1350. (3233, 413)
  1351. index : nonnegative integer, optional
  1352. Returns an arbitrary solution of a RSA private key at the index
  1353. specified at `0, 1, 2, \dots`. This parameter needs to be
  1354. specified along with ``totient='Carmichael'``.
  1355. RSA private exponent is a non-unique solution of
  1356. `e d \mod \lambda(n) = 1` and it is possible in any form of
  1357. `d + k \lambda(n)`, where `d` is an another
  1358. already-computed private exponent, and `\lambda` is a
  1359. Carmichael's totient function, and `k` is any integer.
  1360. However, considering only the positive cases, there can be
  1361. a principal solution of a RSA private exponent `d_0` in
  1362. `0 < d_0 < \lambda(n)`, and all the other solutions
  1363. can be canonicalzed in a form of `d_0 + k \lambda(n)`.
  1364. ``index`` specifies the `k` notation to yield any possible value
  1365. an RSA private key can have.
  1366. An example of computing any arbitrary RSA private key:
  1367. >>> from sympy.crypto.crypto import rsa_private_key
  1368. >>> rsa_private_key(61, 53, 17, totient='Carmichael', index=0)
  1369. (3233, 413)
  1370. >>> rsa_private_key(61, 53, 17, totient='Carmichael', index=1)
  1371. (3233, 1193)
  1372. >>> rsa_private_key(61, 53, 17, totient='Carmichael', index=2)
  1373. (3233, 1973)
  1374. multipower : bool, optional
  1375. The keyword is identical to the ``multipower`` in
  1376. :meth:`rsa_public_key`.
  1377. Returns
  1378. =======
  1379. (n, d) : int, int
  1380. `n` is a product of any arbitrary number of primes given as
  1381. the argument.
  1382. `d` is the inverse of `e` (mod `\phi(n)`) where `e` is the
  1383. exponent given, and `\phi` is a Euler totient.
  1384. False
  1385. Returned if less than two arguments are given, or `e` is
  1386. not relatively prime to the totient of the modulus.
  1387. Examples
  1388. ========
  1389. >>> from sympy.crypto.crypto import rsa_private_key
  1390. A private key of a two-prime RSA:
  1391. >>> p, q, e = 3, 5, 7
  1392. >>> rsa_private_key(p, q, e)
  1393. (15, 7)
  1394. >>> rsa_private_key(p, q, 30)
  1395. False
  1396. A private key of a multiprime RSA:
  1397. >>> primes = [2, 3, 5, 7, 11, 13]
  1398. >>> e = 7
  1399. >>> args = primes + [e]
  1400. >>> rsa_private_key(*args)
  1401. (30030, 823)
  1402. See Also
  1403. ========
  1404. rsa_public_key
  1405. encipher_rsa
  1406. decipher_rsa
  1407. References
  1408. ==========
  1409. .. [1] https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29
  1410. .. [2] http://cacr.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
  1411. .. [3] https://link.springer.com/content/pdf/10.1007%2FBFb0055738.pdf
  1412. .. [4] http://www.itiis.org/digital-library/manuscript/1381
  1413. """
  1414. return _rsa_key(*args, public=False, private=True, **kwargs)
  1415. def _encipher_decipher_rsa(i, key, factors=None):
  1416. n, d = key
  1417. if not factors:
  1418. return pow(i, d, n)
  1419. def _is_coprime_set(l):
  1420. is_coprime_set = True
  1421. for i in range(len(l)):
  1422. for j in range(i+1, len(l)):
  1423. if igcd(l[i], l[j]) != 1:
  1424. is_coprime_set = False
  1425. break
  1426. return is_coprime_set
  1427. prod = reduce(lambda i, j: i*j, factors)
  1428. if prod == n and _is_coprime_set(factors):
  1429. return _decipher_rsa_crt(i, d, factors)
  1430. return _encipher_decipher_rsa(i, key, factors=None)
  1431. def encipher_rsa(i, key, factors=None):
  1432. r"""Encrypt the plaintext with RSA.
  1433. Parameters
  1434. ==========
  1435. i : integer
  1436. The plaintext to be encrypted for.
  1437. key : (n, e) where n, e are integers
  1438. `n` is the modulus of the key and `e` is the exponent of the
  1439. key. The encryption is computed by `i^e \bmod n`.
  1440. The key can either be a public key or a private key, however,
  1441. the message encrypted by a public key can only be decrypted by
  1442. a private key, and vice versa, as RSA is an asymmetric
  1443. cryptography system.
  1444. factors : list of coprime integers
  1445. This is identical to the keyword ``factors`` in
  1446. :meth:`decipher_rsa`.
  1447. Notes
  1448. =====
  1449. Some specifications may make the RSA not cryptographically
  1450. meaningful.
  1451. For example, `0`, `1` will remain always same after taking any
  1452. number of exponentiation, thus, should be avoided.
  1453. Furthermore, if `i^e < n`, `i` may easily be figured out by taking
  1454. `e` th root.
  1455. And also, specifying the exponent as `1` or in more generalized form
  1456. as `1 + k \lambda(n)` where `k` is an nonnegative integer,
  1457. `\lambda` is a carmichael totient, the RSA becomes an identity
  1458. mapping.
  1459. Examples
  1460. ========
  1461. >>> from sympy.crypto.crypto import encipher_rsa
  1462. >>> from sympy.crypto.crypto import rsa_public_key, rsa_private_key
  1463. Public Key Encryption:
  1464. >>> p, q, e = 3, 5, 7
  1465. >>> puk = rsa_public_key(p, q, e)
  1466. >>> msg = 12
  1467. >>> encipher_rsa(msg, puk)
  1468. 3
  1469. Private Key Encryption:
  1470. >>> p, q, e = 3, 5, 7
  1471. >>> prk = rsa_private_key(p, q, e)
  1472. >>> msg = 12
  1473. >>> encipher_rsa(msg, prk)
  1474. 3
  1475. Encryption using chinese remainder theorem:
  1476. >>> encipher_rsa(msg, prk, factors=[p, q])
  1477. 3
  1478. """
  1479. return _encipher_decipher_rsa(i, key, factors=factors)
  1480. def decipher_rsa(i, key, factors=None):
  1481. r"""Decrypt the ciphertext with RSA.
  1482. Parameters
  1483. ==========
  1484. i : integer
  1485. The ciphertext to be decrypted for.
  1486. key : (n, d) where n, d are integers
  1487. `n` is the modulus of the key and `d` is the exponent of the
  1488. key. The decryption is computed by `i^d \bmod n`.
  1489. The key can either be a public key or a private key, however,
  1490. the message encrypted by a public key can only be decrypted by
  1491. a private key, and vice versa, as RSA is an asymmetric
  1492. cryptography system.
  1493. factors : list of coprime integers
  1494. As the modulus `n` created from RSA key generation is composed
  1495. of arbitrary prime factors
  1496. `n = {p_1}^{k_1}{p_2}^{k_2}\dots{p_n}^{k_n}` where
  1497. `p_1, p_2, \dots, p_n` are distinct primes and
  1498. `k_1, k_2, \dots, k_n` are positive integers, chinese remainder
  1499. theorem can be used to compute `i^d \bmod n` from the
  1500. fragmented modulo operations like
  1501. .. math::
  1502. i^d \bmod {p_1}^{k_1}, i^d \bmod {p_2}^{k_2}, \dots,
  1503. i^d \bmod {p_n}^{k_n}
  1504. or like
  1505. .. math::
  1506. i^d \bmod {p_1}^{k_1}{p_2}^{k_2},
  1507. i^d \bmod {p_3}^{k_3}, \dots ,
  1508. i^d \bmod {p_n}^{k_n}
  1509. as long as every moduli does not share any common divisor each
  1510. other.
  1511. The raw primes used in generating the RSA key pair can be a good
  1512. option.
  1513. Note that the speed advantage of using this is only viable for
  1514. very large cases (Like 2048-bit RSA keys) since the
  1515. overhead of using pure Python implementation of
  1516. :meth:`sympy.ntheory.modular.crt` may overcompensate the
  1517. theoritical speed advantage.
  1518. Notes
  1519. =====
  1520. See the ``Notes`` section in the documentation of
  1521. :meth:`encipher_rsa`
  1522. Examples
  1523. ========
  1524. >>> from sympy.crypto.crypto import decipher_rsa, encipher_rsa
  1525. >>> from sympy.crypto.crypto import rsa_public_key, rsa_private_key
  1526. Public Key Encryption and Decryption:
  1527. >>> p, q, e = 3, 5, 7
  1528. >>> prk = rsa_private_key(p, q, e)
  1529. >>> puk = rsa_public_key(p, q, e)
  1530. >>> msg = 12
  1531. >>> new_msg = encipher_rsa(msg, prk)
  1532. >>> new_msg
  1533. 3
  1534. >>> decipher_rsa(new_msg, puk)
  1535. 12
  1536. Private Key Encryption and Decryption:
  1537. >>> p, q, e = 3, 5, 7
  1538. >>> prk = rsa_private_key(p, q, e)
  1539. >>> puk = rsa_public_key(p, q, e)
  1540. >>> msg = 12
  1541. >>> new_msg = encipher_rsa(msg, puk)
  1542. >>> new_msg
  1543. 3
  1544. >>> decipher_rsa(new_msg, prk)
  1545. 12
  1546. Decryption using chinese remainder theorem:
  1547. >>> decipher_rsa(new_msg, prk, factors=[p, q])
  1548. 12
  1549. See Also
  1550. ========
  1551. encipher_rsa
  1552. """
  1553. return _encipher_decipher_rsa(i, key, factors=factors)
  1554. #################### kid krypto (kid RSA) #############################
  1555. def kid_rsa_public_key(a, b, A, B):
  1556. r"""
  1557. Kid RSA is a version of RSA useful to teach grade school children
  1558. since it does not involve exponentiation.
  1559. Explanation
  1560. ===========
  1561. Alice wants to talk to Bob. Bob generates keys as follows.
  1562. Key generation:
  1563. * Select positive integers `a, b, A, B` at random.
  1564. * Compute `M = a b - 1`, `e = A M + a`, `d = B M + b`,
  1565. `n = (e d - 1)//M`.
  1566. * The *public key* is `(n, e)`. Bob sends these to Alice.
  1567. * The *private key* is `(n, d)`, which Bob keeps secret.
  1568. Encryption: If `p` is the plaintext message then the
  1569. ciphertext is `c = p e \pmod n`.
  1570. Decryption: If `c` is the ciphertext message then the
  1571. plaintext is `p = c d \pmod n`.
  1572. Examples
  1573. ========
  1574. >>> from sympy.crypto.crypto import kid_rsa_public_key
  1575. >>> a, b, A, B = 3, 4, 5, 6
  1576. >>> kid_rsa_public_key(a, b, A, B)
  1577. (369, 58)
  1578. """
  1579. M = a*b - 1
  1580. e = A*M + a
  1581. d = B*M + b
  1582. n = (e*d - 1)//M
  1583. return n, e
  1584. def kid_rsa_private_key(a, b, A, B):
  1585. """
  1586. Compute `M = a b - 1`, `e = A M + a`, `d = B M + b`,
  1587. `n = (e d - 1) / M`. The *private key* is `d`, which Bob
  1588. keeps secret.
  1589. Examples
  1590. ========
  1591. >>> from sympy.crypto.crypto import kid_rsa_private_key
  1592. >>> a, b, A, B = 3, 4, 5, 6
  1593. >>> kid_rsa_private_key(a, b, A, B)
  1594. (369, 70)
  1595. """
  1596. M = a*b - 1
  1597. e = A*M + a
  1598. d = B*M + b
  1599. n = (e*d - 1)//M
  1600. return n, d
  1601. def encipher_kid_rsa(msg, key):
  1602. """
  1603. Here ``msg`` is the plaintext and ``key`` is the public key.
  1604. Examples
  1605. ========
  1606. >>> from sympy.crypto.crypto import (
  1607. ... encipher_kid_rsa, kid_rsa_public_key)
  1608. >>> msg = 200
  1609. >>> a, b, A, B = 3, 4, 5, 6
  1610. >>> key = kid_rsa_public_key(a, b, A, B)
  1611. >>> encipher_kid_rsa(msg, key)
  1612. 161
  1613. """
  1614. n, e = key
  1615. return (msg*e) % n
  1616. def decipher_kid_rsa(msg, key):
  1617. """
  1618. Here ``msg`` is the plaintext and ``key`` is the private key.
  1619. Examples
  1620. ========
  1621. >>> from sympy.crypto.crypto import (
  1622. ... kid_rsa_public_key, kid_rsa_private_key,
  1623. ... decipher_kid_rsa, encipher_kid_rsa)
  1624. >>> a, b, A, B = 3, 4, 5, 6
  1625. >>> d = kid_rsa_private_key(a, b, A, B)
  1626. >>> msg = 200
  1627. >>> pub = kid_rsa_public_key(a, b, A, B)
  1628. >>> pri = kid_rsa_private_key(a, b, A, B)
  1629. >>> ct = encipher_kid_rsa(msg, pub)
  1630. >>> decipher_kid_rsa(ct, pri)
  1631. 200
  1632. """
  1633. n, d = key
  1634. return (msg*d) % n
  1635. #################### Morse Code ######################################
  1636. morse_char = {
  1637. ".-": "A", "-...": "B",
  1638. "-.-.": "C", "-..": "D",
  1639. ".": "E", "..-.": "F",
  1640. "--.": "G", "....": "H",
  1641. "..": "I", ".---": "J",
  1642. "-.-": "K", ".-..": "L",
  1643. "--": "M", "-.": "N",
  1644. "---": "O", ".--.": "P",
  1645. "--.-": "Q", ".-.": "R",
  1646. "...": "S", "-": "T",
  1647. "..-": "U", "...-": "V",
  1648. ".--": "W", "-..-": "X",
  1649. "-.--": "Y", "--..": "Z",
  1650. "-----": "0", ".----": "1",
  1651. "..---": "2", "...--": "3",
  1652. "....-": "4", ".....": "5",
  1653. "-....": "6", "--...": "7",
  1654. "---..": "8", "----.": "9",
  1655. ".-.-.-": ".", "--..--": ",",
  1656. "---...": ":", "-.-.-.": ";",
  1657. "..--..": "?", "-....-": "-",
  1658. "..--.-": "_", "-.--.": "(",
  1659. "-.--.-": ")", ".----.": "'",
  1660. "-...-": "=", ".-.-.": "+",
  1661. "-..-.": "/", ".--.-.": "@",
  1662. "...-..-": "$", "-.-.--": "!"}
  1663. char_morse = {v: k for k, v in morse_char.items()}
  1664. def encode_morse(msg, sep='|', mapping=None):
  1665. """
  1666. Encodes a plaintext into popular Morse Code with letters
  1667. separated by ``sep`` and words by a double ``sep``.
  1668. Examples
  1669. ========
  1670. >>> from sympy.crypto.crypto import encode_morse
  1671. >>> msg = 'ATTACK RIGHT FLANK'
  1672. >>> encode_morse(msg)
  1673. '.-|-|-|.-|-.-.|-.-||.-.|..|--.|....|-||..-.|.-..|.-|-.|-.-'
  1674. References
  1675. ==========
  1676. .. [1] https://en.wikipedia.org/wiki/Morse_code
  1677. """
  1678. mapping = mapping or char_morse
  1679. assert sep not in mapping
  1680. word_sep = 2*sep
  1681. mapping[" "] = word_sep
  1682. suffix = msg and msg[-1] in whitespace
  1683. # normalize whitespace
  1684. msg = (' ' if word_sep else '').join(msg.split())
  1685. # omit unmapped chars
  1686. chars = set(''.join(msg.split()))
  1687. ok = set(mapping.keys())
  1688. msg = translate(msg, None, ''.join(chars - ok))
  1689. morsestring = []
  1690. words = msg.split()
  1691. for word in words:
  1692. morseword = []
  1693. for letter in word:
  1694. morseletter = mapping[letter]
  1695. morseword.append(morseletter)
  1696. word = sep.join(morseword)
  1697. morsestring.append(word)
  1698. return word_sep.join(morsestring) + (word_sep if suffix else '')
  1699. def decode_morse(msg, sep='|', mapping=None):
  1700. """
  1701. Decodes a Morse Code with letters separated by ``sep``
  1702. (default is '|') and words by `word_sep` (default is '||)
  1703. into plaintext.
  1704. Examples
  1705. ========
  1706. >>> from sympy.crypto.crypto import decode_morse
  1707. >>> mc = '--|---|...-|.||.|.-|...|-'
  1708. >>> decode_morse(mc)
  1709. 'MOVE EAST'
  1710. References
  1711. ==========
  1712. .. [1] https://en.wikipedia.org/wiki/Morse_code
  1713. """
  1714. mapping = mapping or morse_char
  1715. word_sep = 2*sep
  1716. characterstring = []
  1717. words = msg.strip(word_sep).split(word_sep)
  1718. for word in words:
  1719. letters = word.split(sep)
  1720. chars = [mapping[c] for c in letters]
  1721. word = ''.join(chars)
  1722. characterstring.append(word)
  1723. rv = " ".join(characterstring)
  1724. return rv
  1725. #################### LFSRs ##########################################
  1726. def lfsr_sequence(key, fill, n):
  1727. r"""
  1728. This function creates an LFSR sequence.
  1729. Parameters
  1730. ==========
  1731. key : list
  1732. A list of finite field elements, `[c_0, c_1, \ldots, c_k].`
  1733. fill : list
  1734. The list of the initial terms of the LFSR sequence,
  1735. `[x_0, x_1, \ldots, x_k].`
  1736. n
  1737. Number of terms of the sequence that the function returns.
  1738. Returns
  1739. =======
  1740. L
  1741. The LFSR sequence defined by
  1742. `x_{n+1} = c_k x_n + \ldots + c_0 x_{n-k}`, for
  1743. `n \leq k`.
  1744. Notes
  1745. =====
  1746. S. Golomb [G]_ gives a list of three statistical properties a
  1747. sequence of numbers `a = \{a_n\}_{n=1}^\infty`,
  1748. `a_n \in \{0,1\}`, should display to be considered
  1749. "random". Define the autocorrelation of `a` to be
  1750. .. math::
  1751. C(k) = C(k,a) = \lim_{N\rightarrow \infty} {1\over N}\sum_{n=1}^N (-1)^{a_n + a_{n+k}}.
  1752. In the case where `a` is periodic with period
  1753. `P` then this reduces to
  1754. .. math::
  1755. C(k) = {1\over P}\sum_{n=1}^P (-1)^{a_n + a_{n+k}}.
  1756. Assume `a` is periodic with period `P`.
  1757. - balance:
  1758. .. math::
  1759. \left|\sum_{n=1}^P(-1)^{a_n}\right| \leq 1.
  1760. - low autocorrelation:
  1761. .. math::
  1762. C(k) = \left\{ \begin{array}{cc} 1,& k = 0,\\ \epsilon, & k \ne 0. \end{array} \right.
  1763. (For sequences satisfying these first two properties, it is known
  1764. that `\epsilon = -1/P` must hold.)
  1765. - proportional runs property: In each period, half the runs have
  1766. length `1`, one-fourth have length `2`, etc.
  1767. Moreover, there are as many runs of `1`'s as there are of
  1768. `0`'s.
  1769. Examples
  1770. ========
  1771. >>> from sympy.crypto.crypto import lfsr_sequence
  1772. >>> from sympy.polys.domains import FF
  1773. >>> F = FF(2)
  1774. >>> fill = [F(1), F(1), F(0), F(1)]
  1775. >>> key = [F(1), F(0), F(0), F(1)]
  1776. >>> lfsr_sequence(key, fill, 10)
  1777. [1 mod 2, 1 mod 2, 0 mod 2, 1 mod 2, 0 mod 2,
  1778. 1 mod 2, 1 mod 2, 0 mod 2, 0 mod 2, 1 mod 2]
  1779. References
  1780. ==========
  1781. .. [G] Solomon Golomb, Shift register sequences, Aegean Park Press,
  1782. Laguna Hills, Ca, 1967
  1783. """
  1784. if not isinstance(key, list):
  1785. raise TypeError("key must be a list")
  1786. if not isinstance(fill, list):
  1787. raise TypeError("fill must be a list")
  1788. p = key[0].mod
  1789. F = FF(p)
  1790. s = fill
  1791. k = len(fill)
  1792. L = []
  1793. for i in range(n):
  1794. s0 = s[:]
  1795. L.append(s[0])
  1796. s = s[1:k]
  1797. x = sum([int(key[i]*s0[i]) for i in range(k)])
  1798. s.append(F(x))
  1799. return L # use [x.to_int() for x in L] for int version
  1800. def lfsr_autocorrelation(L, P, k):
  1801. """
  1802. This function computes the LFSR autocorrelation function.
  1803. Parameters
  1804. ==========
  1805. L
  1806. A periodic sequence of elements of `GF(2)`.
  1807. L must have length larger than P.
  1808. P
  1809. The period of L.
  1810. k : int
  1811. An integer `k` (`0 < k < P`).
  1812. Returns
  1813. =======
  1814. autocorrelation
  1815. The k-th value of the autocorrelation of the LFSR L.
  1816. Examples
  1817. ========
  1818. >>> from sympy.crypto.crypto import (
  1819. ... lfsr_sequence, lfsr_autocorrelation)
  1820. >>> from sympy.polys.domains import FF
  1821. >>> F = FF(2)
  1822. >>> fill = [F(1), F(1), F(0), F(1)]
  1823. >>> key = [F(1), F(0), F(0), F(1)]
  1824. >>> s = lfsr_sequence(key, fill, 20)
  1825. >>> lfsr_autocorrelation(s, 15, 7)
  1826. -1/15
  1827. >>> lfsr_autocorrelation(s, 15, 0)
  1828. 1
  1829. """
  1830. if not isinstance(L, list):
  1831. raise TypeError("L (=%s) must be a list" % L)
  1832. P = int(P)
  1833. k = int(k)
  1834. L0 = L[:P] # slices makes a copy
  1835. L1 = L0 + L0[:k]
  1836. L2 = [(-1)**(L1[i].to_int() + L1[i + k].to_int()) for i in range(P)]
  1837. tot = sum(L2)
  1838. return Rational(tot, P)
  1839. def lfsr_connection_polynomial(s):
  1840. """
  1841. This function computes the LFSR connection polynomial.
  1842. Parameters
  1843. ==========
  1844. s
  1845. A sequence of elements of even length, with entries in a finite
  1846. field.
  1847. Returns
  1848. =======
  1849. C(x)
  1850. The connection polynomial of a minimal LFSR yielding s.
  1851. This implements the algorithm in section 3 of J. L. Massey's
  1852. article [M]_.
  1853. Examples
  1854. ========
  1855. >>> from sympy.crypto.crypto import (
  1856. ... lfsr_sequence, lfsr_connection_polynomial)
  1857. >>> from sympy.polys.domains import FF
  1858. >>> F = FF(2)
  1859. >>> fill = [F(1), F(1), F(0), F(1)]
  1860. >>> key = [F(1), F(0), F(0), F(1)]
  1861. >>> s = lfsr_sequence(key, fill, 20)
  1862. >>> lfsr_connection_polynomial(s)
  1863. x**4 + x + 1
  1864. >>> fill = [F(1), F(0), F(0), F(1)]
  1865. >>> key = [F(1), F(1), F(0), F(1)]
  1866. >>> s = lfsr_sequence(key, fill, 20)
  1867. >>> lfsr_connection_polynomial(s)
  1868. x**3 + 1
  1869. >>> fill = [F(1), F(0), F(1)]
  1870. >>> key = [F(1), F(1), F(0)]
  1871. >>> s = lfsr_sequence(key, fill, 20)
  1872. >>> lfsr_connection_polynomial(s)
  1873. x**3 + x**2 + 1
  1874. >>> fill = [F(1), F(0), F(1)]
  1875. >>> key = [F(1), F(0), F(1)]
  1876. >>> s = lfsr_sequence(key, fill, 20)
  1877. >>> lfsr_connection_polynomial(s)
  1878. x**3 + x + 1
  1879. References
  1880. ==========
  1881. .. [M] James L. Massey, "Shift-Register Synthesis and BCH Decoding."
  1882. IEEE Trans. on Information Theory, vol. 15(1), pp. 122-127,
  1883. Jan 1969.
  1884. """
  1885. # Initialization:
  1886. p = s[0].mod
  1887. x = Symbol("x")
  1888. C = 1*x**0
  1889. B = 1*x**0
  1890. m = 1
  1891. b = 1*x**0
  1892. L = 0
  1893. N = 0
  1894. while N < len(s):
  1895. if L > 0:
  1896. dC = Poly(C).degree()
  1897. r = min(L + 1, dC + 1)
  1898. coeffsC = [C.subs(x, 0)] + [C.coeff(x**i)
  1899. for i in range(1, dC + 1)]
  1900. d = (s[N].to_int() + sum([coeffsC[i]*s[N - i].to_int()
  1901. for i in range(1, r)])) % p
  1902. if L == 0:
  1903. d = s[N].to_int()*x**0
  1904. if d == 0:
  1905. m += 1
  1906. N += 1
  1907. if d > 0:
  1908. if 2*L > N:
  1909. C = (C - d*((b**(p - 2)) % p)*x**m*B).expand()
  1910. m += 1
  1911. N += 1
  1912. else:
  1913. T = C
  1914. C = (C - d*((b**(p - 2)) % p)*x**m*B).expand()
  1915. L = N + 1 - L
  1916. m = 1
  1917. b = d
  1918. B = T
  1919. N += 1
  1920. dC = Poly(C).degree()
  1921. coeffsC = [C.subs(x, 0)] + [C.coeff(x**i) for i in range(1, dC + 1)]
  1922. return sum([coeffsC[i] % p*x**i for i in range(dC + 1)
  1923. if coeffsC[i] is not None])
  1924. #################### ElGamal #############################
  1925. def elgamal_private_key(digit=10, seed=None):
  1926. r"""
  1927. Return three number tuple as private key.
  1928. Explanation
  1929. ===========
  1930. Elgamal encryption is based on the mathmatical problem
  1931. called the Discrete Logarithm Problem (DLP). For example,
  1932. `a^{b} \equiv c \pmod p`
  1933. In general, if ``a`` and ``b`` are known, ``ct`` is easily
  1934. calculated. If ``b`` is unknown, it is hard to use
  1935. ``a`` and ``ct`` to get ``b``.
  1936. Parameters
  1937. ==========
  1938. digit : int
  1939. Minimum number of binary digits for key.
  1940. Returns
  1941. =======
  1942. tuple : (p, r, d)
  1943. p = prime number.
  1944. r = primitive root.
  1945. d = random number.
  1946. Notes
  1947. =====
  1948. For testing purposes, the ``seed`` parameter may be set to control
  1949. the output of this routine. See sympy.core.random._randrange.
  1950. Examples
  1951. ========
  1952. >>> from sympy.crypto.crypto import elgamal_private_key
  1953. >>> from sympy.ntheory import is_primitive_root, isprime
  1954. >>> a, b, _ = elgamal_private_key()
  1955. >>> isprime(a)
  1956. True
  1957. >>> is_primitive_root(b, a)
  1958. True
  1959. """
  1960. randrange = _randrange(seed)
  1961. p = nextprime(2**digit)
  1962. return p, primitive_root(p), randrange(2, p)
  1963. def elgamal_public_key(key):
  1964. r"""
  1965. Return three number tuple as public key.
  1966. Parameters
  1967. ==========
  1968. key : (p, r, e)
  1969. Tuple generated by ``elgamal_private_key``.
  1970. Returns
  1971. =======
  1972. tuple : (p, r, e)
  1973. `e = r**d \bmod p`
  1974. `d` is a random number in private key.
  1975. Examples
  1976. ========
  1977. >>> from sympy.crypto.crypto import elgamal_public_key
  1978. >>> elgamal_public_key((1031, 14, 636))
  1979. (1031, 14, 212)
  1980. """
  1981. p, r, e = key
  1982. return p, r, pow(r, e, p)
  1983. def encipher_elgamal(i, key, seed=None):
  1984. r"""
  1985. Encrypt message with public key.
  1986. Explanation
  1987. ===========
  1988. ``i`` is a plaintext message expressed as an integer.
  1989. ``key`` is public key (p, r, e). In order to encrypt
  1990. a message, a random number ``a`` in ``range(2, p)``
  1991. is generated and the encryped message is returned as
  1992. `c_{1}` and `c_{2}` where:
  1993. `c_{1} \equiv r^{a} \pmod p`
  1994. `c_{2} \equiv m e^{a} \pmod p`
  1995. Parameters
  1996. ==========
  1997. msg
  1998. int of encoded message.
  1999. key
  2000. Public key.
  2001. Returns
  2002. =======
  2003. tuple : (c1, c2)
  2004. Encipher into two number.
  2005. Notes
  2006. =====
  2007. For testing purposes, the ``seed`` parameter may be set to control
  2008. the output of this routine. See sympy.core.random._randrange.
  2009. Examples
  2010. ========
  2011. >>> from sympy.crypto.crypto import encipher_elgamal, elgamal_private_key, elgamal_public_key
  2012. >>> pri = elgamal_private_key(5, seed=[3]); pri
  2013. (37, 2, 3)
  2014. >>> pub = elgamal_public_key(pri); pub
  2015. (37, 2, 8)
  2016. >>> msg = 36
  2017. >>> encipher_elgamal(msg, pub, seed=[3])
  2018. (8, 6)
  2019. """
  2020. p, r, e = key
  2021. if i < 0 or i >= p:
  2022. raise ValueError(
  2023. 'Message (%s) should be in range(%s)' % (i, p))
  2024. randrange = _randrange(seed)
  2025. a = randrange(2, p)
  2026. return pow(r, a, p), i*pow(e, a, p) % p
  2027. def decipher_elgamal(msg, key):
  2028. r"""
  2029. Decrypt message with private key.
  2030. `msg = (c_{1}, c_{2})`
  2031. `key = (p, r, d)`
  2032. According to extended Eucliden theorem,
  2033. `u c_{1}^{d} + p n = 1`
  2034. `u \equiv 1/{{c_{1}}^d} \pmod p`
  2035. `u c_{2} \equiv \frac{1}{c_{1}^d} c_{2} \equiv \frac{1}{r^{ad}} c_{2} \pmod p`
  2036. `\frac{1}{r^{ad}} m e^a \equiv \frac{1}{r^{ad}} m {r^{d a}} \equiv m \pmod p`
  2037. Examples
  2038. ========
  2039. >>> from sympy.crypto.crypto import decipher_elgamal
  2040. >>> from sympy.crypto.crypto import encipher_elgamal
  2041. >>> from sympy.crypto.crypto import elgamal_private_key
  2042. >>> from sympy.crypto.crypto import elgamal_public_key
  2043. >>> pri = elgamal_private_key(5, seed=[3])
  2044. >>> pub = elgamal_public_key(pri); pub
  2045. (37, 2, 8)
  2046. >>> msg = 17
  2047. >>> decipher_elgamal(encipher_elgamal(msg, pub), pri) == msg
  2048. True
  2049. """
  2050. p, _, d = key
  2051. c1, c2 = msg
  2052. u = igcdex(c1**d, p)[0]
  2053. return u * c2 % p
  2054. ################ Diffie-Hellman Key Exchange #########################
  2055. def dh_private_key(digit=10, seed=None):
  2056. r"""
  2057. Return three integer tuple as private key.
  2058. Explanation
  2059. ===========
  2060. Diffie-Hellman key exchange is based on the mathematical problem
  2061. called the Discrete Logarithm Problem (see ElGamal).
  2062. Diffie-Hellman key exchange is divided into the following steps:
  2063. * Alice and Bob agree on a base that consist of a prime ``p``
  2064. and a primitive root of ``p`` called ``g``
  2065. * Alice choses a number ``a`` and Bob choses a number ``b`` where
  2066. ``a`` and ``b`` are random numbers in range `[2, p)`. These are
  2067. their private keys.
  2068. * Alice then publicly sends Bob `g^{a} \pmod p` while Bob sends
  2069. Alice `g^{b} \pmod p`
  2070. * They both raise the received value to their secretly chosen
  2071. number (``a`` or ``b``) and now have both as their shared key
  2072. `g^{ab} \pmod p`
  2073. Parameters
  2074. ==========
  2075. digit
  2076. Minimum number of binary digits required in key.
  2077. Returns
  2078. =======
  2079. tuple : (p, g, a)
  2080. p = prime number.
  2081. g = primitive root of p.
  2082. a = random number from 2 through p - 1.
  2083. Notes
  2084. =====
  2085. For testing purposes, the ``seed`` parameter may be set to control
  2086. the output of this routine. See sympy.core.random._randrange.
  2087. Examples
  2088. ========
  2089. >>> from sympy.crypto.crypto import dh_private_key
  2090. >>> from sympy.ntheory import isprime, is_primitive_root
  2091. >>> p, g, _ = dh_private_key()
  2092. >>> isprime(p)
  2093. True
  2094. >>> is_primitive_root(g, p)
  2095. True
  2096. >>> p, g, _ = dh_private_key(5)
  2097. >>> isprime(p)
  2098. True
  2099. >>> is_primitive_root(g, p)
  2100. True
  2101. """
  2102. p = nextprime(2**digit)
  2103. g = primitive_root(p)
  2104. randrange = _randrange(seed)
  2105. a = randrange(2, p)
  2106. return p, g, a
  2107. def dh_public_key(key):
  2108. r"""
  2109. Return three number tuple as public key.
  2110. This is the tuple that Alice sends to Bob.
  2111. Parameters
  2112. ==========
  2113. key : (p, g, a)
  2114. A tuple generated by ``dh_private_key``.
  2115. Returns
  2116. =======
  2117. tuple : int, int, int
  2118. A tuple of `(p, g, g^a \mod p)` with `p`, `g` and `a` given as
  2119. parameters.s
  2120. Examples
  2121. ========
  2122. >>> from sympy.crypto.crypto import dh_private_key, dh_public_key
  2123. >>> p, g, a = dh_private_key();
  2124. >>> _p, _g, x = dh_public_key((p, g, a))
  2125. >>> p == _p and g == _g
  2126. True
  2127. >>> x == pow(g, a, p)
  2128. True
  2129. """
  2130. p, g, a = key
  2131. return p, g, pow(g, a, p)
  2132. def dh_shared_key(key, b):
  2133. """
  2134. Return an integer that is the shared key.
  2135. This is what Bob and Alice can both calculate using the public
  2136. keys they received from each other and their private keys.
  2137. Parameters
  2138. ==========
  2139. key : (p, g, x)
  2140. Tuple `(p, g, x)` generated by ``dh_public_key``.
  2141. b
  2142. Random number in the range of `2` to `p - 1`
  2143. (Chosen by second key exchange member (Bob)).
  2144. Returns
  2145. =======
  2146. int
  2147. A shared key.
  2148. Examples
  2149. ========
  2150. >>> from sympy.crypto.crypto import (
  2151. ... dh_private_key, dh_public_key, dh_shared_key)
  2152. >>> prk = dh_private_key();
  2153. >>> p, g, x = dh_public_key(prk);
  2154. >>> sk = dh_shared_key((p, g, x), 1000)
  2155. >>> sk == pow(x, 1000, p)
  2156. True
  2157. """
  2158. p, _, x = key
  2159. if 1 >= b or b >= p:
  2160. raise ValueError(filldedent('''
  2161. Value of b should be greater 1 and less
  2162. than prime %s.''' % p))
  2163. return pow(x, b, p)
  2164. ################ Goldwasser-Micali Encryption #########################
  2165. def _legendre(a, p):
  2166. """
  2167. Returns the legendre symbol of a and p
  2168. assuming that p is a prime.
  2169. i.e. 1 if a is a quadratic residue mod p
  2170. -1 if a is not a quadratic residue mod p
  2171. 0 if a is divisible by p
  2172. Parameters
  2173. ==========
  2174. a : int
  2175. The number to test.
  2176. p : prime
  2177. The prime to test ``a`` against.
  2178. Returns
  2179. =======
  2180. int
  2181. Legendre symbol (a / p).
  2182. """
  2183. sig = pow(a, (p - 1)//2, p)
  2184. if sig == 1:
  2185. return 1
  2186. elif sig == 0:
  2187. return 0
  2188. else:
  2189. return -1
  2190. def _random_coprime_stream(n, seed=None):
  2191. randrange = _randrange(seed)
  2192. while True:
  2193. y = randrange(n)
  2194. if gcd(y, n) == 1:
  2195. yield y
  2196. def gm_private_key(p, q, a=None):
  2197. r"""
  2198. Check if ``p`` and ``q`` can be used as private keys for
  2199. the Goldwasser-Micali encryption. The method works
  2200. roughly as follows.
  2201. Explanation
  2202. ===========
  2203. #. Pick two large primes $p$ and $q$.
  2204. #. Call their product $N$.
  2205. #. Given a message as an integer $i$, write $i$ in its bit representation $b_0, \dots, b_n$.
  2206. #. For each $k$,
  2207. if $b_k = 0$:
  2208. let $a_k$ be a random square
  2209. (quadratic residue) modulo $p q$
  2210. such that ``jacobi_symbol(a, p*q) = 1``
  2211. if $b_k = 1$:
  2212. let $a_k$ be a random non-square
  2213. (non-quadratic residue) modulo $p q$
  2214. such that ``jacobi_symbol(a, p*q) = 1``
  2215. returns $\left[a_1, a_2, \dots\right]$
  2216. $b_k$ can be recovered by checking whether or not
  2217. $a_k$ is a residue. And from the $b_k$'s, the message
  2218. can be reconstructed.
  2219. The idea is that, while ``jacobi_symbol(a, p*q)``
  2220. can be easily computed (and when it is equal to $-1$ will
  2221. tell you that $a$ is not a square mod $p q$), quadratic
  2222. residuosity modulo a composite number is hard to compute
  2223. without knowing its factorization.
  2224. Moreover, approximately half the numbers coprime to $p q$ have
  2225. :func:`~.jacobi_symbol` equal to $1$ . And among those, approximately half
  2226. are residues and approximately half are not. This maximizes the
  2227. entropy of the code.
  2228. Parameters
  2229. ==========
  2230. p, q, a
  2231. Initialization variables.
  2232. Returns
  2233. =======
  2234. tuple : (p, q)
  2235. The input value ``p`` and ``q``.
  2236. Raises
  2237. ======
  2238. ValueError
  2239. If ``p`` and ``q`` are not distinct odd primes.
  2240. """
  2241. if p == q:
  2242. raise ValueError("expected distinct primes, "
  2243. "got two copies of %i" % p)
  2244. elif not isprime(p) or not isprime(q):
  2245. raise ValueError("first two arguments must be prime, "
  2246. "got %i of %i" % (p, q))
  2247. elif p == 2 or q == 2:
  2248. raise ValueError("first two arguments must not be even, "
  2249. "got %i of %i" % (p, q))
  2250. return p, q
  2251. def gm_public_key(p, q, a=None, seed=None):
  2252. """
  2253. Compute public keys for ``p`` and ``q``.
  2254. Note that in Goldwasser-Micali Encryption,
  2255. public keys are randomly selected.
  2256. Parameters
  2257. ==========
  2258. p, q, a : int, int, int
  2259. Initialization variables.
  2260. Returns
  2261. =======
  2262. tuple : (a, N)
  2263. ``a`` is the input ``a`` if it is not ``None`` otherwise
  2264. some random integer coprime to ``p`` and ``q``.
  2265. ``N`` is the product of ``p`` and ``q``.
  2266. """
  2267. p, q = gm_private_key(p, q)
  2268. N = p * q
  2269. if a is None:
  2270. randrange = _randrange(seed)
  2271. while True:
  2272. a = randrange(N)
  2273. if _legendre(a, p) == _legendre(a, q) == -1:
  2274. break
  2275. else:
  2276. if _legendre(a, p) != -1 or _legendre(a, q) != -1:
  2277. return False
  2278. return (a, N)
  2279. def encipher_gm(i, key, seed=None):
  2280. """
  2281. Encrypt integer 'i' using public_key 'key'
  2282. Note that gm uses random encryption.
  2283. Parameters
  2284. ==========
  2285. i : int
  2286. The message to encrypt.
  2287. key : (a, N)
  2288. The public key.
  2289. Returns
  2290. =======
  2291. list : list of int
  2292. The randomized encrypted message.
  2293. """
  2294. if i < 0:
  2295. raise ValueError(
  2296. "message must be a non-negative "
  2297. "integer: got %d instead" % i)
  2298. a, N = key
  2299. bits = []
  2300. while i > 0:
  2301. bits.append(i % 2)
  2302. i //= 2
  2303. gen = _random_coprime_stream(N, seed)
  2304. rev = reversed(bits)
  2305. encode = lambda b: next(gen)**2*pow(a, b) % N
  2306. return [ encode(b) for b in rev ]
  2307. def decipher_gm(message, key):
  2308. """
  2309. Decrypt message 'message' using public_key 'key'.
  2310. Parameters
  2311. ==========
  2312. message : list of int
  2313. The randomized encrypted message.
  2314. key : (p, q)
  2315. The private key.
  2316. Returns
  2317. =======
  2318. int
  2319. The encrypted message.
  2320. """
  2321. p, q = key
  2322. res = lambda m, p: _legendre(m, p) > 0
  2323. bits = [res(m, p) * res(m, q) for m in message]
  2324. m = 0
  2325. for b in bits:
  2326. m <<= 1
  2327. m += not b
  2328. return m
  2329. ########### RailFence Cipher #############
  2330. def encipher_railfence(message,rails):
  2331. """
  2332. Performs Railfence Encryption on plaintext and returns ciphertext
  2333. Examples
  2334. ========
  2335. >>> from sympy.crypto.crypto import encipher_railfence
  2336. >>> message = "hello world"
  2337. >>> encipher_railfence(message,3)
  2338. 'horel ollwd'
  2339. Parameters
  2340. ==========
  2341. message : string, the message to encrypt.
  2342. rails : int, the number of rails.
  2343. Returns
  2344. =======
  2345. The Encrypted string message.
  2346. References
  2347. ==========
  2348. .. [1] https://en.wikipedia.org/wiki/Rail_fence_cipher
  2349. """
  2350. r = list(range(rails))
  2351. p = cycle(r + r[-2:0:-1])
  2352. return ''.join(sorted(message, key=lambda i: next(p)))
  2353. def decipher_railfence(ciphertext,rails):
  2354. """
  2355. Decrypt the message using the given rails
  2356. Examples
  2357. ========
  2358. >>> from sympy.crypto.crypto import decipher_railfence
  2359. >>> decipher_railfence("horel ollwd",3)
  2360. 'hello world'
  2361. Parameters
  2362. ==========
  2363. message : string, the message to encrypt.
  2364. rails : int, the number of rails.
  2365. Returns
  2366. =======
  2367. The Decrypted string message.
  2368. """
  2369. r = list(range(rails))
  2370. p = cycle(r + r[-2:0:-1])
  2371. idx = sorted(range(len(ciphertext)), key=lambda i: next(p))
  2372. res = [''] * len(ciphertext)
  2373. for i, c in zip(idx, ciphertext):
  2374. res[i] = c
  2375. return ''.join(res)
  2376. ################ Blum-Goldwasser cryptosystem #########################
  2377. def bg_private_key(p, q):
  2378. """
  2379. Check if p and q can be used as private keys for
  2380. the Blum-Goldwasser cryptosystem.
  2381. Explanation
  2382. ===========
  2383. The three necessary checks for p and q to pass
  2384. so that they can be used as private keys:
  2385. 1. p and q must both be prime
  2386. 2. p and q must be distinct
  2387. 3. p and q must be congruent to 3 mod 4
  2388. Parameters
  2389. ==========
  2390. p, q
  2391. The keys to be checked.
  2392. Returns
  2393. =======
  2394. p, q
  2395. Input values.
  2396. Raises
  2397. ======
  2398. ValueError
  2399. If p and q do not pass the above conditions.
  2400. """
  2401. if not isprime(p) or not isprime(q):
  2402. raise ValueError("the two arguments must be prime, "
  2403. "got %i and %i" %(p, q))
  2404. elif p == q:
  2405. raise ValueError("the two arguments must be distinct, "
  2406. "got two copies of %i. " %p)
  2407. elif (p - 3) % 4 != 0 or (q - 3) % 4 != 0:
  2408. raise ValueError("the two arguments must be congruent to 3 mod 4, "
  2409. "got %i and %i" %(p, q))
  2410. return p, q
  2411. def bg_public_key(p, q):
  2412. """
  2413. Calculates public keys from private keys.
  2414. Explanation
  2415. ===========
  2416. The function first checks the validity of
  2417. private keys passed as arguments and
  2418. then returns their product.
  2419. Parameters
  2420. ==========
  2421. p, q
  2422. The private keys.
  2423. Returns
  2424. =======
  2425. N
  2426. The public key.
  2427. """
  2428. p, q = bg_private_key(p, q)
  2429. N = p * q
  2430. return N
  2431. def encipher_bg(i, key, seed=None):
  2432. """
  2433. Encrypts the message using public key and seed.
  2434. Explanation
  2435. ===========
  2436. ALGORITHM:
  2437. 1. Encodes i as a string of L bits, m.
  2438. 2. Select a random element r, where 1 < r < key, and computes
  2439. x = r^2 mod key.
  2440. 3. Use BBS pseudo-random number generator to generate L random bits, b,
  2441. using the initial seed as x.
  2442. 4. Encrypted message, c_i = m_i XOR b_i, 1 <= i <= L.
  2443. 5. x_L = x^(2^L) mod key.
  2444. 6. Return (c, x_L)
  2445. Parameters
  2446. ==========
  2447. i
  2448. Message, a non-negative integer
  2449. key
  2450. The public key
  2451. Returns
  2452. =======
  2453. Tuple
  2454. (encrypted_message, x_L)
  2455. Raises
  2456. ======
  2457. ValueError
  2458. If i is negative.
  2459. """
  2460. if i < 0:
  2461. raise ValueError(
  2462. "message must be a non-negative "
  2463. "integer: got %d instead" % i)
  2464. enc_msg = []
  2465. while i > 0:
  2466. enc_msg.append(i % 2)
  2467. i //= 2
  2468. enc_msg.reverse()
  2469. L = len(enc_msg)
  2470. r = _randint(seed)(2, key - 1)
  2471. x = r**2 % key
  2472. x_L = pow(int(x), int(2**L), int(key))
  2473. rand_bits = []
  2474. for _ in range(L):
  2475. rand_bits.append(x % 2)
  2476. x = x**2 % key
  2477. encrypt_msg = [m ^ b for (m, b) in zip(enc_msg, rand_bits)]
  2478. return (encrypt_msg, x_L)
  2479. def decipher_bg(message, key):
  2480. """
  2481. Decrypts the message using private keys.
  2482. Explanation
  2483. ===========
  2484. ALGORITHM:
  2485. 1. Let, c be the encrypted message, y the second number received,
  2486. and p and q be the private keys.
  2487. 2. Compute, r_p = y^((p+1)/4 ^ L) mod p and
  2488. r_q = y^((q+1)/4 ^ L) mod q.
  2489. 3. Compute x_0 = (q(q^-1 mod p)r_p + p(p^-1 mod q)r_q) mod N.
  2490. 4. From, recompute the bits using the BBS generator, as in the
  2491. encryption algorithm.
  2492. 5. Compute original message by XORing c and b.
  2493. Parameters
  2494. ==========
  2495. message
  2496. Tuple of encrypted message and a non-negative integer.
  2497. key
  2498. Tuple of private keys.
  2499. Returns
  2500. =======
  2501. orig_msg
  2502. The original message
  2503. """
  2504. p, q = key
  2505. encrypt_msg, y = message
  2506. public_key = p * q
  2507. L = len(encrypt_msg)
  2508. p_t = ((p + 1)/4)**L
  2509. q_t = ((q + 1)/4)**L
  2510. r_p = pow(int(y), int(p_t), int(p))
  2511. r_q = pow(int(y), int(q_t), int(q))
  2512. x = (q * mod_inverse(q, p) * r_p + p * mod_inverse(p, q) * r_q) % public_key
  2513. orig_bits = []
  2514. for _ in range(L):
  2515. orig_bits.append(x % 2)
  2516. x = x**2 % public_key
  2517. orig_msg = 0
  2518. for (m, b) in zip(encrypt_msg, orig_bits):
  2519. orig_msg = orig_msg * 2
  2520. orig_msg += (m ^ b)
  2521. return orig_msg