教学服务系统

用户名  找回密码
 立即注册
帖子
查看: 620|回复: 2

信息计算2019级1班19号谭斌斌

[复制链接]

9

主题

16

帖子

75

积分

注册会员

Rank: 2

积分
75
发表于 2022-5-2 17:20:09 | 显示全部楼层 |阅读模式
本帖最后由 谭斌斌 于 2022-5-2 17:21 编辑

大数RSA算法的实现


一、源码

工具类代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace Security_Test3
  7. {
  8.     class RSATools
  9.     {
  10.         public static bool isPrim(long num)

  11.         {

  12.             if (num == 2 || num == 3)
  13.                 return true;

  14.             if (num % 6 != 1 && num % 6 != 5)
  15.                 return false;
  16.             long tmp = (long)Math.Sqrt(num);

  17.             for (long i = 5; i <= tmp; i += 6)
  18.                 if (num % i == 0 || num % (i + 2) == 0)
  19.                     return false;

  20.             return true;
  21.         }
  22.         public static long gcd(long x, long y) => y != 0 ? gcd(y, x % y) : x;

  23.         public static long inverse(long number1, long number3)

  24.         {
  25.             long x1 = 1, x2 = 0, x3 = number3, y1 = 0, y2 = 1, y3 = number1;
  26.             long q;
  27.             long number4 = 0;
  28.             long t1, t2, t3;
  29.             while (y3 != 0)
  30.             {
  31.                 if (y3 == 1)
  32.                 {
  33.                     number4 = y2;
  34.                     break;
  35.                 }
  36.                 else
  37.                 {
  38.                     q = (x3 / y3);
  39.                     t1 = x1 - q * y1;
  40.                     t2 = x2 - q * y2;
  41.                     t3 = x3 - q * y3;
  42.                     x1 = y1; x2 = y2; x3 = y3;
  43.                     y1 = t1; y2 = t2; y3 = t3;
  44.                 }
  45.             }
  46.             if (number4 < 0)
  47.                 number4 = number4 + number3;
  48.             return number4;
  49.         }
  50.         public static long getMod(long a, long b, long c)
  51.         //利用快速指数模运算,计算m^e mod n
  52.         {

  53.             long number3 = 1;
  54.             while (a != 0)
  55.             {
  56.                 if (a % 2 == 1)
  57.                 {
  58.                     a = a - 1;
  59.                     number3 = (number3 * b) % c;
  60.                 }
  61.                 else
  62.                 {
  63.                     a = (a / 2);
  64.                     b = (b * b) % c;
  65.                 }
  66.             }
  67.             return number3;

  68.         }

  69.         public static long getN(long p, long q) => p * q;
  70.         public static long getEuler_N(long p, long q) => (p - 1) * (q - 1);

  71.         public static void getP_Q(out long p, out long q)
  72.         {
  73.             Random random = new Random();
  74.             while (true)
  75.             {
  76.                 p = random.Next(1000);
  77.                 q = random.Next(2000);
  78.                 if (isPrim(p) && isPrim(q)) return;
  79.             }
  80.         }

  81.         public static byte[] longToBytes(long a)
  82.         {
  83.             byte[] b = new byte[8];
  84.             b[0] = (byte)(a);
  85.             b[1] = (byte)(a >> 8 & 0xFF);
  86.             b[2] = (byte)(a >> 16 & 0xFF);
  87.             b[3] = (byte)(a >> 24 & 0xFF);
  88.             b[4] = (byte)(a >> 32 & 0xFF);
  89.             b[5] = (byte)(a >> 40 & 0xFF);
  90.             b[6] = (byte)(a >> 48 & 0xFF);
  91.             b[7] = (byte)(a >> 56 & 0xFF);
  92.             return b;
  93.         }
  94.         public static long BytesToLong(byte[] input)
  95.         {
  96.             uint num = (uint)(((input[0] | (input[1] << 8)) | (input[2] << 0x10)) | (input[3] << 0x18));
  97.             uint num2 = (uint)(((input[4] | (input[5] << 8)) | (input[6] << 0x10)) | (input[7] << 0x18));
  98.             return (long)((num2 << 0x20) | num);
  99.         }

  100.         public static long[] UTF8ToLong(string input)
  101.         {
  102.             string input_64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
  103.             byte[] inputByte = Convert.FromBase64String(input_64);
  104.             long[] inputLong = new long[inputByte.Length];
  105.             for (int i = 0; i < inputByte.Length; i++)
  106.             {
  107.                 inputLong[i] = (long)inputByte[i];
  108.             }
  109.             return inputLong;
  110.         }
  111.         public static string longToUTF8(long[] input)
  112.         {
  113.             byte[] inputByte = new byte[input.Length];
  114.             for (int i = 0; i < inputByte.Length; i++)
  115.             {
  116.                 inputByte[i] = (byte)input[i];
  117.             }
  118.             string inputBase64 = Convert.ToBase64String(inputByte);
  119.             byte[] outputb = Convert.FromBase64String(inputBase64);
  120.             string output = Encoding.UTF8.GetString(outputb);
  121.             return output;
  122.         }
  123.         public static long[] Base64ToLong(string input)
  124.         {
  125.             List<long> output_l = new List<long>();
  126.             string t = "";
  127.             for (int i = 0; i < input.Length; i++)
  128.             {
  129.                 t += input[i];
  130.                 if (input[i] == '=')
  131.                 {
  132.                     byte[] tByte = Convert.FromBase64String(t);
  133.                     output_l.Add(BytesToLong(tByte));
  134.                     t = "";
  135.                 }
  136.             }
  137.             return output_l.ToArray(); ;
  138.         }
  139.         public static string longToBase64(long[] input)
  140.         {
  141.             byte[][] inputByte = new byte[input.Length][];
  142.             string output = "";
  143.             for (int i = 0; i < input.Length; i++)
  144.             {
  145.                 inputByte[i] = longToBytes(input[i]);
  146.                 output += Convert.ToBase64String(inputByte[i]);
  147.             }
  148.             return output;
  149.         }
  150.     }
  151. }
