密码学#
警告
本单元仅用于教育目的。不要将此模块中的函数用于实际的加密应用程序。如果您希望加密真实数据,我们建议使用类似 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)中存在重复字符,则引发ValueErrorsymbols
或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
.如果
symbols
是None
,不执行检查。
实例
>>> 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'
笔记
算法:
- 步骤:
从0,…,N开始给字母表中的字母编号
从字符串计算
msg
一览表L1
对应的整数。从列表中计算
L1
新名单L2
,通过添加(k mod 26)
到中的每个元素L1
.从列表中计算
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\) 如果这不是真的,就会产生一个错误。笔记
算法:
- 步骤:
从0,…,N开始给字母表中的字母编号
从字符串计算
msg
一览表L1
对应的整数。从列表中计算
L1
新名单L2
,通过替换x
通过a*x + b (mod N)
,对于每个元素x
在里面L1
.从列表中计算
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 = 25
和b = 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'
在特殊情况下
old
和new
是顺序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
:字符串(密文消息)- 步骤:
从0,…,N开始给字母表中的字母编号
从字符串计算
key
一览表L1
对应的整数。让n1 = len(L1)
.从字符串计算
msg
一览表L2
对应的整数。让n2 = len(L2)
.休息
L2
按顺序排列成大小的子列表n1
;最后一个子列表可能小于n1
对于每个子列表
L
属于L2
,计算新列表C
给予者C[i] = L[i] + L1[i] (mod N)
到i
-子列表中的第个元素,对于每个元素i
.把这些单子集合起来
C
通过连接到一个新的长度列表n2
.从新列表计算一个字符串
ct
对应的字母。
一旦知道关键是, \(n\) 字符长,频率分析可应用于 \(n\) -用于确定明文的密文的第个字母。此方法称为 卡西基检查 (尽管它是巴贝奇首先发现的)。如果他们的键和信息一样长,并且由随机选择的字符组成——一个一次性的键盘——信息理论上是牢不可破的。
Vigenere实际发现的密码是一个“自动密钥”密码,描述如下。
算法:
输入:
key
:一串字母(密钥)msg
:字符串(纯文本消息)输出:
ct
:大写字母字符串(密文消息)- 步骤:
从0,…,N开始给字母表中的字母编号
从字符串计算
msg
一览表L2
对应的整数。让n2 = len(L2)
.让
n1
是钥匙的长度。附加到字符串key
第一个n2 - n1
明文消息的字符。从这个字符串计算(也包括长度n2
)名单L1
与第一步中的字母数字相对应的整数。计算新列表
C
给予者C[i] = L1[i] + L2[i] (mod N)
.从新列表计算一个字符串
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).
笔记
算法:
- 步骤:
从0,…,N开始给字母表中的字母编号
从字符串计算
msg
一览表L
对应的整数。让n = len(L)
.打破名单
L
上升到t = ceiling(n/k)
子列表L_1
…L_t
尺寸的k
(最后一个列表“填充”以确保其大小k
)计算新列表
C_1
…C_t
给予者C[i] = K*L_i
(算术在N模式下完成),对于每个i
.将这些连接到一个列表中
C = C_1 + ... + C_t
.计算依据
C
一根绳子ct
对应的字母。这个有长度k*t
.
工具书类
- 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'
- 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案例)
- 步骤:
创建 \(5 \times 5\) 波利比乌斯广场
S
关联到key
如下:从左到右,从上到下,将键的字母放入 \(5 \times 5\) 矩阵,
如果钥匙少于25个字母,则将字母表中的字母添加到钥匙中,直到 \(5 \times 5\) 正方形已填充。
创建列表
P
一对数字,它们是msg
.让
L1
是所有第一个坐标的列表P
(长度L1 = n
),让L2
是所有第二个坐标的列表P
(所以L2
也是n
)让
L
是L1
和L2
(长度L = 2*n
),但连续的数字是成对的(L[2*i], L[2*i + 1])
. 你可以考虑L
作为长度对的列表n
.让
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 issympy.functions.combinatorial.numbers.totient()
in SymPy.If
'Carmichael'
, it uses Carmichael's totient \(\lambda(n)\) which issympy.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 issympy.functions.combinatorial.numbers.totient()
in SymPy.If
'Carmichael'
, it uses Carmichael's totient convention \(\lambda(n)\) which issympy.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
参见
- 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 doublesep
.实例
>>> 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]
工具书类
- 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
工具书类
- 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\)
一般来说,如果
a
和b
我们都知道,ct
很容易计算。如果b
是未知的,很难使用a
和ct
得到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
在哪里?a
和b
随机数在范围内吗 \([2, p)\) . 这是他们的私钥。然后爱丽丝公开派鲍勃去 \(g^{{a}} \pmod p\) 当鲍勃派爱丽丝来的时候 \(g^{{b}} \pmod p\)
它们都会将收到的值提高到自己秘密选择的数字 (
a
或b
)现在他们共享了他们的钥匙 \(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
返回一个作为共享密钥的整数。
这就是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
andq
. Note that in Goldwasser-Micali Encryption, public keys are randomly selected.- 参数:
p、 问,答 :int、int、int
初始化变量。
- 返回:
元组 :(a,N)
a
是输入a
如果不是None
否则一些随机整数互质p
和q
.N
是p
和q
.
- sympy.crypto.crypto.gm_private_key(p, q, a=None)[源代码]#
检查是否
p
和q
可以用作Goldwasser Micali加密的私钥。该方法的工作原理大致如下。- 参数:
p、 问,答
初始化变量。
- 返回:
元组 :(p,q)
输入值
p
和q
.- 加薪:
ValueError
如果
p
和q
不是不同的奇素数。
解释
Pick two large primes \(p\) and \(q\).
Call their product \(N\).
Given a message as an integer \(i\), write \(i\) in its bit representation \(b_0, \dots, b_n\).
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)
私钥。
- 返回:
利息
加密的消息。