密码学#

警告

本单元仅用于教育目的。不要将此模块中的函数用于实际的加密应用程序。如果您希望加密真实数据,我们建议使用类似 cryptography 模块。

加密是隐藏消息的过程,而密码就是一种方法。本模块包括块密码和流密码:

  • 移位法

  • 仿射密码

  • 替代密码

  • 维格纳密码

  • 希尔密码

  • 双歧密码

  • RSA

  • 小子RSA

  • 线性反馈移位寄存器(用于流密码)

  • ElGamal加密

在一个 替代密码 根据常规系统,明文的“单位”(不一定是单个字符)被密文替换。

A 换位密码 是一种加密方法,通过这种方法,明文的“单元”所占据的位置被明文的排列所代替。也就是说,通过在字符位置上使用双射函数来改变单元的顺序来执行加密。

A 单字母密码 对整个消息使用固定替换,而 多字母密码 在消息的不同时间使用多个替换。

sympy.crypto.crypto.AZ(s=None)[源代码]#

返回的字母 s 大写。如果传递了多个字符串,则将处理每个字符串并返回大写字符串列表。

实例

>>> from sympy.crypto.crypto import AZ
>>> AZ('Hello, world!')
'HELLOWORLD'
>>> AZ('Hello, world!'.split())
['HELLO', 'WORLD']
sympy.crypto.crypto.padded_key(key, symbols)[源代码]#

返回 symbols 与那些 key 先出现。如果A)中存在重复字符,则引发ValueError symbols 或b)有字符 key 不在里面 symbols .

实例

>>> from sympy.crypto.crypto import padded_key
>>> padded_key('PUPPY', 'OPQRSTUVWXY')
'PUYOQRSTVWX'
>>> padded_key('RSA', 'ARTIST')
Traceback (most recent call last):
...
ValueError: duplicate characters in symbols: T
sympy.crypto.crypto.check_and_join(phrase, symbols=None, filter=None)[源代码]#

连接字符 phrase 如果 symbols 如果中有任何字符,则引发错误 phrase 不在 symbols .

参数:

phrase

要作为字符串返回的字符串或字符串列表。

symbols

中允许的字符数 phrase .

如果 symbolsNone ,不执行检查。

实例

>>> from sympy.crypto.crypto import check_and_join
>>> check_and_join('a phrase')
'a phrase'
>>> check_and_join('a phrase'.upper().split())
'APHRASE'
>>> check_and_join('a phrase!'.upper().split(), 'ARE', filter=True)
'ARAE'
>>> check_and_join('a phrase!'.upper().split(), 'ARE')
Traceback (most recent call last):
...
ValueError: characters in phrase but not symbols: "!HPS"
sympy.crypto.crypto.cycle_list(k, n)[源代码]#

