教学服务系统

 找回密码
 立即注册
搜索
查看: 590|回复: 1

信息计算2019级2班32号王诗琪

[复制链接]

8

主题

16

帖子

114

积分

注册会员

Rank: 2

积分
114
发表于 2022-5-31 15:15:07 | 显示全部楼层 |阅读模式
本帖最后由 王诗琪 于 2022-5-31 16:09 编辑

RSA加解密和签名
环境:PyCharm3.7.9
1.RSA算法简介
​    RSA加密算法是一种非对称加密算法,加密的秘钥是由公钥和私钥两部分组成秘钥对,公钥用来加密消息,私钥用来对消息进行解密。公钥是公开的,私钥则由用户自己保留。由于公钥是公开的,那么任何人只要获取到公钥,都可以使用公钥来加密发送伪造内容,出于安全性考虑,在发送消息之前我们可以使用RSA来签名。签名使用私钥来进行签名,使用公钥来进行验签。通过签名我们可以确保用户身份的唯一性,从而提高安全性。

2.生成私钥和公钥
  1. # 生成public.pem(公钥)和private.pem(私钥)
  2. def generateKeys():
  3.     print("1.开始生成私钥和公钥.")
  4.     # 伪随机数生成器
  5.     random_generator = Random.new().read
  6.     # 生成秘钥对实例对象:2048是秘钥的长度
  7.     rsa = RSA.generate(2048, random_generator)
  8.     # 获取公钥,保存到文件
  9.     private_pem = rsa.exportKey()
  10.     with open('private.pem', 'wb') as f:
  11.         f.write(private_pem)
  12.     # 获取私钥,保存到文件
  13.     public_pem = rsa.publickey().exportKey()
  14.     with open('public.pem', 'wb') as f:
  15.         f.write(public_pem)
  16.     print("2.生成成功.")
  17.     print("----------------------------------")
复制代码

3.加密与解密

  1. # 用公钥加密,然后用私钥解密
  2. def pubEncryAndprivDecry(content_size):
  3.     # 公钥加密
  4.     with open("public.pem") as f:
  5.         # 读取文件中的公钥
  6.         key = f.read()
  7.         rsakey = RSA.importKey(key)
  8.         # 进行加密
  9.         cipher = Cipher_pkcs1_v1_5.new(rsakey)
  10.         cipher_text = base64.b64encode(cipher.encrypt(content_size.encode()))
  11.         print('3.加密结果:'+cipher_text.decode())
  12.     with open("encrypted_data", "wb") as f:
  13.         f.write(cipher_text)

  14.     # 私钥解密
  15.     with open("private.pem") as f:
  16.         key = f.read()
  17.         prikey = RSA.importKey(key)
  18.         cipher2 = Cipher_pkcs1_v1_5.new(prikey)
  19.         with open("encrypted_data") as f:
  20.             data = f.read()
  21.             text = cipher2.decrypt(base64.b64decode(data), 'DecryptError')
  22.             print('4.解密结果:'+text.decode())
复制代码

4.签名和验签

  1. # 私钥进行签名,然后用公钥去验证签名
  2. def privSignAndPubAttesation(content_size):
  3.     # 私钥签名
  4.     with open("private.pem") as f:
  5.         key = f.read()
  6.         rsakey = RSA.importKey(key)
  7.         signer = Signature_pkcs1_v1_5.new(rsakey)
  8.         digest = SHA.new(content_size.encode())
  9.         sign_data = signer.sign(digest)
  10.         signature = base64.b64encode(sign_data)
  11.         print('5.签名结果:'+signature.decode())

  12.     # 公钥验证
  13.     with open("public.pem") as f:
  14.         key = f.read()
  15.         rsakey = RSA.importKey(key)
  16.         verifier = Signature_pkcs1_v1_5.new(rsakey)
  17.         digest = SHA.new(content_size.encode())
  18.         is_matched = verifier.verify(digest, base64.b64decode(signature))
  19.         print('6.验签结果:'+str(is_matched))
复制代码

