关于加密算法 Python实现 的笔记梳理

Posted 四叔的旅途

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于加密算法 Python实现 的笔记梳理相关的知识,希望对你有一定的参考价值。

前言:

因为主管数据,数据安全问题比较常见,最近遇到一个业务场景,较多数据加密的处理,结合最近优化数据安全流程的问题,重新梳理下数据加密的知识。
原则还是那句话:代码尽可能短,讲的尽可能通俗。
考虑到加密算法的进步,文末特地放了一些新的文章,供大家交流学习。

定义

数据加密:对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码为“密文”,只能在输入相应的密钥之后才能显示出原容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。

算法分类

目前主流的分法有2类,对称加密、非对称加密,当然也还有分3类的,新增单向加密(Hash算法),取决于每个人的理解。

算法对称加密非对称加密单向加密
类别AES / DES / 3DESRSA / DSAMD5,SHA系列
描述数据加解密用相同密钥公钥加密,加解密不同密钥只可加密不可解密
解决问题数据的机密性身份验证数据的完整性
优点加密速度快加解密密钥不一致,公钥公开,密钥安全
缺点密钥一致容易泄露加密速度慢
安全性AES高 > 3DES中 > DES低均高SHA-1高>MD中
速度AES快 > DES中 > 3DES慢RSA中>ECC慢MD5快>SHA-1慢
资源消耗3DES高 > DES中 > AES低ECC高>RSA中
适用范围内部系统,适合大数据量M比特级/秒小数据量/数据签名极少
其他密钥:AES(128/192/256位)/3DES(112/168位)/DES(56位)成熟度:高

主要包介绍

因为平时主要用python处理,所以主要介绍下常用的包

模块名描述
base64用于二进制数据与ASCII字符的转换操作,提供了基于Base16, Base32, 和Base64算法以及实际标准Ascii85和Base85的编码和解码函数
hashlib提供常见的单向加密算法(如MD5,SHA等),每种算法都提供了与其同名的函数实现
hmac实现hmac单向加密算法,支持设置一个额外的密钥(通常被称为’salt’)来提高安全性
secretsPython3.6 新增的模块,用于获取安全随机数
pycrypto持单向加密、对称加密和公钥加密以及随机数操作,该包是Python中密码学最有名的,2012年已停止。幸运的是,该项目的分支PyCrytodome 取代了 PyCrypto。

算法详解

1. base64

  • 网络上最常见的用于传输8Bit字节码的编码方式之一,是一种基于64个可打印字符来表示二进制数据的方法。
  • 从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。
  • 由于以上优点被广泛应用于计算机的各个领域,由于输出内容中包括两个以上“符号类”字符(+, /, =),不同的应用场景又分别研制了Base64的各种“变种”。为统一和规范化Base64的输出,Base62x被视为无符号化的改进版本。
1.1 实现原理
  • 先将字符转化为ASCII码
  • ASCII码转化为8位二进制
  • 将二进制3个字节归成一组,每3个字节在编码之后被转换为4个字节一组(如一个数据有6个字节,可编码后将包含6/3*4=8个字节,不足3个在后边补0或“=”)
  • 统一在6位二进制前补两个0凑足8位。
  • 将补0后的二进制转为十进制。
  • 从Base64编码表获取十进制对应的Base64编码。
1.2 代码实现
import base64
# 编码 encode
# 想将字符串转编码成base64,要先将字符串转换成二进制数据
tmp = "this is a test message:四叔的旅途."
res = tmp.encode("utf-8")              # 默认以 utf-8 编码 
res_code = base64.b64encode(res)       # 被编码的参数必须是二进制数据
print(res_code) 

# 解码 decode
res_code = "b'dGhpcyBpcyBhIHRlc3QgbWVzc2FnZS4="
res = base64.b64decode(res_code).decode("utf-8")
print(res) 

2.MD5 算法

2.1 原理