返回列表的元素 range(n) 左移 k (所以列表从 k (国防部 n

实例

>>> from sympy.crypto.crypto import cycle_list
>>> cycle_list(3, 10)
[3, 4, 5, 6, 7, 8, 9, 0, 1, 2]
sympy.crypto.crypto.encipher_shift(msg, key, symbols=None)[源代码]#

对明文消息执行移位密码加密,并返回密文。

参数:

key :内景

秘密钥匙。

msg :结构

大写字母的明文。

返回:

STR

大写字母的密文。

实例

>>> from sympy.crypto.crypto import encipher_shift, decipher_shift
>>> msg = "GONAVYBEATARMY"
>>> ct = encipher_shift(msg, 1); ct
'HPOBWZCFBUBSNZ'

要破译移位的文本,请更改键的符号:

>>> encipher_shift(ct, -1)
'GONAVYBEATARMY'

还有一个方便的功能,可以用原来的钥匙进行此操作:

>>> decipher_shift(ct, 1)
'GONAVYBEATARMY'

笔记

算法:

步骤:
  1. 从0,…,N开始给字母表中的字母编号

  2. 从字符串计算 msg 一览表 L1 对应的整数。

  3. 从列表中计算 L1 新名单 L2 ,通过添加 (k mod 26) 到中的每个元素 L1 .

  4. 从列表中计算 L2 一根绳子 ct 对应的字母。

移位密码也被称为凯撒密码,是在朱利叶斯·凯撒(Julius Caesar)之后,根据苏托尼乌斯(Suetonius)的说法,他用三次移位来保护具有军事意义的信息。据报道,凯撒的侄子奥古斯都使用了类似的密码,但右移1。

工具书类

sympy.crypto.crypto.decipher_shift(msg, key, symbols=None)[源代码]#

通过移动的字符返回文本 msg 在左边 key .

实例

>>> from sympy.crypto.crypto import encipher_shift, decipher_shift
>>> msg = "GONAVYBEATARMY"
>>> ct = encipher_shift(msg, 1); ct
'HPOBWZCFBUBSNZ'

要破译移位的文本,请更改键的符号:

>>> encipher_shift(ct, -1)
'GONAVYBEATARMY'

或将此功能与原始键一起使用:

>>> decipher_shift(ct, 1)
'GONAVYBEATARMY'
sympy.crypto.crypto.encipher_rot13(msg, symbols=None)[源代码]#

对给定的明文执行ROT13加密 msg .

解释

ROT13是一种替代密码,它将明文信息中的每个字母替换为英语字母表中距离它最远的字母。

相当于,它只是一个Caeser(移位)密码,移位键为13(字母表的中间点)。

工具书类

sympy.crypto.crypto.decipher_rot13(msg, symbols=None)[源代码]#

对给定的明文执行ROT13解密 msg .

解释

decipher_rot13 等于 encipher_rot13 两者兼而有之 decipher_shift 钥匙是13和 encipher_shift 键为13的键将返回相同的结果。尽管如此, decipher_rot13 尽管如此,为了保持一致性,这里已经明确定义了。

实例

>>> from sympy.crypto.crypto import encipher_rot13, decipher_rot13
>>> msg = 'GONAVYBEATARMY'
>>> ciphertext = encipher_rot13(msg);ciphertext
'TBANILORNGNEZL'
>>> decipher_rot13(ciphertext)
'GONAVYBEATARMY'
>>> encipher_rot13(msg) == decipher_rot13(msg)
True
>>> msg == decipher_rot13(ciphertext)
True
sympy.crypto.crypto.encipher_affine(msg, key, symbols=None, _inverse=False)[源代码]#

对明文执行仿射密码加密 msg ,并返回密文。

参数:

msg :结构

出现在中的字符 symbols .

a, b :int,int

一对整数,带 gcd(a, N) = 1 (密钥)。

symbols

字符串(默认值=大写字母)。

当没有符号的时候, msg 转换为大写字母,并且忽略所有其他字符。

返回:

计算机断层扫描

字符串(密文消息)

解释

加密是基于地图的 \(x \rightarrow ax+b\) (国防部 \(N\) 何处 N 是字母表中的字符数。解密是基于地图 \(x \rightarrow cx+d\) (国防部 \(N\) 在哪里 \(c = a^{{-1}}\) (国防部 \(N\)\(d = -a^{{-1}}b\) (国防部 \(N\) ). 特别是,为了使映射是可逆的,我们需要 \(\mathrm{{gcd}}(a, N) = 1\) 如果这不是真的,就会产生一个错误。

笔记

算法:

步骤:
  1. 从0,…,N开始给字母表中的字母编号

  2. 从字符串计算 msg 一览表 L1 对应的整数。

  3. 从列表中计算 L1 新名单 L2 ,通过替换 x 通过 a*x + b (mod N) ,对于每个元素 x 在里面 L1 .

  4. 从列表中计算 L2 一根绳子 ct 对应的字母。

这是移位密码的一个简单概括,它增加了需要2个字符进行解密才能恢复密钥的复杂性。

工具书类

sympy.crypto.crypto.decipher_affine(msg, key, symbols=None)[源代码]#

返回由映射生成的已破译文本, \(x \rightarrow ax+b\) (国防部 \(N\) 在哪里 N 是字母表中的字符数。通过使用新密钥进行往复处理来进行解密: \(x \rightarrow cx+d\) (国防部 \(N\) 在哪里 \(c = a^{{-1}}\) (国防部 \(N\)\(d = -a^{{-1}}b\) (国防部 \(N\)

实例

>>> from sympy.crypto.crypto import encipher_affine, decipher_affine
>>> msg = "GO NAVY BEAT ARMY"
>>> key = (3, 1)
>>> encipher_affine(msg, key)
'TROBMVENBGBALV'
>>> decipher_affine(_, key)
'GONAVYBEATARMY'
sympy.crypto.crypto.encipher_atbash(msg, symbols=None)[源代码]#

加密给定的 msg 并返回它。

解释

Atbash是一种替代密码,最初用于加密希伯来语字母表。Atbash的工作原理是将每个字母表映射到它的反向/对应项(即a将映射到z,b映射到y等)

Atbash在功能上等价于仿射密码 a = 25b = 25

sympy.crypto.crypto.decipher_atbash(msg, symbols=None)[源代码]#

破译给定的 msg 使用Atbash密码并返回它。

解释

decipher_atbash 在功能上等同于 encipher_atbash . 但是,它仍然作为一个单独的功能添加,以保持一致性。

实例

>>> from sympy.crypto.crypto import encipher_atbash, decipher_atbash
>>> msg = 'GONAVYBEATARMY'
>>> encipher_atbash(msg)
'TLMZEBYVZGZINB'
>>> decipher_atbash(msg)
'TLMZEBYVZGZINB'
>>> encipher_atbash(msg) == decipher_atbash(msg)
True
>>> msg == encipher_atbash(encipher_atbash(msg))
True

工具书类

sympy.crypto.crypto.encipher_substitution(msg, old, new=None)[源代码]#

返回通过替换中出现的每个字符而获得的密文 old 对应的字符 new .如果 old 是一个映射,则忽略new并由定义替换 old 被使用。

解释

这是一个比仿射密码更通用的密码,因为密钥只能通过确定每个符号的映射来恢复。虽然在实践中,一旦识别出一些符号,其他字符的映射就可以很快猜到了。

实例

>>> from sympy.crypto.crypto import encipher_substitution, AZ
>>> old = 'OEYAG'
>>> new = '034^6'
>>> msg = AZ("go navy! beat army!")
>>> ct = encipher_substitution(msg, old, new); ct
'60N^V4B3^T^RM4'

要解密替换,请反转最后两个参数:

>>> encipher_substitution(ct, new, old)
'GONAVYBEATARMY'

在特殊情况下 oldnew 是顺序2的排列(代表字符的换位),它们的顺序无关紧要:

>>> old = 'NAVY'
>>> new = 'ANYV'
>>> encipher = lambda x: encipher_substitution(x, old, new)
>>> encipher('NAVY')
'ANYV'
>>> encipher(_)
'NAVY'

一般来说,替换密码是一种根据常规系统用密文替换明文的“单元”(不一定是单个字符)的方法。

>>> ords = dict(zip('abc', ['\\%i' % ord(i) for i in 'abc']))
>>> print(encipher_substitution('abc', ords))
\97\98\99

工具书类

sympy.crypto.crypto.encipher_vigenere(msg, key, symbols=None)[源代码]#

对明文执行Vigenere密码加密 msg ,并返回密文。

实例

>>> from sympy.crypto.crypto import encipher_vigenere, AZ
>>> key = "encrypt"
>>> msg = "meet me on monday"
>>> encipher_vigenere(msg, key)
'QRGKKTHRZQEBPR'

Section 1 of the Kryptos sculpture at the CIA headquarters uses this cipher and also changes the order of the alphabet [R158]. Here is the first line of that section of the sculpture:

>>> from sympy.crypto.crypto import decipher_vigenere, padded_key
>>> alp = padded_key('KRYPTOS', AZ())
>>> key = 'PALIMPSEST'
>>> msg = 'EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJ'
>>> decipher_vigenere(msg, key, alp)
'BETWEENSUBTLESHADINGANDTHEABSENC'

解释

维格纳密码是以16世纪外交官和密码学家布莱斯·德·维格纳(Blaise de Vigenere)的名字命名的,这是一次历史事故。维格纳实际上发明了一种不同的更复杂的密码。所谓的 维吉尼亚加密法 实际上是乔万·巴蒂斯塔·贝拉索在1553年发明的。

This cipher was used in the 1800's, for example, during the American Civil War. The Confederacy used a brass cipher disk to implement the Vigenere cipher (now on display in the NSA Museum in Fort Meade) [R157].

维格纳密码是移位密码的推广。而移位密码将每个字母移位相同的量(这个量是移位密码的密钥),而Vigenere密码则将一个字母按密钥确定的移位量(即只有发送者和接收者知道的单词或短语)。

例如,如果密钥是单个字母,例如“C”,那么所谓的Vigenere密码实际上是一个移位的移位密码 \(2\) (因为“C”是字母表中的第二个字母,如果您从 \(0\) ). 如果密钥是一个有两个字母的单词,比如“CA”,那么所谓的Vigenere密码会将字母在偶数位置移动 \(2\) 在奇数位置的字母被单独留下(移动 \(0\) ,因为“A”是第0个字母,如果您在开始计数 \(0\)

算法:

输入:

msg :出现在 symbols (明文)

key :出现在 symbols (秘钥)

symbols :定义字母表的一串字母

输出:

ct :字符串(密文消息)

步骤:
  1. 从0,…,N开始给字母表中的字母编号

  2. 从字符串计算 key 一览表 L1 对应的整数。让 n1 = len(L1) .

  3. 从字符串计算 msg 一览表 L2 对应的整数。让 n2 = len(L2) .

  4. 休息 L2 按顺序排列成大小的子列表 n1 ;最后一个子列表可能小于 n1

  5. 对于每个子列表 L 属于 L2 ,计算新列表 C 给予者 C[i] = L[i] + L1[i] (mod N)i -子列表中的第个元素,对于每个元素 i .

  6. 把这些单子集合起来 C 通过连接到一个新的长度列表 n2 .

  7. 从新列表计算一个字符串 ct 对应的字母。

一旦知道关键是, \(n\) 字符长,频率分析可应用于 \(n\) -用于确定明文的密文的第个字母。此方法称为 卡西基检查 (尽管它是巴贝奇首先发现的)。如果他们的键和信息一样长,并且由随机选择的字符组成——一个一次性的键盘——信息理论上是牢不可破的。

Vigenere实际发现的密码是一个“自动密钥”密码,描述如下。

算法:

输入:

key :一串字母(密钥)

msg :字符串(纯文本消息)

输出:

ct :大写字母字符串(密文消息)

步骤:
  1. 从0,…,N开始给字母表中的字母编号

  2. 从字符串计算 msg 一览表 L2 对应的整数。让 n2 = len(L2) .

  3. n1 是钥匙的长度。附加到字符串 key 第一个 n2 - n1 明文消息的字符。从这个字符串计算(也包括长度 n2 )名单 L1 与第一步中的字母数字相对应的整数。

  4. 计算新列表 C 给予者 C[i] = L1[i] + L2[i] (mod N) .

  5. 从新列表计算一个字符串 ct 与新整数相对应的字母。

要破译自动密钥密文,密钥是用来破译第一个 n1 然后这些字符就成了破解下一个的关键 n1 字符等:

>>> m = AZ('go navy, beat army! yes you can'); m
'GONAVYBEATARMYYESYOUCAN'
>>> key = AZ('gold bug'); n1 = len(key); n2 = len(m)
>>> auto_key = key + m[:n2 - n1]; auto_key
'GOLDBUGGONAVYBEATARMYYE'
>>> ct = encipher_vigenere(m, auto_key); ct
'MCYDWSHKOGAMKZCELYFGAYR'
>>> n1 = len(key)
>>> pt = []
>>> while ct:
...     part, ct = ct[:n1], ct[n1:]
...     pt.append(decipher_vigenere(part, key))
...     key = pt[-1]
...
>>> ''.join(pt) == m
True

工具书类

sympy.crypto.crypto.decipher_vigenere(msg, key, symbols=None)[源代码]#

用维格纳密码解码。

实例

>>> from sympy.crypto.crypto import decipher_vigenere
>>> key = "encrypt"
>>> ct = "QRGK kt HRZQE BPR"
>>> decipher_vigenere(ct, key)
'MEETMEONMONDAY'
sympy.crypto.crypto.encipher_hill(msg, key, symbols=None, pad='Q')[源代码]#

返回的希尔密码加密 msg .

参数:

msg

的明文消息 \(n\) 大写字母。

key

A \(k \times k\) 可逆矩阵 \(K\) ,其所有条目都在 \(Z_{{26}}\) (或使用任何数量的符号)。

pad

字符(默认为“Q”),用于使文本长度为 k .

返回:

计算机断层扫描

大写字母的密文。

解释

The Hill cipher [R159], invented by Lester S. Hill in the 1920's [R160], was the first polygraphic cipher in which it was practical (though barely) to operate on more than three symbols at once. The following discussion assumes an elementary knowledge of matrices.

First, each letter is first encoded as a number starting with 0. Suppose your message \(msg\) consists of \(n\) capital letters, with no spaces. This may be regarded an \(n\)-tuple M of elements of \(Z_{26}\) (if the letters are those of the English alphabet). A key in the Hill cipher is a \(k x k\) matrix \(K\), all of whose entries are in \(Z_{26}\), such that the matrix \(K\) is invertible (i.e., the linear transformation \(K: Z_{N}^k \rightarrow Z_{N}^k\) is one-to-one).

笔记

算法:

步骤:
  1. 从0,…,N开始给字母表中的字母编号

  2. 从字符串计算 msg 一览表 L 对应的整数。让 n = len(L) .

  3. 打破名单 L 上升到 t = ceiling(n/k) 子列表 L_1L_t 尺寸的 k (最后一个列表“填充”以确保其大小 k

  4. 计算新列表 C_1C_t 给予者 C[i] = K*L_i (算术在N模式下完成),对于每个 i .

  5. 将这些连接到一个列表中 C = C_1 + ... + C_t .

  6. 计算依据 C 一根绳子 ct 对应的字母。这个有长度 k*t .

参见

decipher_hill

工具书类

[R160] (1,2)

莱斯特S.希尔,《代数字母表中的密码学》,美国数学月刊第36卷,1929年6月至7月,第306-312页。

sympy.crypto.crypto.decipher_hill(msg, key, symbols=None)[源代码]#

解密与加密相同,但使用关键矩阵的逆。

实例

>>> from sympy.crypto.crypto import encipher_hill, decipher_hill
>>> from sympy import Matrix
>>> key = Matrix([[1, 2], [3, 5]])
>>> encipher_hill("meet me on monday", key)
'UEQDUEODOCTCWQ'
>>> decipher_hill(_, key)
'MEETMEONMONDAY'

当明文长度(去掉无效字符)不是密钥维数的倍数时,加密和解密后的文本末尾会出现额外的字符。为了破译文本,这些字符必须包含在要破译的文本中。在下面,键的维数为4,但文本缺少4的倍数,因此将添加两个字符。

>>> key = Matrix([[1, 1, 1, 2], [0, 1, 1, 0],
...               [2, 2, 3, 4], [1, 1, 0, 1]])
>>> msg = "ST"
>>> encipher_hill(msg, key)
'HJEB'
>>> decipher_hill(_, key)
'STQQ'
>>> encipher_hill(msg, key, pad="Z")
'ISPK'
>>> decipher_hill(_, key)
'STZZ'

如果在任一情况下忽略密文的最后两个字符,则将恢复错误的明文:

>>> decipher_hill("HD", key)
'ORMV'
>>> decipher_hill("IS", key)
'UIKY'

参见

encipher_hill

sympy.crypto.crypto.encipher_bifid(msg, key, symbols=None)[源代码]#

对明文执行二进制密码加密 msg ,并返回密文。

这是Bifid密码的版本,它使用 \(n \times n\) 波利比乌斯广场。

参数:

msg

纯文本字符串。

key

密钥的短字符串。

重复字符将被忽略,然后用中的字符填充 symbols 不是在短键里。

symbols

\(n \times n\) 定义字母表的字符。

(默认为字符串。可打印)

返回:

密文

使用不带空格的Bifid5密码的密文。

工具书类

sympy.crypto.crypto.decipher_bifid(msg, key, symbols=None)[源代码]#

对密文执行双歧密码解密 msg ,并返回明文。

这是Bifid密码的版本,它使用 \(n \times n\) 波利比乌斯广场。

参数:

msg

密文字符串。

key

密钥的短字符串。

重复的字符被忽略,然后用不在短键中的符号中的字符填充它。

symbols

\(n \times n\) 定义字母表的字符。

(违约=字符串。可打印,一个 \(10 \times 10\) 矩阵)

返回:

破译

破译的文本。

实例

>>> from sympy.crypto.crypto import (
...     encipher_bifid, decipher_bifid, AZ)

使用bifid5字母表进行加密:

>>> alp = AZ().replace('J', '')
>>> ct = AZ("meet me on monday!")
>>> key = AZ("gold bug")
>>> encipher_bifid(ct, key, alp)
'IEILHHFSTSFQYE'

输入文本或密文时,空格将被忽略,因此可以根据需要设置格式。从前面重新输入密文,每行放4个字符,并用额外的J填充,不会对解密造成问题:

>>> decipher_bifid('''
... IEILH
... HFSTS
... FQYEJ''', key, alp)
'MEETMEONMONDAY'

当没有给出字母表时,将使用所有100个可打印字符:

>>> key = ''
>>> encipher_bifid('hello world!', key)
'bmtwmg-bIo*w'
>>> decipher_bifid(_, key)
'hello world!'

如果密钥被更改,则会获得不同的加密:

>>> key = 'gold bug'
>>> encipher_bifid('hello world!', 'gold_bug')
'hg2sfuei7t}w'

如果用于解密消息的密钥不精确,则无法完全获得原始文本:

>>> decipher_bifid(_, 'gold pug')
'heldo~wor6d!'
sympy.crypto.crypto.bifid5_square(key=None)[源代码]#

Poly5xBius方形。

\(5 \times 5\) 双歧密码。

实例

>>> from sympy.crypto.crypto import bifid5_square
>>> bifid5_square("gold bug")
Matrix([
[G, O, L, D, B],
[U, A, C, E, F],
[H, I, K, M, N],
[P, Q, R, S, T],
[V, W, X, Y, Z]])
sympy.crypto.crypto.encipher_bifid5(msg, key)[源代码]#

对明文执行二进制密码加密 msg ,并返回密文。

参数:

msg :结构

纯文本字符串。

转换为大写,除J外,不包括所有字母。

key

键的短字符串;非字母字母、J和重复字符被忽略,如果长度小于25个字符,则用字母表中的其他字母(按字母顺序)填充。

返回:

计算机断层扫描

密文(全大写,无空格)。

解释

这是Bifid密码的版本,它使用 \(5 \times 5\) 波利比乌斯广场。字母“J”被忽略,因此在加密之前必须用其他东西(传统上是“I”)替换它。

算法:(5x5案例)

步骤:
  1. 创建 \(5 \times 5\) 波利比乌斯广场 S 关联到 key 如下:

    1. 从左到右,从上到下,将键的字母放入 \(5 \times 5\) 矩阵,

    2. 如果钥匙少于25个字母,则将字母表中的字母添加到钥匙中,直到 \(5 \times 5\) 正方形已填充。

  2. 创建列表 P 一对数字,它们是 msg .

  3. L1 是所有第一个坐标的列表 P (长度 L1 = n ),让 L2 是所有第二个坐标的列表 P (所以 L2 也是 n

  4. LL1L2 (长度 L = 2*n ),但连续的数字是成对的 (L[2*i], L[2*i + 1]) . 你可以考虑 L 作为长度对的列表 n .

  5. C 是表格中所有字母的列表 S[i, j] 为了所有 (i, j) 在里面 L . 作为字符串,这是 msg .

实例

>>> from sympy.crypto.crypto import (
...     encipher_bifid5, decipher_bifid5)

“J”将被省略,除非它被替换为其他内容:

>>> round_trip = lambda m, k: \
...     decipher_bifid5(encipher_bifid5(m, k), k)
>>> key = 'a'
>>> msg = "JOSIE"
>>> round_trip(msg, key)
'OSIE'
>>> round_trip(msg.replace("J", "I"), key)
'IOSIE'
>>> j = "QIQ"
>>> round_trip(msg.replace("J", j), key).replace(j, "J")
'JOSIE'

笔记

Bifid密码是由Felix Delastelle在1901年左右发明的。它是一个 分数代换 密码,用较小字母表中的成对符号代替字母。密码使用 \(5 \times 5\) 用字母表的某种顺序填充的正方形,除了“J”被替换为“I”(这是所谓的Polybius正方形;有一个 \(6 \times 6\) 如果你再加上“J”,并且附加到通常的26个字母表上,数字0,1,…,9。根据海伦·盖恩斯的书 密码分析 ,这种密码在第一次世界大战期间被德国军队用于战场。

sympy.crypto.crypto.decipher_bifid5(msg, key)[源代码]#

返回的Bifid密码解密 msg .

参数:

msg

密文字符串。

key

关键字的短字符串;重复的字符将被忽略,如果长度小于25个字符,将用字母表中省略“J”的其他字母填充。忽略非字母字符。

返回:

明文

来自Bifid5密码的明文(全大写,无空格)。

解释

这是Bifid密码的版本,它使用 \(5 \times 5\) 波利比乌斯广场;字母“J”被忽略,除非 key 长度为25。

实例

>>> from sympy.crypto.crypto import encipher_bifid5, decipher_bifid5
>>> key = "gold bug"
>>> encipher_bifid5('meet me on friday', key)
'IEILEHFSTSFXEE'
>>> encipher_bifid5('meet me on monday', key)
'IEILHHFSTSFQYE'
>>> decipher_bifid5(_, key)
'MEETMEONMONDAY'
sympy.crypto.crypto.encipher_bifid6(msg, key)[源代码]#

对明文执行二进制密码加密 msg ,并返回密文。

这是Bifid密码的版本,它使用 \(6 \times 6\) 波利比乌斯广场。

参数:

msg

纯文本字符串(数字可以)。

key

关键字的短字符串(数字可以)。

如果 key 如果长度小于36个字符,则正方形将填充字母A到Z以及数字0到9。

返回:

密文

双歧密码的密文(全大写,无空格)。

sympy.crypto.crypto.decipher_bifid6(msg, key)[源代码]#

对密文执行双歧密码解密 msg ,并返回明文。

这是Bifid密码的版本,它使用 \(6 \times 6\) 波利比乌斯广场。

参数:

msg

密文字符串(数字可以);转换为大写

key

关键字的短字符串(数字可以)。

如果 key 如果长度小于36个字符,则正方形将填充字母A到Z以及数字0到9。所有字母都转换成大写。

返回:

明文

来自Bifid密码的明文(全大写,无空格)。

实例

>>> from sympy.crypto.crypto import encipher_bifid6, decipher_bifid6
>>> key = "gold bug"
>>> encipher_bifid6('meet me on monday at 8am', key)
'KFKLJJHF5MMMKTFRGPL'
>>> decipher_bifid6(_, key)
'MEETMEONMONDAYAT8AM'
sympy.crypto.crypto.bifid6_square(key=None)[源代码]#

6x6波利比乌斯广场。

\(6 \times 6\) 双歧密码。假设符号的字母表是“A”、…、“Z”、“0”、…、“9”。

实例

>>> from sympy.crypto.crypto import bifid6_square
>>> key = "gold bug"
>>> bifid6_square(key)
Matrix([
[G, O, L, D, B, U],
[A, C, E, F, H, I],
[J, K, M, N, P, Q],
[R, S, T, V, W, X],
[Y, Z, 0, 1, 2, 3],
[4, 5, 6, 7, 8, 9]])
sympy.crypto.crypto.rsa_public_key(*args, **kwargs)[源代码]#

退回RSA 公钥 一对, \((n, e)\)

参数:

args :自然

如果指定为 \(p, q, e\) 在哪里? \(p\)\(q\) 是不同的素数和 \(e\) 是RSA的理想公共指数, \(n = p q\)\(e\) 会被证实是针对托特的 \(\phi(n)\) (Euler ToClient)或 \(\lambda(n)\) (Carmichael totient)是 \(\gcd(e, \phi(n)) = 1\)\(\gcd(e, \lambda(n)) = 1\) .

If specified as \(p_1, p_2, \dots, p_n, e\) where \(p_1, p_2, \dots, p_n\) are specified as primes, and \(e\) is specified as a desired public exponent of the RSA, it will be able to form a multi-prime RSA, which is a more generalized form of the popular 2-prime RSA.

也可以通过将参数指定为 \(p, e\) ,这可以看作是多素RSA的一个小例子。

此外,通过指定两个或多个素数对相同,可以形成一个多幂RSA。然而,与两个不同的素数RSA或多素数RSA不同,不是所有的数都是完全剩余系统 (\(\mathbb{{Z}}_n\) )将被解密,因为映射 \(\mathbb{{Z}}_{{n}} \rightarrow \mathbb{{Z}}_{{n}}\) 不会有双重目的。(只有当 \(e = 1\) 或者更广泛地说,

\[e\在\左\{1+k\λ(n)\]

当RSA还原为恒等式时)然而,对于减余系统中的数字,RSA仍然可以解密 (\(\mathbb{{Z}}_n^{{\times}}\) ),因为映射 \(\mathbb{{Z}}_{{n}}^{{\times}} \rightarrow \mathbb{{Z}}_{{n}}^{{\times}}\) 仍然可以是双向的。

If you pass a non-prime integer to the arguments \(p_1, p_2, \dots, p_n\), the particular number will be prime-factored and it will become either a multi-prime RSA or a multi-power RSA in its canonical form, depending on whether the product equals its radical or not. \(p_1 p_2 \dots p_n = \text{rad}(p_1 p_2 \dots p_n)\)

折腾 :bool,可选

If 'Euler', it uses Euler's totient \(\phi(n)\) which is sympy.functions.combinatorial.numbers.totient() in SymPy.

If 'Carmichael', it uses Carmichael's totient \(\lambda(n)\) which is sympy.functions.combinatorial.numbers.reduced_totient() in SymPy.

与私钥生成不同,这是生成公钥的一个简单关键字,因为 \(\gcd(e, \phi(n)) = 1 \iff \gcd(e, \lambda(n)) = 1\) .

指数 :非负整数,可选

Returns an arbitrary solution of a RSA public key at the index specified at \(0, 1, 2, \dots\). This parameter needs to be specified along with totient='Carmichael'.

类似于RSA私钥的非唯一性,如 index 中的参数文档 rsa_private_key() ,RSA公钥也不是唯一的,并且有无穷多个RSA公共指数可以以相同的方式表现。

从任何给定的RSA公共指数 \(e\) ,可能有另一个RSA公共指数 \(e + k \lambda(n)\) 在哪里? \(k\) 是一个整数, \(\lambda\) 是一个Carmichael的tolient函数。

然而,仅考虑正的情形,就可以得到RSA公共指数的主解 \(e_0\) 在里面 \(0 < e_0 < \lambda(n)\) ,所有其他解都可以规范化为 \(e_0 + k \lambda(n)\) .

index 指定 \(k\) 表示法产生RSA公钥可以具有的任何可能值。

计算任意RSA公钥的示例:

>>> from sympy.crypto.crypto import rsa_public_key
>>> rsa_public_key(61, 53, 17, totient='Carmichael', index=0)
(3233, 17)
>>> rsa_public_key(61, 53, 17, totient='Carmichael', index=1)
(3233, 797)
>>> rsa_public_key(61, 53, 17, totient='Carmichael', index=2)
(3233, 1577)

多电源 :bool,可选

Any pair of non-distinct primes found in the RSA specification will restrict the domain of the cryptosystem, as noted in the explanation of the parameter args.

SymPy RSA密钥生成器在将其作为多电源RSA发送之前可能会发出警告,但是,如果通过,则可以禁用该警告 True 到这个关键字。

返回:

(东北) :int,int

\(n\) 是任意数目的素数的乘积。

\(e\) 相对于Euler-toclient来说是相对质的 \(\phi(n)\) .

如果给定的参数少于两个,则返回,或者 \(e\) 不是相对质数。

实例

>>> from sympy.crypto.crypto import rsa_public_key

两素数RSA的公钥:

>>> p, q, e = 3, 5, 7
>>> rsa_public_key(p, q, e)
(15, 7)
>>> rsa_public_key(p, q, 30)
False

多质RSA的公钥:

>>> primes = [2, 3, 5, 7, 11, 13]
>>> e = 7
>>> args = primes + [e]
>>> rsa_public_key(*args)
(30030, 7)

笔记

虽然RSA可以推广到任何模上 \(n\) ,使用两个大素数已经成为最流行的规范,因为两个大素数的乘积通常比 \(n\) 可以有。

然而,它可能需要进一步了解每一个质数因式分解算法的时间复杂性来验证这一说法。

工具书类

sympy.crypto.crypto.rsa_private_key(*args, **kwargs)[源代码]#

退回RSA 私钥 一对, \((n, d)\)

参数:

args :自然

关键字与 args 在里面 rsa_public_key() .

折腾 :bool,可选

If 'Euler', it uses Euler's totient convention \(\phi(n)\) which is sympy.functions.combinatorial.numbers.totient() in SymPy.

If 'Carmichael', it uses Carmichael's totient convention \(\lambda(n)\) which is sympy.functions.combinatorial.numbers.reduced_totient() in SymPy.

私钥生成可能存在一些输出差异,如下例所示。

使用Euler的ToClient的示例:

>>> from sympy.crypto.crypto import rsa_private_key
>>> rsa_private_key(61, 53, 17, totient='Euler')
(3233, 2753)

使用Carmichael的ToClient的示例:

>>> from sympy.crypto.crypto import rsa_private_key
>>> rsa_private_key(61, 53, 17, totient='Carmichael')
(3233, 413)

指数 :非负整数,可选

Returns an arbitrary solution of a RSA private key at the index specified at \(0, 1, 2, \dots\). This parameter needs to be specified along with totient='Carmichael'.

RSA private exponent是 \(e d \mod \lambda(n) = 1\) 任何形式的 \(d + k \lambda(n)\) 在哪里 \(d\) 是另一个已经计算的私有指数,并且 \(\lambda\) 是一个Carmichael的tolient函数,并且 \(k\) 是任意整数。

然而,仅考虑正的情况,就可以得到RSA私有指数的主解 \(d_0\) 在里面 \(0 < d_0 < \lambda(n)\) ,所有其他解都可以规范化为 \(d_0 + k \lambda(n)\) .

index 指定 \(k\) 表示法产生RSA私钥可以具有的任何可能值。

计算任意RSA私钥的示例:

>>> from sympy.crypto.crypto import rsa_private_key
>>> rsa_private_key(61, 53, 17, totient='Carmichael', index=0)
(3233, 413)
>>> rsa_private_key(61, 53, 17, totient='Carmichael', index=1)
(3233, 1193)
>>> rsa_private_key(61, 53, 17, totient='Carmichael', index=2)
(3233, 1973)

多电源 :bool,可选

关键字与 multipower 在里面 rsa_public_key() .

返回:

(n,d) :int,int

\(n\) 是任意数目的素数的乘积。

\(d\) 是的反义词 \(e\) (国防部 \(\phi(n)\) 何处 \(e\) 给出指数,并且 \(\phi\) 是一个欧拉托特。

如果给定的参数少于两个,则返回,或者 \(e\) 不是相对质数相对于模量的。

实例

>>> from sympy.crypto.crypto import rsa_private_key

双素数RSA的私钥:

>>> p, q, e = 3, 5, 7
>>> rsa_private_key(p, q, e)
(15, 7)
>>> rsa_private_key(p, q, 30)
False

多质RSA的私钥:

>>> primes = [2, 3, 5, 7, 11, 13]
>>> e = 7
>>> args = primes + [e]
>>> rsa_private_key(*args)
(30030, 823)

工具书类

sympy.crypto.crypto.encipher_rsa(i, key, factors=None)[源代码]#

用RSA加密明文。

参数:

i :整数

要加密的明文。

key :(n,e)其中n,e是整数

\(n\) 关键是 \(e\) 是键的指数。加密的计算方法是 \(i^e \bmod n\) .

密钥可以是公钥,也可以是私钥,但是,用公钥加密的消息只能用私钥解密,反之亦然,因为RSA是一种非对称加密系统。

因素 :互质整数列表

这与关键字相同 factors 在里面 decipher_rsa() .

笔记

一些规范可能使RSA在加密方面没有意义。

例如, \(0\)\(1\) 取任意数次求幂后将始终保持不变,因此,应避免。

此外,如果 \(i^e < n\)\(i\) 可以很容易地通过 \(e\) 第三根。

同时,将指数指定为 \(1\) 或者用更普遍的形式 \(1 + k \lambda(n)\) 在哪里? \(k\) 是一个非负整数, \(\lambda\) 是一个carmichael Toclient,RSA变成了一个身份映射。

实例

>>> from sympy.crypto.crypto import encipher_rsa
>>> from sympy.crypto.crypto import rsa_public_key, rsa_private_key

公钥加密:

>>> p, q, e = 3, 5, 7
>>> puk = rsa_public_key(p, q, e)
>>> msg = 12
>>> encipher_rsa(msg, puk)
3

私钥加密:

>>> p, q, e = 3, 5, 7
>>> prk = rsa_private_key(p, q, e)
>>> msg = 12
>>> encipher_rsa(msg, prk)
3

使用中国剩余定理加密:

>>> encipher_rsa(msg, prk, factors=[p, q])
3
sympy.crypto.crypto.decipher_rsa(i, key, factors=None)[源代码]#

用RSA解密密文。

参数:

i :整数

要解密的密文。

key :(n,d)其中n,d是整数

\(n\) 关键是 \(d\) 是键的指数。解密的计算方法是 \(i^d \bmod n\) .

密钥可以是公钥,也可以是私钥,但是,用公钥加密的消息只能用私钥解密,反之亦然,因为RSA是一种非对称加密系统。

因素 :互质整数列表

As the modulus \(n\) created from RSA key generation is composed of arbitrary prime factors \(n = {p_1}^{k_1}{p_2}^{k_2}\dots{p_n}^{k_n}\) where \(p_1, p_2, \dots, p_n\) are distinct primes and \(k_1, k_2, \dots, k_n\) are positive integers, chinese remainder theorem can be used to compute \(i^d \bmod n\) from the fragmented modulo operations like

\[i^d \bmod {p_1}^{k_1}, i^d \bmod {p_2}^{k_2}, \dots, i^d \bmod {p_n}^{k_n}\]

或者类似的

\[i^d \bmod {p_1}^{k_1}{p_2}^{k_2}, i^d \bmod {p_3}^{k_3}, \dots , i^d \bmod {p_n}^{k_n}\]

只要每个模之间没有公约数。

生成RSA密钥对时使用的原始素数是一个不错的选择。

Note that the speed advantage of using this is only viable for very large cases (Like 2048-bit RSA keys) since the overhead of using pure Python implementation of sympy.ntheory.modular.crt() may overcompensate the theoretical speed advantage.

笔记

Notes 文件中的章节 encipher_rsa()

实例

>>> from sympy.crypto.crypto import decipher_rsa, encipher_rsa
>>> from sympy.crypto.crypto import rsa_public_key, rsa_private_key

公钥加密和解密:

>>> p, q, e = 3, 5, 7
>>> prk = rsa_private_key(p, q, e)
>>> puk = rsa_public_key(p, q, e)
>>> msg = 12
>>> new_msg = encipher_rsa(msg, prk)
>>> new_msg
3
>>> decipher_rsa(new_msg, puk)
12

私钥加密和解密:

>>> p, q, e = 3, 5, 7
>>> prk = rsa_private_key(p, q, e)
>>> puk = rsa_public_key(p, q, e)
>>> msg = 12
>>> new_msg = encipher_rsa(msg, puk)
>>> new_msg
3
>>> decipher_rsa(new_msg, prk)
12

利用中国剩余定理解密:

>>> decipher_rsa(new_msg, prk, factors=[p, q])
12

参见

encipher_rsa

sympy.crypto.crypto.kid_rsa_public_key(a, b, A, B)[源代码]#

Kid RSA是RSA的一个版本,因为它不涉及求幂运算,所以非常适合教小学生。

解释

爱丽丝想和鲍勃谈谈。Bob按如下方式生成密钥。密钥生成:

  • 选择正整数 \(a, b, A, B\) 随机的。

  • 计算 \(M = a b - 1\)\(e = A M + a\)\(d = B M + b\)\(n = (e d - 1)//M\) .

  • 这个 公钥\((n, e)\) . 鲍勃把这些寄给爱丽丝。

  • 这个 私钥\((n, d)\) ,鲍勃对此保密。

加密:如果 \(p\) 是明文信息,那么密文就是 \(c = p e \pmod n\) .

解密:如果 \(c\) 是密文信息,那么明文就是 \(p = c d \pmod n\) .

实例

>>> from sympy.crypto.crypto import kid_rsa_public_key
>>> a, b, A, B = 3, 4, 5, 6
>>> kid_rsa_public_key(a, b, A, B)
(369, 58)
sympy.crypto.crypto.kid_rsa_private_key(a, b, A, B)[源代码]#

计算 \(M = a b - 1\)\(e = A M + a\)\(d = B M + b\)\(n = (e d - 1) / M\) . 这个 私钥\(d\) ,鲍勃对此保密。

实例

>>> from sympy.crypto.crypto import kid_rsa_private_key
>>> a, b, A, B = 3, 4, 5, 6
>>> kid_rsa_private_key(a, b, A, B)
(369, 70)
sympy.crypto.crypto.encipher_kid_rsa(msg, key)[源代码]#

在这里 msg 是明文和 key 是公钥。

实例

>>> from sympy.crypto.crypto import (
...     encipher_kid_rsa, kid_rsa_public_key)
>>> msg = 200
>>> a, b, A, B = 3, 4, 5, 6
>>> key = kid_rsa_public_key(a, b, A, B)
>>> encipher_kid_rsa(msg, key)
161
sympy.crypto.crypto.decipher_kid_rsa(msg, key)[源代码]#

在这里 msg 是明文和 key 是私钥。

实例

>>> from sympy.crypto.crypto import (
...     kid_rsa_public_key, kid_rsa_private_key,
...     decipher_kid_rsa, encipher_kid_rsa)
>>> a, b, A, B = 3, 4, 5, 6
>>> d = kid_rsa_private_key(a, b, A, B)
>>> msg = 200
>>> pub = kid_rsa_public_key(a, b, A, B)
>>> pri = kid_rsa_private_key(a, b, A, B)
>>> ct = encipher_kid_rsa(msg, pub)
>>> decipher_kid_rsa(ct, pri)
200
sympy.crypto.crypto.encode_morse(msg, sep='|', mapping=None)[源代码]#

Encodes a plaintext into popular Morse Code with letters separated by sep and words by a double sep.

实例

>>> from sympy.crypto.crypto import encode_morse
>>> msg = 'ATTACK RIGHT FLANK'
>>> encode_morse(msg)
'.-|-|-|.-|-.-.|-.-||.-.|..|--.|....|-||..-.|.-..|.-|-.|-.-'

工具书类

sympy.crypto.crypto.decode_morse(msg, sep='|', mapping=None)[源代码]#

Decodes a Morse Code with letters separated by sep (default is '|') and words by \(word_sep\) (default is '||) into plaintext.

实例

>>> from sympy.crypto.crypto import decode_morse
>>> mc = '--|---|...-|.||.|.-|...|-'
>>> decode_morse(mc)
'MOVE EAST'

工具书类

sympy.crypto.crypto.lfsr_sequence(key, fill, n)[源代码]#

此函数用于创建LFSR序列。

参数:

key :列表

有限域元素列表, \([c_0, c_1, \ldots, c_k].\)

fill :列表

LFSR序列的初始项列表, \([x_0, x_1, \ldots, x_k].\)

n

函数返回的序列的项数。

返回:

L

LFSR序列由 \(x_{{n+1}} = c_k x_n + \ldots + c_0 x_{{n-k}}\) ,为了 \(n \leq k\) .

笔记

S. Golomb [G171] gives a list of three statistical properties a sequence of numbers \(a = \{a_n\}_{n=1}^\infty\), \(a_n \in \{0,1\}\), should display to be considered "random". Define the autocorrelation of \(a\) to be

\[C(k)=C(k,a)=\lim{N\rightarrow\infty}{1\ over N}\sum{N=1}^N(-1)^{a_N+a{N+k}}。\]

在什么情况下 \(a\) 是周期性的 \(P\) 那么这就减少到

\[C(k)={1\ over P}\sum{n=1}^P(-1)^{a_n+a{n+k}。\]

假定 \(a\) 是周期性的 \(P\) .

  • 余额:

    \[\左|\sum{n=1}^P(-1)^{a_n}\右|\leq 1。\]
  • 低自相关:

    \[\begin{split}C(k)=\left\{\begin{array}{cc}1,&k=0,\\\epsilon,&k\ne 0。\右结束{array}\右。\end{split}\]

    (对于满足前两个性质的序列,已知 \(\epsilon = -1/P\) 必须保持住。)

  • 比例运行特性:在每个周期中,有一半的运行具有长度 \(1\) 四分之一有长度 \(2\) 等等,而且 \(1\) 就像现在一样 \(0\) s。

实例

>>> from sympy.crypto.crypto import lfsr_sequence
>>> from sympy.polys.domains import FF
>>> F = FF(2)
>>> fill = [F(1), F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(0), F(1)]
>>> lfsr_sequence(key, fill, 10)
[1 mod 2, 1 mod 2, 0 mod 2, 1 mod 2, 0 mod 2,
1 mod 2, 1 mod 2, 0 mod 2, 0 mod 2, 1 mod 2]

工具书类

[G171] (1,2)

Solomon Golomb,《移位寄存器序列》,爱琴海公园出版社,加利福尼亚州拉古纳山,1967年

sympy.crypto.crypto.lfsr_autocorrelation(L, P, k)[源代码]#

此函数用于计算LFSR自相关函数。

参数:

L

元素的周期性序列 \(GF(2)\) . 我的长度必须大于P。

P

L。

k :内景

An integer \(k\) (\(0 < k < P\)).

返回:

自相关

LFSR L自相关的第k个值。

实例

>>> from sympy.crypto.crypto import (
...     lfsr_sequence, lfsr_autocorrelation)
>>> from sympy.polys.domains import FF
>>> F = FF(2)
>>> fill = [F(1), F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_autocorrelation(s, 15, 7)
-1/15
>>> lfsr_autocorrelation(s, 15, 0)
1
sympy.crypto.crypto.lfsr_connection_polynomial(s)[源代码]#

此函数用于计算LFSR连接多项式。

参数:

s

偶数长度的元素序列,在有限域中有条目。

返回:

C(x)

最小LFSR的连接多项式。

This implements the algorithm in section 3 of J. L. Massey's article [M172].

实例

>>> from sympy.crypto.crypto import (
...     lfsr_sequence, lfsr_connection_polynomial)
>>> from sympy.polys.domains import FF
>>> F = FF(2)
>>> fill = [F(1), F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**4 + x + 1
>>> fill = [F(1), F(0), F(0), F(1)]
>>> key = [F(1), F(1), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**3 + 1
>>> fill = [F(1), F(0), F(1)]
>>> key = [F(1), F(1), F(0)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**3 + x**2 + 1
>>> fill = [F(1), F(0), F(1)]
>>> key = [F(1), F(0), F(1)]
>>> s = lfsr_sequence(key, fill, 20)
>>> lfsr_connection_polynomial(s)
x**3 + x + 1

工具书类

[M172] (1,2)

詹姆斯L.梅西,“移位寄存器合成与BCH解码”,IEEE Trans。信息论,第15卷(1),第122-127页,1969年1月。

sympy.crypto.crypto.elgamal_public_key(key)[源代码]#

返回三个数元组作为公钥。

参数:

key :(p、r、e)

元组生成者 elgamal_private_key .

返回:

元组 :(p、r、e)

\(e = r**d \bmod p\)

\(d\) 是私钥中的随机数。

实例

>>> from sympy.crypto.crypto import elgamal_public_key
>>> elgamal_public_key((1031, 14, 636))
(1031, 14, 212)
sympy.crypto.crypto.elgamal_private_key(digit=10, seed=None)[源代码]#

返回三个数元组作为私钥。

参数:

数字 :内景

密钥的最小二进制位数。

返回:

元组 :(p、r、d)

p=质数。

r=原始根。

d=随机数。

解释

Elgamal encryption is based on the mathematical problem called the Discrete Logarithm Problem (DLP). For example,

\(a^{b} \equiv c \pmod p\)

一般来说,如果 ab 我们都知道, ct 很容易计算。如果 b 是未知的,很难使用 act 得到 b .

笔记

For testing purposes, the seed parameter may be set to control the output of this routine. See sympy.core.random._randrange.

实例

>>> from sympy.crypto.crypto import elgamal_private_key
>>> from sympy.ntheory import is_primitive_root, isprime
>>> a, b, _ = elgamal_private_key()
>>> isprime(a)
True
>>> is_primitive_root(b, a)
True
sympy.crypto.crypto.encipher_elgamal(i, key, seed=None)[源代码]#

Encrypt message with public key.

参数:

msg

编码消息的int。

key

公钥。

返回:

元组 :(c1、c2)

把它加密成两个数字。

解释

i 是表示为整数的纯文本消息。 key 是公钥(p,r,e)。为了加密消息,随机数 a 在里面 range(2, p) 生成并将加密的消息作为 \(c_{{1}}\)\(c_{{2}}\) 在哪里?

\(c_{1} \equiv r^{a} \pmod p\)

\(c_{2} \equiv m e^{a} \pmod p\)

笔记

For testing purposes, the seed parameter may be set to control the output of this routine. See sympy.core.random._randrange.

实例

>>> from sympy.crypto.crypto import encipher_elgamal, elgamal_private_key, elgamal_public_key
>>> pri = elgamal_private_key(5, seed=[3]); pri
(37, 2, 3)
>>> pub = elgamal_public_key(pri); pub
(37, 2, 8)
>>> msg = 36
>>> encipher_elgamal(msg, pub, seed=[3])
(8, 6)
sympy.crypto.crypto.decipher_elgamal(msg, key)[源代码]#

Decrypt message with private key.

\(msg = (c_{1}, c_{2})\)

\(key = (p, r, d)\)

根据扩展的欧几里德定理, \(u c_{{1}}^{{d}} + p n = 1\)

\(u \equiv 1/{{c_{1}}^d} \pmod p\)

\(u c_{2} \equiv \frac{1}{c_{1}^d} c_{2} \equiv \frac{1}{r^{ad}} c_{2} \pmod p\)

\(\frac{1}{r^{ad}} m e^a \equiv \frac{1}{r^{ad}} m {r^{d a}} \equiv m \pmod p\)

实例

>>> from sympy.crypto.crypto import decipher_elgamal
>>> from sympy.crypto.crypto import encipher_elgamal
>>> from sympy.crypto.crypto import elgamal_private_key
>>> from sympy.crypto.crypto import elgamal_public_key
>>> pri = elgamal_private_key(5, seed=[3])
>>> pub = elgamal_public_key(pri); pub
(37, 2, 8)
>>> msg = 17
>>> decipher_elgamal(encipher_elgamal(msg, pub), pri) == msg
True
sympy.crypto.crypto.dh_public_key(key)[源代码]#

返回三个数元组作为公钥。

这是爱丽丝发给鲍勃的元组。

参数:

key :(p、g、a)

由生成的元组 dh_private_key .

返回:

元组 :int、int、int

一个元组 \((p, g, g^a \mod p)\) 具有 \(p\)\(g\)\(a\) 以参数形式给出

实例

>>> from sympy.crypto.crypto import dh_private_key, dh_public_key
>>> p, g, a = dh_private_key();
>>> _p, _g, x = dh_public_key((p, g, a))
>>> p == _p and g == _g
True
>>> x == pow(g, a, p)
True
sympy.crypto.crypto.dh_private_key(digit=10, seed=None)[源代码]#

返回三个整数元组作为私钥。

参数:

digit

键中所需的最小二进制数字数。

返回:

元组 :(p、g、a)

p=质数。

g=p的本根。

a=从2到p-1的随机数。

解释

基于离散对数的hellie-gamal问题称为离散对数问题。

Diffie-Hellman密钥交换分为以下步骤:

  • 爱丽丝和鲍勃同意由质数组成的基 p 原始的根 p 打电话 g

  • 爱丽丝选了一个号码 a 鲍勃选了一个号码 b 在哪里? ab 随机数在范围内吗 \([2, p)\) . 这是他们的私钥。

  • 然后爱丽丝公开派鲍勃去 \(g^{{a}} \pmod p\) 当鲍勃派爱丽丝来的时候 \(g^{{b}} \pmod p\)

  • 它们都会将收到的值提高到自己秘密选择的数字 (ab )现在他们共享了他们的钥匙 \(g^{{ab}} \pmod p\)

笔记

For testing purposes, the seed parameter may be set to control the output of this routine. See sympy.core.random._randrange.

实例

>>> from sympy.crypto.crypto import dh_private_key
>>> from sympy.ntheory import isprime, is_primitive_root
>>> p, g, _ = dh_private_key()
>>> isprime(p)
True
>>> is_primitive_root(g, p)
True
>>> p, g, _ = dh_private_key(5)
>>> isprime(p)
True
>>> is_primitive_root(g, p)
True
sympy.crypto.crypto.dh_shared_key(key, b)[源代码]#

返回一个作为共享密钥的整数。

这就是Bob和Alice都可以使用从对方收到的公钥和私钥来计算的结果。

参数:

key :(p,g,x)

元组 \((p, g, x)\) 生成的 dh_public_key .

b

范围内的随机数 \(2\)\(p - 1\) (由第二个密钥交换成员(Bob)选择)。

返回:

利息

共享密钥。

实例

>>> from sympy.crypto.crypto import (
...     dh_private_key, dh_public_key, dh_shared_key)
>>> prk = dh_private_key();
>>> p, g, x = dh_public_key(prk);
>>> sk = dh_shared_key((p, g, x), 1000)
>>> sk == pow(x, 1000, p)
True
sympy.crypto.crypto.gm_public_key(p, q, a=None, seed=None)[源代码]#

Compute public keys for p and q. Note that in Goldwasser-Micali Encryption, public keys are randomly selected.

参数:

p、 问,答 :int、int、int

初始化变量。

返回:

元组 :(a,N)

a 是输入 a 如果不是 None 否则一些随机整数互质 pq .

Npq .

sympy.crypto.crypto.gm_private_key(p, q, a=None)[源代码]#

检查是否 pq 可以用作Goldwasser Micali加密的私钥。该方法的工作原理大致如下。

参数:

p、 问,答

初始化变量。

返回:

元组 :(p,q)

输入值 pq .

加薪:

ValueError

如果 pq 不是不同的奇素数。

解释

  1. Pick two large primes \(p\) and \(q\).

  2. Call their product \(N\).

  3. Given a message as an integer \(i\), write \(i\) in its bit representation \(b_0, \dots, b_n\).

  4. For each \(k\),

if \(b_k = 0\):

let \(a_k\) be a random square (quadratic residue) modulo \(p q\) such that jacobi_symbol(a, p*q) = 1

if \(b_k = 1\):

let \(a_k\) be a random non-square (non-quadratic residue) modulo \(p q\) such that jacobi_symbol(a, p*q) = 1

returns \(\left[a_1, a_2, \dots\right]\)

\(b_k\) can be recovered by checking whether or not \(a_k\) is a residue. And from the \(b_k\)'s, the message can be reconstructed.

The idea is that, while jacobi_symbol(a, p*q) can be easily computed (and when it is equal to \(-1\) will tell you that \(a\) is not a square mod \(p q\)), quadratic residuosity modulo a composite number is hard to compute without knowing its factorization.

Moreover, approximately half the numbers coprime to \(p q\) have jacobi_symbol() equal to \(1\) . And among those, approximately half are residues and approximately half are not. This maximizes the entropy of the code.

sympy.crypto.crypto.encipher_gm(i, key, seed=None)[源代码]#

使用公钥“key”加密整数“i”。请注意,gm使用随机加密。

参数:

i :内景

要加密的消息。

key :(a,N)

公钥。

返回:

list :int列表

随机加密的消息。

sympy.crypto.crypto.decipher_gm(message, key)[源代码]#

使用公钥“key”解密消息“message”。

参数:

消息 :int列表

随机加密的消息。

key :(p,q)

私钥。

返回:

利息

加密的消息。

sympy.crypto.crypto.encipher_railfence(message, rails)[源代码]#

对明文执行Railfence加密并返回密文

参数:

消息 :string,要加密的消息。

轨道 :int,轨道数。

返回:

加密的字符串消息。

实例

>>> from sympy.crypto.crypto import encipher_railfence
>>> message = "hello world"
>>> encipher_railfence(message,3)
'horel ollwd'

工具书类

sympy.crypto.crypto.decipher_railfence(ciphertext, rails)[源代码]#

使用给定的rails解密消息

参数:

消息 :string,要加密的消息。

轨道 :int,轨道数。

返回:

解密的字符串消息。

实例

>>> from sympy.crypto.crypto import decipher_railfence
>>> decipher_railfence("horel ollwd",3)
'hello world'