5.完整代码

  1. import base64
  2. from Crypto import Random
  3. from Crypto.Hash import SHA
  4. from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
  5. from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
  6. from Crypto.PublicKey import RSA


  7. # 生成public.pem(公钥)和private.pem(私钥)
  8. def generateKeys():
  9.     print("1.开始生成私钥和公钥.")
  10.     # 伪随机数生成器
  11.     random_generator = Random.new().read
  12.     # 生成秘钥对实例对象:2048是秘钥的长度
  13.     rsa = RSA.generate(2048, random_generator)
  14.     # 获取公钥,保存到文件
  15.     private_pem = rsa.exportKey()
  16.     with open('private.pem', 'wb') as f:
  17.         f.write(private_pem)
  18.     # 获取私钥,保存到文件
  19.     public_pem = rsa.publickey().exportKey()
  20.     with open('public.pem', 'wb') as f:
  21.         f.write(public_pem)
  22.     print("2.生成成功.")
  23.     print("----------------------------------")


  24. # 用公钥加密,然后用私钥解密
  25. def pubEncryAndprivDecry(content_size):
  26.     # 公钥加密
  27.     with open("public.pem") as f:
  28.         # 读取文件中的公钥
  29.         key = f.read()
  30.         rsakey = RSA.importKey(key)
  31.         # 进行加密
  32.         cipher = Cipher_pkcs1_v1_5.new(rsakey)
  33.         cipher_text = base64.b64encode(cipher.encrypt(content_size.encode()))
  34.         print('3.加密结果:'+cipher_text.decode())
  35.     with open("encrypted_data", "wb") as f:
  36.         f.write(cipher_text)

  37.     # 私钥解密
  38.     with open("private.pem") as f:
  39.         key = f.read()
  40.         prikey = RSA.importKey(key)
  41.         cipher2 = Cipher_pkcs1_v1_5.new(prikey)

  42.         with open("encrypted_data") as f:
  43.             data = f.read()
  44.             text = cipher2.decrypt(base64.b64decode(data), 'DecryptError')
  45.             print('4.解密结果:'+text.decode())


  46. # 私钥进行签名,然后用公钥去验证签名
  47. def privSignAndPubAttesation(content_size):
  48.     # 私钥签名
  49.     with open("private.pem") as f:
  50.         key = f.read()
  51.         rsakey = RSA.importKey(key)
  52.         signer = Signature_pkcs1_v1_5.new(rsakey)
  53.         digest = SHA.new(content_size.encode())
  54.         sign_data = signer.sign(digest)
  55.         signature = base64.b64encode(sign_data)
  56.         print('5.签名结果:'+signature.decode())

  57.     # 公钥验证
  58.     with open("public.pem") as f:
  59.         key = f.read()
  60.         rsakey = RSA.importKey(key)
  61.         verifier = Signature_pkcs1_v1_5.new(rsakey)
  62.         digest = SHA.new(content_size.encode())
  63.         is_matched = verifier.verify(digest, base64.b64decode(signature))
  64.         print('6.验签结果:'+str(is_matched))


  65. def main(content_size):
  66.     # 生成公钥、私钥
  67.     generateKeys()
  68.     # 1. 加密和解密
  69.     pubEncryAndprivDecry(content_size)
  70.     # 2. 签名和验签
  71.     privSignAndPubAttesation(content_size)
  72.     return 0

  73. if __name__ == '__main__':
  74.     print('请输入要加密的内容:')
  75.     content_size = input()
  76.     main(content_size)
复制代码

6.运行结果
















本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

8

主题

16

帖子

114

积分

注册会员

Rank: 2

积分
114
 楼主| 发表于 2022-5-31 16:08:44 | 显示全部楼层
椭圆加密算法(ECC加密)

1.原理
首先要知道什么是椭圆曲线:一条椭圆曲线就是一组被y^2=x^3+ax+b定义的且满足4a^3+27b^2≠0的点集.
椭圆曲线乘法很简单,除法却很难.其具体来说就是,给定k和G,那么便很容易计算 K=kG (K和G都是椭圆曲线EP(a,b)上的点,k小于点G的阶n).反之知道K和G,我们很难算出k,这就是一个ECC可以利用的难题.其中G被称为基点.
获得公私钥对方式:
1.随机选择一条椭圆曲线EP(a,b),并随机取其中一点G作为基点.
2.随机生成一个k和椭圆曲线EP(a,b)一起编码生成私钥.
3.计算K=kG ,和椭圆曲线EP(a,b)以及基点G一起编码生成公钥.
加密方式:
公钥有K,G和EP(a,b),设要加密的消息为符号message,加密过程:
1.解码m=decodem(message) ,由于无论什么样的文本在计算机中都是以字节串的形式保存的,而字节实际又是二进制数,所以可以认为message可以转换为一个二进制数,设其符号为m.
2.加密前我们需要将m编码到EP(a,b)上的一点M=Embeding(m,EP(a,b)),同时产生一个随机整数r.
3.加密需要使用两个公式:
  C1=M+rK
  C2=rG