复制代码
RSA算法代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace Security_Test3
  7. {
  8.         class RSA
  9.         {
  10.             private long p, q;
  11.             private long n;
  12.             private long euler_N;
  13.             private long[] publicKey;//0-e 1-n
  14.             private long[] privateKey;//0-d 1-n

  15.             public long P { get => p; set => p = value; }
  16.             public long Q { get => q; set => q = value; }
  17.             public long[] PublicKey { get => publicKey; set => publicKey = value; }
  18.             public long[] PrivateKey { get => privateKey; set => privateKey = value; }
  19.             public long N { get => n; set => n = value; }
  20.             public long Euler_N { get => euler_N; set => euler_N = value; }

  21.             public void InitPublicKey()
  22.             //初始化公钥
  23.             {
  24.                 RSATools.getP_Q(out p, out q);
  25.                 euler_N = RSATools.getEuler_N(p, q);
  26.                 long e;
  27.                 n = RSATools.getN(p, q);

  28.                 Random radom = new Random();
  29.                 while (true)
  30.                 {
  31.                     e = radom.Next(655300);
  32.                     if (e > 1 && e < euler_N && RSATools.gcd(e, euler_N) == 1 && RSATools.isPrim(e)) break;
  33.                 }

  34.                 publicKey = new long[2];
  35.                 publicKey[0] = e;
  36.                 publicKey[1] = n;
  37.             }
  38.             public void InitPrivateKey()
  39.             //初始化私钥
  40.             {
  41.                 long d = RSATools.inverse(publicKey[0], euler_N);
  42.                 privateKey = new long[2];
  43.                 privateKey[0] = d;
  44.                 privateKey[1] = n;
  45.             }

  46.             //加密操作
  47.             public long encrypt(long plaintext, long[] p_k) => RSATools.getMod(p_k[0], plaintext, p_k[1]);
  48.             //解密操作
  49.             public long decrypt(long ciphertext) => RSATools.getMod(privateKey[0], ciphertext, privateKey[1]);

  50.             public string getCiphertext(string plaintext, long[] p_k)
  51.             //加密明文得到密文
  52.             {
  53.                 long[] p_long = RSATools.UTF8ToLong(plaintext);
  54.                 long[] c_long = new long[p_long.Length];
  55.                 for (int i = 0; i < p_long.Length; i++)
  56.                 {
  57.                     c_long[i] = encrypt(p_long[i], p_k);
  58.                 }
  59.                 string c_text = RSATools.longToBase64(c_long);
  60.                 return c_text;
  61.             }
  62.             public string getPlaintext(string ciphertext)
  63.             //解密密文得到明文
  64.             {
  65.                 long[] c_long = RSATools.Base64ToLong(ciphertext);
  66.                 long[] p_long = new long[c_long.Length];
  67.                 for (int i = 0; i < c_long.Length; i++)
  68.                 {
  69.                     p_long[i] = decrypt(c_long[i]);
  70.                 }
  71.                 string p_text = RSATools.longToUTF8(p_long);
  72.                 return p_text;
  73.             }
  74.         }
  75.     }

复制代码
主函数代码:

  1. using System;

  2. namespace Security_Test3
  3. {
  4.     class Program
  5.     {
  6.         static void Main(string[] args)
  7.         {
  8.             RSA a = new RSA();
  9.             a.InitPublicKey();
  10.             a.InitPrivateKey();
  11.             string p = a.P.ToString();
  12.             string q = a.Q.ToString();
  13.             string publickey = a.PublicKey[0].ToString() + "-" + a.PublicKey[1].ToString();


  14.             Console.WriteLine("明文为:");
  15.             string plaintext = "于是二子愀然改容,超若自失,逡巡避席,曰:“鄙人固陋,不知忌讳,乃今日见教,谨受命矣。”";
  16.             Console.WriteLine(plaintext);
  17.             Console.WriteLine();

  18.             //Console.WriteLine("p:"+p+";q:"+q);

  19.             Console.Write("公钥为:");
  20.             Console.WriteLine(publickey);
  21.             Console.WriteLine();

  22.             Console.WriteLine("密文为:");
  23.             string ciphertext = a.getCiphertext(plaintext, a.PublicKey);
  24.             Console.WriteLine(ciphertext);
  25.             Console.WriteLine();

  26.             Console.WriteLine("解密后的明文为:");
  27.             string decryptedtext = a.getPlaintext(ciphertext);
  28.             Console.WriteLine(decryptedtext);
  29.         }
  30.     }
  31. }
复制代码


回复

举报

9

主题

16

帖子

75

积分

注册会员

Rank: 2

积分
75
 楼主| 发表于 2022-5-2 17:20:53 | 显示全部楼层
二、运行截图

本帖子中包含更多资源

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

x
回复

举报

9

主题

16

帖子

75

积分

注册会员

Rank: 2

积分
75
 楼主| 发表于 2022-6-3 00:16:08 | 显示全部楼层
ECC源码:


  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 != False):
  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()
复制代码


回复

举报

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

本版积分规则

教学服务系统

GMT+8, 2025-5-17 23:54 , Processed in 0.016440 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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