一种信息摘要算法,以512位分组来处理输入的信息,每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
简单来说,即把一段信息(明文),通过一种有损的方式压缩成定长的字符(32位密文)。因为这种压缩方式是会损失信息的,所以是无法还原出“明文”的,即不可逆
虽然无法从数学上破解MD5算法,但由于现在计算机具备强大的计算能力,可以通过“穷举法”破解该算法。如果想用该算法加密,还可以通过**“加盐”**的方式提高解密难度。算法允许多传一个参数"salt",指定通过MD5加密的次数,这样是能够提高解密难度的。

2.2 应用场景

常用于不可还原的密码存储、信息完整性校验,如:

  • 密码管理(加密注册用户的密码)、电子签名;
  • 网站用户上传图片 / 文件后,将MD5值作为文件名。(MD5因不可逆,可保证唯一性)
  • 比较两个文件是否被篡改。(在下载资源的时候,发现网站提供了MD5值,就是用来检测文件是否被篡改)
  • key-value数据库中使用MD5值作为key。
2.3 代码实现
# 由于MD5模块在python3中被移除,在python3中使用hashlib模块进行md5操作。
# pip install md5/import md5 会报错
# ERROR: Could not find a version that satisfies the requirement md5
# ERROR: No matching distribution found for md5

# 写法1 
import hashlib
tmp_text = 'test message:四叔的旅途'      
md5 = hashlib.md5()                    # 生成MD5对象
md5.update(tmp_text.encode('utf-8'))   # 对数据加密 该方法只接受byte类型,否则会报错,所以要在参数前添加b来转换类型的原因, 后面方法
tmp_text = md5.hexdigest()             # 获取密文  hexdigest 十六进制的意思
print(tmp_text)
# or:
tmp_text = 'test message:四叔的旅途'
tmp_text = hashlib.md5(bytes(tmp_text,encoding = 'utf-8')).hexdigest()

#  不同写法 
tmp_text = hashlib.md5(tmp.encode("utf-8")).hexdigest()      # 最简单写法,推荐☆
tmp_pic = hashlib.md5(b'test message:四叔的旅途').hexdigest()    # 最常见的写法,常用于图片的命名,因为该方法只接受byte类型,否则会报错,所以要在参数前添加b来转换类型的原因
tmp_text = hashlib.new('md5', b'test message:四叔的旅途').hexdigest() # hashlib.new(name[, data]),name传入的是哈希加密算法的名称,如md5

# MD5加盐值(SALT)
tmp_text = 'test message:四叔的旅途'  
# 生成MD5对象
md5 = hashlib.md5(b'~!@@#!#$DFDT@#$@#')
# 以下两种方式与上面效果等同
# md5 = hashlib.md5('~!@@#!#$DFDT@#$@#'.encode('utf-8'))
# md5 = hashlib.md5(bytes('~!@@#!#$DFDT@#$@#',encoding='utf-8'))

3. SHA 算法

3.1 原理

安全哈希算法(英语:Secure Hash Algorithm,缩写为SHA)一个密码哈希函数家族,是FIPS所认证的安全哈希算法。

  • SHA家族的五个算法:SHA-1、SHA-2(SHA-224、SHA-256、SHA-384和SHA-512),由美国国家安全局(NSA)所设计,并由美国国家标准与技术研究院(NIST)发布,是美国的政府标准。
  • SHA-1在许多安全协定中广为使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5的后继者,基于MD5,加密后的数据长度更长,它对长度小于264的输入,产生长度为160bit的散列值。比MD5多32位,因此,比MD5更加安全,但SHA1的运算速度就比MD5要慢。

SHA与MD5的不同:

  • 对强行攻击的安全性,SHA-1摘要比MD5摘长,对强行攻击有更大的强度。
  • 对密码分析的安全性,由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
  • 在相同的硬件上,SHA-1的运行速度比MD5慢。
3.2 代码实现

# md5和sha1 同一个包,均为不可逆算法,所以写法上基本一致;
import hashlib
tmp = "test message:四叔的旅途"
tmp_text = hashlib.sha1(tmp.encode("utf-8")).hexdigest()
print("sha1加密前为 :",tmp)
print("sha1加密前后 :",tmp_text)

4. AES 算法