4.将C1和C2编码为完整密文C=encodec(C1,C2).
解密方式:
有私钥k和EP(a,b),获得到密文C,要获取到明文.
1.C1,C2=decodec(C)解码密文为两段.
2.M=C1−kC2即C1−kC2=M+rK−k(rG)=M+rK−r(kG)=M获取信息在椭圆曲线上的对应点.
3.m=Searching(M,EP(a,b))通过嵌入找到椭圆曲线上对应点的信息.
4.message=encodem(m)编码信息为明文.
签名方式:
有私钥k和EP(a,b).
1.产生一个随机整数r,并使用明文嵌入的方式获得其在EP(a,b)上的点,记为R(x,y).x,y是R点的横纵坐标.
2.计算消息message和R点横纵坐标x和y的消息摘要,记为h(message,x,y).
3.计算签名 s=r−h(message,x,y)∗k 获得到签名信息s.
验签方式:
有公钥K,G和EP(a,b),同时要验的是h(message,x,y)和s.
1.计算 R^=s∗G+h(message,x,y)∗K获得点R(x^,y^)的坐标.
2.计算h(s,x^,y^),如果h(s,x^,y^)==h(message,x,y)则验签通过,否则验签不通过.


2.代码
  1. def get_inverse(mu, p):
  2.     """
  3.     获取y的负元
  4.     """
  5.     for i in range(1, p):
  6.         if (i * mu) % p == 1:
  7.             return i
  8.     return -1


  9. def get_gcd(zi, mu):
  10.     """
  11.     获取最大公约数
  12.     """
  13.     if mu:
  14.         return get_gcd(mu, zi % mu)
  15.     else:
  16.         return zi


  17. def get_np(x1, y1, x2, y2, a, p):
  18.     """
  19.     获取n*p,每次+p,直到求解阶数np=-p
  20.     """
  21.     flag = 1  # 定义符号位(+/-)
  22.     # 如果 p=q  k=(3x2+a)/2y1mod p
  23.     if x1 == x2 and y1 == y2:
  24.         zi = 3 * (x1 ** 2) + a  # 计算分子      【求导】
  25.         mu = 2 * y1  # 计算分母
  26.     # 若P≠Q,则k=(y2-y1)/(x2-x1) mod p
  27.     else:
  28.         zi = y2 - y1
  29.         mu = x2 - x1
  30.         if zi * mu < 0:
  31.             flag = 0  # 符号0为-(负数)
  32.             zi = abs(zi)
  33.             mu = abs(mu)
  34.     # 将分子和分母化为最简
  35.     gcd_value = get_gcd(zi, mu)  # 最大公約數
  36.     zi = zi // gcd_value  # 整除
  37.     mu = mu // gcd_value
  38.     # 求分母的逆元  逆元: ∀a ∈G ,ョb∈G 使得 ab = ba = e
  39.     # P(x,y)的负元是 (x,-y mod p)= (x,p-y) ,有P+(-P)= O∞
  40.     inverse_value = get_inverse(mu, p)
  41.     k = (zi * inverse_value)
  42.     if flag == 0:  # 斜率负数 flag==0
  43.         k = -k
  44.     k = k % p
  45.     # 计算x3,y3 P+Q
  46.     """
  47.         x3≡k2-x1-x2(mod p)
  48.         y3≡k(x1-x3)-y1(mod p)
  49.     """
  50.     x3 = (k ** 2 - x1 - x2) % p
  51.     y3 = (k * (x1 - x3) - y1) % p
  52.     return x3, y3


  53. def get_rank(x0, y0, a, b, p):
  54.     """
  55.     获取椭圆曲线的阶
  56.     """
  57.     x1 = x0  # -p的x坐标
  58.     y1 = (-1 * y0) % p  # -p的y坐标
  59.     tempX = x0
  60.     tempY = y0
  61.     n = 1
  62.     while True:
  63.         n += 1
  64.         # 求p+q的和,得到n*p,直到求出阶
  65.         p_x, p_y = get_np(tempX, tempY, x0, y0, a, p)
  66.         # 如果 == -p,那么阶数+1,返回
  67.         if p_x == x1 and p_y == y1:
  68.             return n + 1
  69.         tempX = p_x
  70.         tempY = p_y


  71. def get_param(x0, a, b, p):
  72.     """
  73.     计算p与-p
  74.     """
  75.     y0 = -1
  76.     for i in range(p):
  77.         # 满足取模约束条件,椭圆曲线Ep(a,b),p为质数,x,y∈[0,p-1]
  78.         if i ** 2 % p == (x0 ** 3 + a * x0 + b) % p:
  79.             y0 = i
  80.             break
  81.     # 如果y0没有,返回false
  82.     if y0 == -1:
  83.         return False
  84.     # 计算-y(负数取模)
  85.     x1 = x0
  86.     y1 = (-1 * y0) % p
  87.     return x0, y0, x1, y1


  88. def get_graph(a, b, p):
  89.     """
  90.     输出椭圆曲线散点图
  91.     """
  92.     x_y = []
  93.     # 初始化二维数组
  94.     for i in range(p):
  95.         x_y.append(['-' for i in range(p)])
  96.     for i in range(p):
  97.         val = get_param(i, a, b, p)  # 椭圆曲线上的点
  98.         if val:
  99.             x0, y0, x1, y1 = val
  100.             x_y[x0][y0] = 1
  101.             x_y[x1][y1] = 1
  102.     print("椭圆曲线的散列图为:")
  103.     for i in range(p):  # i= 0-> p-1
  104.         temp = p - 1 - i  # 倒序
  105.         # 格式化输出1/2位数,y坐标轴
  106.         if temp >= 10:
  107.             print(temp, end=" ")
  108.         else:
  109.             print(temp, end="  ")
  110.         # 输出具体坐标的值,一行
  111.         for j in range(p):
  112.             print(x_y[j][temp], end="  ")
  113.         print("")  # 换行
  114.     # 输出 x 坐标轴
  115.     print("   ", end="")
  116.     for i in range(p):
  117.         if i >= 10:
  118.             print(i, end=" ")
  119.         else:
  120.             print(i, end="  ")
  121.     print('\n')


  122. def get_ng(G_x, G_y, key, a, p):
  123.     """
  124.     计算nG
  125.     """
  126.     temp_x = G_x
  127.     temp_y = G_y
  128.     while key != 1:
  129.         temp_x, temp_y = get_np(temp_x, temp_y, G_x, G_y, a, p)
  130.         key -= 1
  131.     return temp_x, temp_y


  132. def ecc_main():
  133.     while True:
  134.         a = int(input("请输入椭圆曲线参数a(a>0)的值:"))
  135.         b = int(input("请输入椭圆曲线参数b(b>0)的值:"))
  136.         p = int(input("请输入椭圆曲线参数p(p为素数)的值:"))  # 用作模运算
  137.         # 条件满足判断
  138.         if (4 * (a ** 3) + 27 * (b ** 2)) % p == 0:
  139.             print("您输入的参数有误,请重新输入!!!\n")
  140.         else:
  141.             break
  142.     # 输出椭圆曲线散点图
  143.     get_graph(a, b, p)
  144.     # 选点作为G点
  145.     print("user1:在如上坐标系中选一个值为G的坐标")
  146.     G_x = int(input("user1:请输入选取的x坐标值:"))
  147.     G_y = int(input("user1:请输入选取的y坐标值:"))
  148.     # 获取椭圆曲线的阶
  149.     n = get_rank(G_x, G_y, a, b, p)
  150.     # user1生成私钥,小key
  151.     key = int(input("user1:请输入私钥小key(<{}):".format(n)))
  152.     # user1生成公钥,大KEY
  153.     KEY_x, kEY_y = get_ng(G_x, G_y, key, a, p)

  154.     # user2阶段
  155.     # user2拿到user1的公钥KEY,Ep(a,b)阶n,加密需要加密的明文数据
  156.     # 加密准备
  157.     k = int(input("user2:请输入一个整数k(<{})用于求kG和kQ:".format(n)))
  158.     k_G_x, k_G_y = get_ng(G_x, G_y, k, a, p)  # kG
  159.     k_Q_x, k_Q_y = get_ng(KEY_x, kEY_y, k, a, p)  # kQ
  160.     # 加密
  161.     plain_text = input("user2:请输入需要加密的字符串:")
  162.     plain_text = plain_text.strip()
  163.     # plain_text = int(input("user1:请输入需要加密的密文:"))
  164.     c = []
  165.     print("密文为:", end="")
  166.     for char in plain_text:
  167.         intchar = ord(char)
  168.         cipher_text = intchar * k_Q_x
  169.         c.append([k_G_x, k_G_y, cipher_text])
  170.         print("({},{}),{}".format(k_G_x, k_G_y, cipher_text), end="-")

  171.     # user1阶段
  172.     # 拿到user2加密的数据进行解密
  173.     # 知道 k_G_x,k_G_y,key情况下,求解k_Q_x,k_Q_y是容易的,然后plain_text = cipher_text/k_Q_x
  174.     print("\nuser1解密得到明文:", end="")
  175.     for charArr in c:
  176.         decrypto_text_x, decrypto_text_y = get_ng(charArr[0], charArr[1], key, a, p)
  177.         print(chr(charArr[2] // decrypto_text_x), end="")


  178. if __name__ == "__main__":
  179.     print("*************ECC椭圆曲线加密*************")
  180.     ecc_main()
复制代码


3.运行结果



















本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

教学服务系统

GMT+8, 2025-4-30 08:16 , Processed in 0.017707 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表