高级加密标准(Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法。速度快,编码紧凑
AES技术是一种对称的分组加密技术,使用128位分组加密数据,提供比WEP/TKIPS的RC4算法更高的加密强度,其加密码表和解密码表是分开的,并且支持子密钥加密,这种做法优于以前用一个特殊的密钥解密的做法。
AES算法优点:

  • 强安全性、高性能、高效率、易用和灵活
  • 其独特并行性可以有效地利用处理器资源
  • 应用范围广、等待时间短、相对容易隐藏、吞吐量高等优点,在性能等各方面都优于WEP算法。
    AES算法缺点:
  • 对硬件要求比较高,因此无法通过在原有设备上升级固件实现,必须重新设计芯片
    AES加密算法作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。
    AES设计有三个密钥长度:128,192,256 位。
    相对而言,AES的128密钥比DES的56密钥强了1021倍
4.1 原理

加密方和解密方保有同一个16位长的密钥,使用AES算法加解密时需要传入该密钥参数,通过Java实现AES算法提供的工具包加密后返回的是一个Base64格式的字节数组,因此为保证密文“可读性”,需要在加密后对密文进行Base64编码,解密前进行Base64解码成密文。
AES算法的安全性,取决于密钥的安全性。因此一定不要在加解密的URL中传入该密钥参数,不然没有意义。一般的做法是:前后端协商好密钥,或者通过不对称加密的方式传递密钥。

4.2 实现方法

AES本质上是一个基本算法,实现AES有5种模式:ECB、CBC、CFB和OFB、CTR,最常用的是ECB 和 CBC 模式。

  • ECB模式(电子密码本模式:Electronic codebook)
    最简单的块密码加密模式,加密前根据加密块大小(如AES为128位)分成若干块,之后将每块使用相同的密钥单独加密,解密同理。

  • CBC模式(密码分组链接:Cipher-block chaining)
    对于每个待加密的密码块在加密前会先与前一个密码块的密文异或然后再用加密器加密。第一个明文块与一个叫初始化向量的数据块异或。

  • CFB模式(密文反馈:Cipher feedback)
    与ECB和CBC模式只能够加密块数据不同,CFB能够将块密文(Block Cipher)转换为流密文(Stream Cipher)。

  • OFB模式(输出反馈:Output feedback)
    OFB是先用块加密器生成密钥流(Keystream),然后再将密钥流与明文流异或得到密文流,解密是先用块加密器生成密钥流,再将密钥流与密文流异或得到明文,由于异或操作的对称性所以加密和解密的流程是完全一样的。

4.3 AES代码实现

这里代码实现的坑有点多,务必注意几个事项:

4.3.1 AES加密的几个参数
  • 秘钥:加解密的秘钥,必须是16 or 24 or 32bits(因为python3的字符串是unicode编码,需要 encode才可以转换成字节型数据),这里采坑很多
  • 明文:需加密的参数,字节长度需要是16位的倍数
  • 模式:5种,常用的是 ECB 和 CBC
  • iv偏移量:这个参数在 ECB 不需要,CBC 需要
"""
ECB模式,不需要iv偏移量参数 
"""

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

# 16bits 不足的空格补16的倍数  不写这个会采坑  
def add_to_16(text):
    if len(text.encode('utf-8')) % 16:
        add = 16 - (len(text.encode('utf-8')) % 16)
    else:
        add = 0
    text = text + ('\\0' * add)
    return text.encode('utf-8')
 
# 加密函数 
def enCrypt(text):
    key = '1234567891234567'.encode('utf-8')  # 需16bits
    mode = AES.MODE_ECB           # 模式确认
    text = add_to_16(text) 
    cryptos = AES.new(key, mode)  # 加密操作

    cipher_text = cryptos.encrypt(text)   # 密文
    return b2a_hex(cipher_text)

# 解密后,用strip()去掉补足的空格,不去解密后结果不一致 
def deCrypt(text):
    key = '1234567891234567'.encode('utf-8')   # 加解密需同一个
    mode = AES.MODE_ECB                        # 同一个key需同一个模式解
    cryptor = AES.new(key, mode)               
    plain_text = cryptor.decrypt(a2b_hex(text))  # 解密后原文,因为AES加密时候得到的字符串不一定是ascii字符集的,输出or保存时候可能报错,所以这里统一把加密后的字符串转化为16进制字符串
    return bytes.decode(plain_text).rstrip('\\0') 

if __name__ == '__main__':
    jia_m = enCrypt("test message:四叔的旅途")  # 加密
    jie_m = deCrypt(jia_m)                    # 解密
    print("原文加密:", jia_m)
    print("密文解密:", jie_m)
    
"""
原文加密: b'c554fb642755944d9b890f90bcbc37d0ca26f34cf3fb7cbf1d446ba75148b4ea'
密文解密: test message:四叔的旅途
"""


"""
CBC模式,参数要齐 + iv偏移量参数 
在参数前添加b来转换类型的原因:数据加密方法 接受byte类型,否则会报错,前文md5中updata有提;
"""
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

# 16bits 不足的空格补16的倍数  不写这个会采坑  
def add_to_16(text):
    if len(text.encode('utf-8')) % 16:
        add = 16 - (len(text.encode('utf-8')) % 16)
    else:
        add = 0
    text = text + ('\\0' * add)
    return text.encode('utf-8')

# 加密函数
def enCrypt(text):
    key = '1234567891234567'.encode('utf-8')   # 同样16bits
    mode = AES.MODE_CBC
    iv = b'abcdefghijklmnop'             # 偏移量,参见前文加b原因
    text = add_to_16(text)               # 文本补足16bits
    cryptos = AES.new(key, mode, iv)  
    cipher_text = cryptos.encrypt(text)  # 解密后原文,因为AES加密时候得到的字符串不一定是ascii字符集的,输出or保存时候可能报错,所以这里统一把加密后的字符串转化为16进制字符串
    return b2a_hex(cipher_text) 

# 解密后,用strip()去掉补足的空格 
def deCrypt(text):
    key = '1234567891234567'.encode('utf-8')
    iv = b'abcdefghijklmnop'                       
    mode = AES.MODE_CBC                             # 同一个key需同一个模式解
    cryptos = AES.new(key, mode, iv)
    clear_text = cryptos.decrypt(a2b_hex(text))     # 解密后原文
    return bytes.decode(clear_text).rstrip('\\0')    

if __name__ == '__main__':
    jia_m = enCrypt("test message:四叔的旅途")  # 加密
    jie_m = deCrypt(jia_m)          # 解密
    print("原文加密:", jia_m)
    print("密文解密:", jie_m)
    
"""
原文加密: b'c07638565f2944ae4db4366d361f4af42b65fed9f4df0589e20461e5f5618814'
密文解密: test message:四叔的旅途
"""

5. DES/3DES 算法

DES算法:密码体制中的对称密码体制,又被称为美国数据加密标准,是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。

5.1 加密原理

DES加密过程:
接收一个明文盒一个64位的密钥key,明文字符串会被转换为对各64位的块,加密过程以块位单位,经过初态转换,16轮循环加密,终态转换,最终每个64位的块都会被加密成一个64位的密文块,将得到的密文块拼起来,得到的就是最终加密后的结果。
具体算法流程图如下 : orz…看了n遍才看懂…

5.2 代码实现
"""
查了好多资料,DES 有比较成熟的包,不搞一堆循环加密的代码...
"""
# pip install pyDes
from pyDes import des, CBC, PAD_PKCS5
import binascii

# 秘钥 真的是采坑不断....
# 在使用pyDes实现DES加密时,初始化des是必须要8位密码的,超过8位报错常见于使用Python实现javascript的场景中,从JavaScript获取的密钥有时不止8位... MD..Python问题...
# 解决办法:可通过使用一个随意的8位密钥先初始化des对象,然后调用setkey()方法传入超过8位的密钥重置
# from pyDes import des, PAD_PKCS5
# import base64
# encry = des("0" * 8)
# encry.setKey("123456789")   # 可设置超过8bits
# result = encry.encrypt("密文".encode(), padmode=PAD_PKCS5)
# base = base64.b64encode(result).decode()
# print '2xC7EUPxQY4='

key = 'lz@lzljn'  

def enCrypt(s):
    """
    DES 加密
    :param s: 原始字符串
    :return: 加密后字符串,16进制
    """
    iv = key  # 偏移
    # secret_key:加密密钥,CBC:加密模式,iv:偏移, padmode:填充
    des_obj = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    # 返回为字节
    secret_bytes = des_obj.encrypt(s, padmode=PAD_PKCS5)
    # 返回为16进制
    return binascii.b2a_hex(secret_bytes)

def deCrypt(s):
    """
    DE 解密
    :param s: 加密后的字符串,16进制
    :return:  解密后的字符串
    """
    iv = key
    des_obj = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    decrypt_str = des_obj.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
    return decrypt_str

print("原文加密:",enCrypt("iloveullllz"))
print("密文解密:",deCrypt("3b0754717de0a05d7cb6ae88125c09d5"))

"""
b'3b0754717de0a05d7cb6ae88125c09d5'
b'iloveullllz'
"""

5.3 3DES

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称,是DES向AES过渡的加密算法,此处不做详细介绍了,基本和上面一致。

6. RSA 算法

RSA加密算法:一种非对称加密算法, 使用openssl ,keytools等工具生成一对公私钥对,使用被公钥加密的数据可以使用私钥来解密。

1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。用他们三个人的名字命名叫RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。

RSA算法非常可靠,密钥越长,越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。即长度超过768位的密钥,还无法破解(至少没人公开宣布),因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。

6.1 原理
6.1.1 数学基础

基于一个数论事实:将两个大质数p,q相乘,对其乘积n = p*q进行因式分解极其困难,因此可以将乘积n 进制化后公开作为加密密钥,密钥一般1024位起。

6.1.2 欧拉函数

欧拉函数φ(n):任意给定正整数n,请问在小于等于n的正整数之中,计算有多少个与n构成互质关系的方法(比如,在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = (p-1)*(q-1) = 4)

6.1.3 参数原理

RSA的公钥、私钥的组成,以及加密、解密的公式可见于下表:

模块名解密公式
公钥KUn: 两素数p和q的乘积 – e: 与(p-1)(q-1)互质,1<e<(p-1)(q-1)
私钥KRd: d ≡e-1 mod f(n) – n: 两素数p和q的乘积
加密C ≡ m^e mod n
解密m ≡ C^e mod n

注:≡ 恒等号一般用于一些参变量恒为一个常数或恒定表达式时,总等于关系与变量无关。例 f(x)≡k 表示该函数的值始终为k而与x的值无关.

6.1.4 算法过程

公钥与私钥的生成:

  • 随机挑选两个大素数 p 和 q,构造两数的乘积 n = p*q ,将n二进制后即为密钥 ;
  • 计算欧拉函数 φ(n) = (p-1) * (q-1) ;
  • 随机挑选e (e = 65537原因点击此处),条件是1< e < φ(n),即 e 与 φ(n) 互质 ( gcd(e, φ(n)) = 1 );
  • 计算e对于φ(n)的模反元素d,使得 e*d ≡ 1 (mod φ(N)),即扩展欧几里得算法
    ed - 1 = kφ(n) (k∈Z) --> ed + φ(n)k = 1 --> e,φ(n)已知,得出一个d
  • 得到了n,e,d ,则公钥为(n,e)可公开,私钥为(n,d)自主保管。

加密信息:

  • 待加密信息(明文)为 m,m < n;(因为要做模运算,若m大于n,则后面的运算不会成立,因此当信息比n要大时,应该分块加密)
  • 密文C = me mod n
  • 解密Cd mod n = me*d mod n ;

6.2 代码实现

6.2.1 现成包可用

import rsa   # 现成的包可用

# rsa 加密 
def rsaEncrypt(clear_text): 
    (pubkey, prikey) = rsa.newkeys(512)    # 生成公钥、私钥,()随机数
    # key = rsa.newkeys(1000)
    # key[0] = pubkey key[1] = prikey 
    print("rsa加密公钥: ", pubkey)  
    print("rsa加密私钥: ", prikey) 
    
    clear_text = clear_text.encode('utf-8')           # 明文编码格式 
    cipher_text = rsa.encrypt(clear_text, pubkey)     # 明文通过公钥加密生成密文
    return (cipher_text, prikey)                      # 传回密文,prikey 私钥 

# rsa 解密 
def rsaDecrypt(cipher_text, prikey):  
    clear_text = rsa.decrypt(cipher_text, prikey)    # 密文通过私钥解密
    clear_text = clear_text.decode('utf-8')          # 明文编码
    return clear_text                                # 传回明文 

(a, b) = rsaEncrypt("test message:四叔的旅途")
print('加密后密文:',a)
print('私钥:',b)

clear_text = rsaDecrypt(a, b)
print('解密后明文:',clear_text) 

"""
rsa公钥:  PublicKey(10663336662571050099297238857296617461672702659070145995594813556835299127631313673297344714201089161781272686456843997221628596317501872676983803305119951, 65537)
rsa私钥:  PrivateKey(10663336662571050099297238857296617461672702659070145995594813556835299127631313673297344714201089161781272686456843997221628596317501872676983803305119951, 65537, 9674890895674195965705058469758632032378385423709187500039043650404207642663541372623922368423209614653394571329100027988392186373717565032205852814673473, 7567398718848405743192951986927239943286617179940639622213395272396044025056814751, 1409115213661396592372119588194019684418400115364502684174591606711605201)

"""

6.2.2 原理代码实现(即6.1.4算法过程)

"""
RSA算法的核心代码分为3个部分:计算最大公约数、大整数幂取模算法、公钥私钥生成及加解密。
"""
# -*- coding: utf-8 -*-
# 求两个数字的最大公约数 即欧几里得算法gcd 百度说明:https://baike.baidu.com/item/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95/1647675?fr=aladdin

###########################################
# Part_1: 获取a,b的最大公约数 
def gcd(a, b):
    while a != 0:
        a, b = b % a, a
    return b

# 扩展欧几里得算法 作用:得到ax+by=gcd(a,b)的解 
def ext_gcd(a, b):     
    if b == 0:         
        return 1, 0, a     
    else:         
        x, y, q = ext_gcd(b, a % b)    # 递归直至余数等于0(需多递归一层用来判断)       
        # q = gcd(a, b) = gcd(b, a%b)         
        x, y = y, (x - (a // b) * y)   # 欧几里得算法反向推导每层a、b的因子使得gcd(a,b)=ax+by成立          
        return x, y, q

###########################################
# Part_2: 大整数幂取模算法
# -*- coding: utf-8 -*-
def exp_mode(base, exponent, n):
    bin_array = bin(exponent)[2:][::-1]
    r = len(bin_array)
    base_array = []
    
    pre_base = base
    base_array.append(pre_base)
    
    for _ in range(r - 1):
        next_base = (pre_base * pre_base) % n 
        base_array.append(next_base)
        pre_base = next_base
        
    a_w_b = __multi(base_array, bin_array, n)
    return a_w_b % n

def __multi(array, bin_array, n):
    result = 1
    for index in range(len(array)):
        a = array[index]
        if not int(bin_array[index]):
            continue
        result *= a
        result = result % n # 加快连乘的速度
    return result


###########################################
# Part_3: 公钥私钥生成
from gcd import ext_gcd
from exponentiation import exp_mode

# 公钥与私钥 生产的步骤 
def rsaKey(p, q):
    n = p * q                  # 选取2个质数,n = p * q φ(n) = (p-1) * (q-1)。
    f = (p - 1) * (q - 1)      # φ(n) = (p-1) * (q-1)。
    e = 65537                 
    k, d, y = ext_gcd(e, f)     # ed + φ(n)k = 1  y最大公约数 
    if d < 0:                   # 因为 e*d ≡ 1 (mod φ(N)) 所以d>0 
        d = d + f 
    return (n, e), (n, d)    
    
# rsa 加密 
def enCrypt(clear_text, pubkey):
        n = pubkey[0]
        e = pubkey[1]
        cipher_text = exp_mode(clear_text, e, n)
        return c
# rsa 解密
def decCrypt(cipher_text, selfkey):
        n = selfkey[0]
        d = selfkey[1]
        clear_text = exp_mode(cipher_text机器学习笔记关于python实现Kmean算法

面试高级算法梳理笔记

python基础整理笔记

python实现base64算法加密

python笔记梳理

80分求DES加密解密算法实现的PHP源代码