教学服务系统

 找回密码
 立即注册
搜索
查看: 636|回复: 3

信息计算2019级1班5号唐乐

[复制链接]

9

主题

22

帖子

98

积分

注册会员

Rank: 2

积分
98
发表于 2022-6-1 22:15:03 | 显示全部楼层 |阅读模式
本帖最后由 唐乐 于 2022-6-2 08:55 编辑

RSA加解密----大数加密
这里添加了外部依赖库boost库

一、源代码
1、RAS.h(结构体的定义和功能函数的声明)
  1. #pragma once
  2. #include <string>
  3. #include <vector>
  4. #include <boost/multiprecision/cpp_int.hpp>
  5. #include <boost/multiprecision/random.hpp>
  6. #include <boost/multiprecision/miller_rabin.hpp>
  7. namespace bm = boost::multiprecision;

  8. struct Key
  9. {
  10.         bm::int1024_t pkey;
  11.         //公钥(ekey, pkey): (e,n)
  12.         bm::int1024_t ekey;
  13.         //私钥(dkey, pkey): (d, n)
  14.         bm::int1024_t dkey;
  15. };

  16. class RSA
  17. {
  18. public:
  19.         RSA();

  20.         Key getKey()
  21.         {
  22.                 return _key;
  23.         }

  24.         void ecrept(const char* plain_file_in, const char* ecrept_file_out,
  25.                 bm::int1024_t ekey, bm::int1024_t pkey);//加密
  26.         void decrept(const char* ecrept_file_in, const char* plain_file_out,
  27.                 bm::int1024_t dkey, bm::int1024_t pkey);//解密

  28.         std::vector<bm::int1024_t> ecrept(std::string& str_in, bm::int1024_t ekey, bm::int1024_t pkey);//字符串加密
  29.         std::string decrept(std::vector<bm::int1024_t>& ecrept_str, bm::int1024_t dkey, bm::int1024_t pkey);//解密为字符串

  30.         void printInfo(std::vector<bm::int1024_t>& ecrept_str);//打印信息
  31. private:
  32.         bm::int1024_t ecrept(bm::int1024_t msg, bm::int1024_t key, bm::int1024_t pkey);//加密单个信息
  33.         bm::int1024_t produce_prime();//产生素数
  34.         bool is_prime(bm::int1024_t prime);//是否为素数
  35.         bool is_prime_bigInt(bm::int1024_t prime);
  36.         void produce_keys();
  37.         bm::int1024_t produce_pkey(bm::int1024_t prime1, bm::int1024_t prime2);//计算pq乘积n
  38.         bm::int1024_t produce_orla(bm::int1024_t prime1, bm::int1024_t prime2);//计算欧拉函数φ(n)
  39.         bm::int1024_t produce_ekey(bm::int1024_t orla);//产生e
  40.         bm::int1024_t produce_gcd(bm::int1024_t ekey, bm::int1024_t orla);//产生最大公约数
  41.         bm::int1024_t produce_dkey(bm::int1024_t ekey, bm::int1024_t orla);//产生d
  42.         bm::int1024_t exgcd(bm::int1024_t ekey, bm::int1024_t orla,
  43.                 bm::int1024_t& x, bm::int1024_t& y);
  44. private:
  45.         Key _key;
  46. };

  47. //        1. 随机选择两个不相等的质数p和q(实际应用中,这两个质数越大,就越难破解)。
  48. //        2. 计算p和q的乘积n,n = pq。
  49. //        3. 计算n的欧拉函数φ(n)。
  50. //        4. 随机选择一个整数e,条件是1 < e < φ(n),且e与φ(n) 互质。
  51. //        5. 计算e对于φ(n)的模反元素d,使得de≡1 mod φ(n),即:
  52. //                                                                                        (de)modφ(n) = 1
  53. //        6. 产生公钥(e, n),私钥(d, n)。
复制代码


回复

使用道具 举报

9

主题

22

帖子

98

积分

注册会员

Rank: 2

积分
98
 楼主| 发表于 2022-6-1 22:17:03 | 显示全部楼层
2、RAS.cpp(功能函数的定义和实现)
  1. #include"RSA.h"
  2. #include<time.h>
  3. #include<math.h>
  4. #include<iostream>
  5. #include<fstream>

  6. RSA::RSA()
  7. {
  8.         produce_keys();
  9. }

  10. void RSA::ecrept(const char* plain_file_in, const char* ecrept_file_out,
  11.         bm::int1024_t ekey, bm::int1024_t pkey)//加密
  12. {
  13.         std::ifstream fin(plain_file_in, std::ifstream::binary);
  14.         std::ofstream fout(ecrept_file_out, std::ofstream::binary);
  15.         if (!fin.is_open())
  16.         {
  17.                 std::cout << "open file failed" << std::endl;
  18.                 return;
  19.         }
  20.         const int NUM = 128;
  21.         char buffer[NUM];
  22.         bm::int1024_t buffer_out[NUM];
  23.         int curNum;
  24.         while (!fin.eof())
  25.         {
  26.                 fin.read(buffer, NUM);
  27.                 curNum = fin.gcount();
  28.                 for (int i = 0; i < curNum; ++i)
  29.                 {
  30.                         buffer_out[i] = ecrept(buffer[i], ekey, pkey);
  31.                 }
  32.                 fout.write((char*)buffer_out, curNum * sizeof(bm::int1024_t));
  33.         }
  34.         fin.close();
  35.         fout.close();
  36. }
  37. void RSA::decrept(const char* ecrept_file_in, const char* plain_file_out,
  38.         bm::int1024_t dkey, bm::int1024_t pkey)//解密
  39. {
  40.         std::ifstream fin(ecrept_file_in, std::ifstream::binary);
  41.         std::ofstream fout(plain_file_out, std::ofstream::binary);
  42.         if (!fin.is_open())
  43.         {
  44.                 std::cout << "open file failed" << std::endl;
  45.                 return;
  46.         }
  47.         const int NUM = 256;
  48.         bm::int1024_t buffer[NUM];
  49.         char buffer_out[NUM];
  50.         int curNum;
  51.         while (!fin.eof())
  52.         {
  53.                 fin.read((char*)buffer, NUM * sizeof(bm::int1024_t));
  54.                 curNum = fin.gcount() / sizeof(bm::int1024_t);
  55.                 for (int i = 0; i < curNum; ++i)
  56.                 {
  57.                         buffer_out[i] = (char)ecrept(buffer[i], dkey, pkey);
  58.                 }
  59.                 fout.write(buffer_out, curNum);
  60.         }
  61.         fin.close();
  62.         fout.close();
  63. }

  64. std::vector<bm::int1024_t> RSA::ecrept(std::string& str_in, bm::int1024_t ekey, bm::int1024_t pkey)//字符串加密
  65. {
  66.         std::vector<bm::int1024_t> vecout;
  67.         size_t sz = str_in.size();
  68.         for (const auto& e : str_in)
  69.         {
  70.                 vecout.push_back(ecrept(e, ekey, pkey));
  71.         }
  72.         return vecout;
  73. }
  74. std::string RSA::decrept(std::vector<bm::int1024_t>& ecrept_str, bm::int1024_t dkey, bm::int1024_t pkey)//解密为字符串
  75. {
  76.         std::string strout;
  77.         for (const auto& e : ecrept_str)
  78.         {
  79.                 strout.push_back((char)ecrept(e, dkey, pkey));
  80.         }
  81.         return strout;
  82. }

  83. void RSA::printInfo(std::vector<bm::int1024_t>& ecrept_str)//打印信息
  84. {
  85.         for (const auto& e : ecrept_str)
  86.         {
  87.                 std::cout << e << ' ';
  88.         }
  89.         std::cout << std::endl;
  90. }


  91. //模幂运算(a^b)%c   
  92. bm::int1024_t RSA::ecrept(bm::int1024_t msg, bm::int1024_t key, bm::int1024_t pkey)
  93. {
  94.         bm::int1024_t msg_out = 1;
  95.         //A0:a^(2^0) = a^1 = a
  96.         bm::int1024_t a = msg;
  97.         bm::int1024_t b = key;
  98.         bm::int1024_t c = pkey;
  99.         while (b)
  100.         {
  101.                 if (b & 1)
  102.                         //msg_out = (A0 * A1 ...Ai ... An) % c
  103.                         msg_out = (msg_out * a) % c;
  104.                 b >>= 1;
  105.                 //Ai = (A(i - 1) * A(i - 1)) % c
  106.                 a = (a * a) % c;
  107.         }
  108.         return msg_out;
  109. }

  110. //随机产生一个素数
  111. bm::int1024_t RSA::produce_prime()
  112. {
  113.         //srand(time(nullptr));
  114.         bm::int1024_t prime = 0;

  115.         //mt19937:一种随机数产生器
  116.         boost::random::mt19937 gen(time(nullptr));

  117.         //指定随机数的范围 2 ~ (1<<128)
  118.         boost::random::uniform_int_distribution<bm::int1024_t> dist(2, bm::int1024_t(1) << 128);

  119.         while (1)
  120.         {
  121.                 prime = dist(gen);
  122.                 if (is_prime_bigInt(prime))
  123.                         break;
  124.         }
  125.         return prime;
  126. }

  127. bool RSA::is_prime(bm::int1024_t prime)
  128. {
  129.         if (prime < 2)
  130.                 return false;
  131.         for (bm::int1024_t i = 2; i < sqrt(prime); ++i)
  132.         {
  133.                 if (prime % i == 0)
  134.                         return false;
  135.         }
  136.         return true;
  137. }

  138. bool RSA::is_prime_bigInt(const bm::int1024_t digit)
  139. {
  140.         boost::random::mt11213b gen(time(nullptr));
  141.         if (miller_rabin_test(digit, 25, gen)) //素数测试算法miller_rabin_test()
  142.         {
  143.                 if (miller_rabin_test((digit - 1) / 2, 25, gen))
  144.                 {
  145.                         return true;
  146.                 }
  147.         }
  148.         return false;

  149. }

  150. void RSA::produce_keys()
  151. {
  152.         bm::int1024_t prime1 = produce_prime();
  153.         bm::int1024_t prime2 = produce_prime();
  154.         while (prime1 == prime2)
  155.                 prime2 = produce_prime();
  156.         _key.pkey = produce_pkey(prime1, prime2);
  157.         bm::int1024_t orla = produce_orla(prime1, prime2);
  158.         _key.ekey = produce_ekey(orla);
  159.         _key.dkey = produce_dkey(_key.ekey, orla);
  160. }

  161. bm::int1024_t RSA::produce_pkey(bm::int1024_t prime1, bm::int1024_t prime2)
  162. {
  163.         return prime1 * prime2;
  164. }

  165. bm::int1024_t RSA::produce_orla(bm::int1024_t prime1, bm::int1024_t prime2)
  166. {
  167.         return (prime1 - 1) * (prime2 - 1);
  168. }

  169. //随机选择一个整数e,条件是1 < e < φ(n),且e与φ(n) 互质
  170. bm::int1024_t RSA::produce_ekey(bm::int1024_t orla)
  171. {
  172.         bm::int1024_t ekey;
  173.         srand(time(nullptr));
  174.         while (1)
  175.         {
  176.                 ekey = rand() % orla;
  177.                 if (ekey > 1 && produce_gcd(ekey, orla) == 1)
  178.                         break;
  179.         }
  180.         return ekey;
  181. }

  182. //求最大公约数
  183. bm::int1024_t RSA::produce_gcd(bm::int1024_t ekey, bm::int1024_t orla)
  184. {
  185.         //gcd(a, b)------gcd(b ,a%b)
  186.         bm::int1024_t ret;
  187.         while (ret = ekey % orla)
  188.         {
  189.                 ekey = orla;
  190.                 orla = ret;
  191.         }
  192.         return orla;
  193. }

  194. bm::int1024_t RSA::produce_dkey(bm::int1024_t ekey, bm::int1024_t orla)
  195. {
  196.         bm::int1024_t x, y;
  197.         exgcd(ekey, orla, x, y);
  198.         return (x % orla + orla) % orla;
  199. }



  200. /*
  201. 扩展的欧几里得算法
  202. x = y1; y = x1 - [a/b]*y1
  203. */

  204. bm::int1024_t RSA::exgcd(bm::int1024_t ekey, bm::int1024_t orla,
  205.         bm::int1024_t& x, bm::int1024_t& y)
  206. {
  207.         if (orla == 0)
  208.         {
  209.                 x = 1;
  210.                 y = 0;
  211.                 return ekey;
  212.         }
  213.         bm::int1024_t ret = exgcd(orla, ekey % orla, x, y);
  214.         bm::int1024_t x1 = x, y1 = y;
  215.         x = y1;
  216.         y = x1 - (ekey / orla) * y1;
  217.         return ret;
  218. }
复制代码
3、test.cpp(主函数及测试函数)
  1. #include"RSA.h"
  2. #include<iostream>


  3. void teststring()
  4. {
  5.         RSA rsa;
  6.         Key key = rsa.getKey();
  7.         std::string strin;
  8.         while (1)
  9.         {
  10.                 std::cout << "输入要加密的信息:" << std::endl;
  11.                 std::cin >> strin;
  12.                 std::vector<bm::int1024_t>strecrept = rsa.ecrept(strin, key.ekey, key.pkey);
  13.                 std::string strout = rsa.decrept(strecrept, key.dkey, key.pkey);
  14.                 std::cout << "加密后的信息:" << std::endl;
  15.                 rsa.printInfo(strecrept);
  16.                 std::cout << "解密后的信息:" << std::endl;
  17.                 std::cout << strout << std::endl;
  18.                 std::cout << std::endl;

  19.         }
  20. }

  21. int main()
  22. {
  23.         teststring();
  24.         system("pause");
  25.         return 0;
  26. }
复制代码


二、运行截图


本帖子中包含更多资源

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

x
回复

使用道具 举报

9

主题

22

帖子

98

积分

注册会员

Rank: 2

积分
98
 楼主| 发表于 2022-6-2 08:53:57 | 显示全部楼层
本帖最后由 唐乐 于 2022-6-2 08:56 编辑

(ECC)椭圆曲线加密

一、ECC加密原理:

    1、用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G。
  2、用户A选择一个私有密钥k,并生成公开密钥K=kG。
  3、用户A将Ep(a,b)和点K,G传给用户B。
  4、用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M,并产生一个随机整数r(r<n)。
  5、用户B计算点C1=M+rK;C2=rG。
  6、用户B将C1、C2传给用户A。
  7、用户A接到信息后,计算C1-kC2,结果就是点M。因为
          C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
   再对点M进行解码就可以得到明文。

    密码学中,描述一条Fp上的椭圆曲线,常用到六个参量: T=(p,a,b,G,n,h)。
        (p 、a 、b 用来确定一条椭圆曲线,G为基点,n为点G的阶,h 是椭圆曲线上所有点的个数m与n相除的整数部分)

        这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件:
        1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;
    2、p≠n×h;
    3、pt≠1 (mod n),1≤t<20;
    4、4a3+27b2≠0 (mod p);
    5、n 为素数;
    6、h≤4。


二、源代码
1、头文件
(1)ECC.h
  1. #pragma once
  2. #include <vector>
  3. #include "stdafx.h"
  4. #include "Key.h"
  5. class ECC
  6. {
  7. public:
  8.         ECC(int a, int b, int p);//设置椭圆曲线方程参数
  9.         virtual ~ECC(void);
  10.         //ECC加密
  11.         //待加密的消息已映射为曲线上的点Pm,密钥key,随机数k,加密结果result,通过引用方式传出该参数
  12.         //随机数为负数则自动生成随机数,否则使用固定数值k进行加密
  13.         void encrypt(const std::vector<Point>& Pm, Key& key, std::vector<Cipher>& result, int k = -1);
  14.         //ECC解密
  15.         //待解密的密文点ciphers,私钥x,解密后的离散点result,通过引用方式传出该参数
  16.         void decrypt(const std::vector<Cipher>& ciphers, int x, std::vector<Point>& result);
  17.         const std::vector<Generator> getGenerators()const;//获取生成元列表
  18.         //生成公私钥对
  19.         //生成元在mGenerators数组中的索引gIndex,私钥x
  20.         //如果传入参数不合法(例如生成元g的阶数不是素数,或者x是默认值-1),会重新生成合法的gIndex和x
  21.         //result是函数返回时生成的密钥,通过引用方式传出该参数
  22.         void genKey(Key& result, int gIndex = -1, int x = -1);
  23.         //将解密后得到的离散点解码为明文字符串
  24.         void decodePlainPoints(const std::vector<Point>& Pm, std::string& result);
  25.         //将明文M编码为椭圆曲线上的点
  26.         //编码方式:对输入的字符串去除重复字符后,构成set集合,然后把这些字符一一映射到椭圆曲线上的离散点集合里
  27.         void encodePlainText(const char* plainText, std::vector<Point>& result);
  28.         static bool isPrime(int n);//判断数n是否为素数
  29. protected:
  30.         int mA, mB, mP;//椭圆曲线方程参数y^2=x^3+ax+b (mod p)
  31.         std::vector<Point> mPoints;//椭圆曲线上的离散点,不包含无穷远点
  32.         std::vector<Generator> mGenerators;//离散点作为生成元,及其阶数构成的集合
  33.         Dictionary mDictionary;//明文字符到曲线上点的映射
  34. private:
  35.         void getAllPoints();//计算椭圆曲线上的离散点
  36.         void getAllOrders();//计算所有生成元的阶数
  37.         int getOrder(const Point& p);//计算点p的阶数
  38.         int ex_gcd(int a, int b, int& x, int& y);//递归扩展欧几里得
  39.         int getInverse(int a, int p);//计算数a在模p下的逆元
  40.         Point getMultiplePoint(int k, const Point& p);//递归计算点p的k倍点
  41.         Point add(const Point& p1, const Point& p2);//计算两个点的加法
  42.         int mod(int a, int p);//计算有符号数a在模p下的最小正数(或0)
  43. };
复制代码
(2)Key.h
  1. #pragma once
  2. #include "StdAfx.h"

  3. class Key
  4. {
  5. public:
  6.         Key(void);
  7.         Key(const Generator& g, int x, const Point& Q);//生成元g,私钥x,公钥Q
  8.         virtual ~Key(void);
  9.         const Point& getPublicKey()const;
  10.         const int getPrivateKey()const;
  11.         const Generator& getGenerator()const;
  12. protected:
  13.         Generator m_g;//生成元
  14.         Point m_Q;//公钥
  15.         int m_x;//私钥
  16. };
复制代码
(3)stdafx.h
  1. // stdafx.h : 标准系统包含文件的包含文件,
  2. // 或是经常使用但不常更改的
  3. // 特定于项目的包含文件
  4. //

  5. #pragma once

  6. //#include "targetver.h"
  7. #include <SDKDDKVer.h>
  8. #include <stdio.h>
  9. #include <tchar.h>
  10. #include <memory>
  11. #include <iostream>
  12. #include <algorithm>


  13. // TODO: 在此处引用程序需要的其他头文件
  14. struct Point {//表示平面上的一个点
  15.         int X;
  16.         int Y;
  17.         Point(int x = 0, int y = 0)//构造函数
  18.         {
  19.                 this->X = x;
  20.                 this->Y = y;
  21.         }
  22.         Point(const Point& p)//拷贝构造函数
  23.         {
  24.                 this->X = p.X;
  25.                 this->Y = p.Y;
  26.         }
  27.         bool operator==(const Point& p)const//判断两点是否相等
  28.         {
  29.                 return this->X == p.X && this->Y == p.Y;
  30.         }
  31.         bool operator!=(const Point& p)const//判断两点是否不等
  32.         {
  33.                 return this->X != p.X || this->Y != p.Y;
  34.         }
  35.         friend std::ostream& operator<<(std::ostream& out, const Point& p)//重载流输出运算符
  36.         {
  37.                 if (p.isInfinity())
  38.                 {
  39.                         out << "(∞,∞)";
  40.                 }
  41.                 else
  42.                 {
  43.                         out << '(' << p.X << ',' << p.Y << ')';
  44.                 }
  45.                 return out;
  46.         }
  47.         bool isZero()const//判断是否是原点
  48.         {
  49.                 return this->X == 0 && this->Y == 0;
  50.         }
  51.         bool isInfinity()const//判断是无穷远点
  52.         {
  53.                 return this->X == INT_MAX || this->Y == INT_MAX;
  54.         }
  55.         static const Point Infinity()//无穷远点
  56.         {
  57.                 static const Point p(INT_MAX, INT_MAX);
  58.                 return p;
  59.         }
  60. };
  61. struct Generator {//表示一个生成元
  62.         Point Value;//生成元,点P
  63.         int Order;//点P的阶,即满足nP=O的最小正整数n
  64.         Generator() {}
  65.         Generator(const Point& p, int o)
  66.         {
  67.                 this->Value.X = p.X;
  68.                 this->Value.Y = p.Y;
  69.                 this->Order = o;
  70.         }
  71.         bool operator==(const Generator& g)const//判断两个生成元是否相等
  72.         {
  73.                 return this->Value == g.Value && this->Order == g.Order;
  74.         }
  75.         bool operator!=(const Generator& g)const//判断两个生成元是否不相等
  76.         {
  77.                 return !(*this == g);
  78.         }
  79.         friend std::ostream& operator<<(std::ostream& out, const Generator& g)
  80.         {
  81.                 out << g.Value << "=>" << g.Order;
  82.                 return out;
  83.         }
  84. };
  85. struct Cipher {//表示一个字符经过ECC加密后所对应的密文
  86.         Point C1;//C1=kP
  87.         Point C2;//C2=Pm+kQ
  88.         Cipher(const Point& c1, const Point& c2)
  89.         {
  90.                 this->C1.X = c1.X;
  91.                 this->C1.Y = c1.Y;
  92.                 this->C2.X = c2.X;
  93.                 this->C2.Y = c2.Y;
  94.         }
  95.         friend std::ostream& operator<<(std::ostream& out, const Cipher& c)
  96.         {
  97.                 out << '[' << c.C1 << ' ' << c.C2 << ']';
  98.                 return out;
  99.         }
  100. };
  101. struct Dictionary {//表示由字符串构成的字符集
  102. private:
  103.         unsigned char mCharValueSet[256];
  104.         int mHash[256];
  105.         int Count;
  106. public:
  107.         Dictionary(void)//初始化一个空字典
  108.         {
  109.                 memset(mCharValueSet, 0, sizeof(mCharValueSet));
  110.                 memset(mHash, 0, sizeof(mHash));
  111.                 this->Count = 0;
  112.         }
  113.         Dictionary(const char* str)//由给定的字符串初始化一个字典
  114.         {
  115.                 memset(mCharValueSet, 0, sizeof(mCharValueSet));
  116.                 memset(mHash, 0, sizeof(mHash));
  117.                 this->Count = 0;

  118.                 unsigned char i = 0;
  119.                 while (*str != '\0')
  120.                 {
  121.                         i = *str;
  122.                         mHash[i]++;
  123.                         str++;
  124.                 }
  125.                 for (int i = 0; i < 256; i++)
  126.                 {
  127.                         if (mHash[i] != 0)
  128.                         {
  129.                                 mCharValueSet[this->Count] = i;
  130.                                 mHash[i] = this->Count;
  131.                                 this->Count++;
  132.                         }
  133.                 }
  134.         }
  135.         int getIndex(unsigned char ch)const//获取某个字符在字典中的下标
  136.         {
  137.                 //return std::lower_bound(mCharValueSet,mCharValueSet+Count,ch)-mCharValueSet;//二分查找
  138.                 return mHash[ch];//哈希查找
  139.         }
  140.         unsigned char getChar(int i)const//获取指定索引处的字符
  141.         {
  142.                 return mCharValueSet[i];
  143.         }
  144. };
复制代码




本帖子中包含更多资源

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

x
回复

使用道具 举报

9

主题

22

帖子

98

积分

注册会员

Rank: 2

积分
98
 楼主| 发表于 2022-6-2 08:59:15 | 显示全部楼层
2.源文件
(1)ECC.cpp
  1. #include "StdAfx.h"
  2. #include "ECC.h"
  3. #include <math.h>
  4. #include <sstream>

  5. //E29(4,20) G(13,23) ord(G)=37 x=25,Q(14,6)
  6. //k=6
  7. ECC::ECC(int a = 4, int b = 20, int p = 29)
  8. {
  9.         this->mA = a;
  10.         this->mB = b;
  11.         this->mP = p;
  12.         this->getAllPoints();
  13.         this->getAllOrders();
  14. }

  15. ECC::~ECC(void)
  16. {
  17. }
  18. //计算曲线上的点
  19. void ECC::getAllPoints()
  20. {
  21.         int left, right = 0;
  22.         for (int x = 0; x < mP; x++)
  23.         {
  24.                 right = x * x * x + mA * x + mB;//先计算式子右边的值
  25.                 for (int y = 0; y < mP; y++)//判断右边是不是左边的平方剩余
  26.                 {
  27.                         left = y * y;
  28.                         if (mod(left, mP) == mod(right, mP))//如果两边相等
  29.                         {
  30.                                 mPoints.push_back(Point(x, y));//则该点在曲线上
  31.                         }
  32.                 }
  33.         }
  34. }
  35. //计算所有生成元的阶
  36. void ECC::getAllOrders()
  37. {
  38.         for (std::vector<Point>::const_iterator it = mPoints.begin(); it != mPoints.end(); it++)
  39.         {
  40.                 mGenerators.push_back(Generator(*it, getOrder(*it)));
  41.         }
  42. }
  43. int ECC::getOrder(const Point& p)
  44. {
  45.         int i = 1;
  46.         Point q = add(p, p);
  47.         while (q != p && q.isInfinity() == false)
  48.         {
  49.                 i++;
  50.                 q = add(p, q);
  51.         }
  52.         return ++i;
  53. }
  54. int ECC::ex_gcd(int a, int b, int& x, int& y)
  55. {
  56.         if (b == 0)
  57.         {
  58.                 x = 1;
  59.                 y = 0;
  60.                 return a;
  61.         }
  62.         int ans = this->ex_gcd(b, a % b, x, y);
  63.         int tmp = x;
  64.         x = y;
  65.         y = tmp - a / b * y;
  66.         return ans;
  67. }

  68. int ECC::getInverse(int a, int p)
  69. {
  70.         int x, y;
  71.         int n = ex_gcd(a, p, x, y);
  72.         if (1 % n != 0) return -1;
  73.         x *= 1 / n;
  74.         p = abs(p);
  75.         int ans = x % p;
  76.         if (ans <= 0) ans += p;
  77.         return ans;
  78. }

  79. Point ECC::getMultiplePoint(int k, const Point& p)
  80. {
  81.         Point q(p);
  82.         for (int i = 1; i < k; i++)
  83.         {
  84.                 q = add(p, q);
  85.         }
  86.         return q;
  87. }

  88. Point ECC::add(const Point& p, const Point& q)
  89. {
  90.         int lambda, m, n;//斜率lambda=m/n
  91.         int x, y;
  92.         if (p.isInfinity())//p是无穷远点P+Q=O+Q=Q
  93.         {
  94.                 return q;
  95.         }
  96.         if (q.isInfinity())//q是无穷远点P+Q=P+O=P
  97.         {
  98.                 return p;
  99.         }
  100.         if (p == q)//P=Q
  101.         {
  102.                 m = mod(3 * p.X * p.X + mA, mP);
  103.                 n = mod(2 * p.Y, mP);
  104.                 //n不能为0,0没有乘法逆元
  105.         }
  106.         else//P≠Q
  107.         {
  108.                 m = mod(q.Y - p.Y, mP);
  109.                 n = mod(q.X - p.X, mP);
  110.                 //n不能为0
  111.                 //如果n=0,P、Q横坐标相同,即P、Q互逆P+Q=P+(-P)=O
  112.         }
  113.         if (n == 0)
  114.         {
  115.                 return Point::Infinity();
  116.         }
  117.         lambda = mod(m * getInverse(n, mP), mP);
  118.         x = mod(lambda * lambda - p.X - q.X, mP);
  119.         y = mod(lambda * (p.X - x) - p.Y, mP);
  120.         return Point(x, y);
  121. }

  122. int ECC::mod(int a, int p)
  123. {
  124.         if (a >= 0)
  125.         {
  126.                 return a % p;
  127.         }
  128.         else
  129.         {
  130.                 return ((a % p) + p) % p;
  131.         }
  132. }

  133. void ECC::encrypt(const std::vector<Point>& Pm, Key& key, std::vector<Cipher>& result, int k)
  134. {
  135.         bool flag = k <= 1 || k > key.getGenerator().Order;
  136.         //开始加密
  137.         for (std::vector<Point>::const_iterator it = Pm.begin(); it != Pm.end(); it++)
  138.         {
  139.                 if (flag)//如果k不符合条件
  140.                 {
  141.                         k = rand() % (key.getGenerator().Order - 1) + 1;//随机选取整数k,满足1<k<n
  142.                 }
  143.                 Point C1 = getMultiplePoint(k, key.getGenerator().Value);//C1=kP
  144.                 Point C2 = add(*it, getMultiplePoint(k, key.getPublicKey()));//C2=Pm+kQ
  145.                 result.push_back(Cipher(C1, C2));//密文c=(C1,C2)
  146.         }
  147. }

  148. void ECC::encodePlainText(const char* plainText, std::vector<Point>& result)
  149. {
  150.         mDictionary = Dictionary(plainText);
  151.         while (*plainText != '\0')
  152.         {
  153.                 int index = mDictionary.getIndex(*plainText);//获取该字符在字典中的索引
  154.                 //把该字符映射到曲线上的一个点,如果字典中元素个数多于曲线上点的个数,会发生数组越界
  155.                 result.push_back(mPoints[index]);
  156.                 plainText++;
  157.         }
  158. }
  159. void ECC::decodePlainPoints(const std::vector<Point>& Pm, std::string& result)
  160. {
  161.         std::stringstream ss;
  162.         for (std::vector<Point>::const_iterator it = Pm.begin(); it != Pm.end(); it++)
  163.         {
  164.                 for (unsigned int i = 0; i < mPoints.size(); i++)
  165.                 {
  166.                         if (mPoints[i] == *it)
  167.                         {
  168.                                 unsigned char ch = mDictionary.getChar(i);
  169.                                 ss << ch;
  170.                                 break;
  171.                         }
  172.                 }
  173.         }
  174.         ss >> result;
  175. }
  176. void ECC::decrypt(const std::vector<Cipher>& ciphers, int x, std::vector<Point>& result)
  177. {
  178.         for (std::vector<Cipher>::const_iterator it = ciphers.begin(); it != ciphers.end(); it++)
  179.         {
  180.                 Point C1R = Point(it->C1.X, -it->C1.Y);//求C1的加法逆元P+(-P)=(x,y)+(x,-y)=O
  181.                 Point Pm = add(it->C2, getMultiplePoint(x, C1R));
  182.                 result.push_back(Pm);
  183.         }
  184. }
  185. bool ECC::isPrime(int n)
  186. {
  187.         if (n < 2)
  188.                 return false;
  189.         if (n == 2 || n == 3)
  190.                 return true;
  191.         if (n % 6 != 1 && n % 6 != 5)
  192.                 return false;
  193.         float n_sqrt = floor(sqrt((float)n));
  194.         for (int i = 5; i <= n_sqrt; i += 6)
  195.         {
  196.                 if (n % i == 0 || n % (i + 2) == 0)
  197.                         return false;
  198.         }
  199.         return true;
  200. }
  201. //g是生成元,x是私钥
  202. void ECC::genKey(Key& result, int gIndex, int x)
  203. {
  204.         int n;
  205.         Generator G;
  206.         if (gIndex < 0 || isPrime(mGenerators[gIndex].Order) == false)
  207.         {
  208.                 do
  209.                 {
  210.                         gIndex = rand() % mGenerators.size();//随机选取一个阶为n的生成元,在数组中的下标为index
  211.                         n = mGenerators[gIndex].Order;
  212.                 } while (isPrime(n) == false);//如果选取的生成元的阶数不是素数,就重新选取
  213.         }
  214.         else
  215.         {
  216.                 n = mGenerators[gIndex].Order;
  217.         }
  218.         G = mGenerators[gIndex];//最终选择的生成元
  219.         if (x >= n || x <= 1)//传入的私钥不对
  220.         {
  221.                 x = rand() % (n - 1) + 1;//随机选取整数x,满足1<x<n
  222.         }
  223.         Point Q = getMultiplePoint(x, G.Value);//计算Q=xG
  224.         result = Key(G, x, Q);//生成元为mGenerators[index],公钥为Q,私钥为x
  225. }
  226. const std::vector<Generator> ECC::getGenerators()const
  227. {
  228.         return mGenerators;
  229. }
复制代码

(2)Key.cpp
  1. #include "StdAfx.h"
  2. #include "Key.h"

  3. Key::Key(const Generator& g, int x, const Point& Q)
  4. {
  5.         this->m_g = g;
  6.         this->m_Q = Q;
  7.         this->m_x = x;
  8. }
  9. Key::Key(void)
  10. {

  11. }

  12. Key::~Key(void)
  13. {
  14. }

  15. const Point& Key::getPublicKey()const
  16. {
  17.         return m_Q;
  18. }

  19. const int Key::getPrivateKey()const
  20. {
  21.         return m_x;
  22. }
  23. const Generator& Key::getGenerator()const
  24. {
  25.         return m_g;
  26. }
复制代码

(3)Test.cpp
  1. #include "stdafx.h"
  2. #include "ECC.h"
  3. #include <stdlib.h>
  4. #include <string>
  5. #include <iomanip>
  6. #include <vector>

  7. using namespace std;

  8. template <typename T>
  9. void print(const vector<T>& list)//打印数组内容
  10. {
  11.         for (unsigned int i = 0; i < list.size(); i++)
  12.         {
  13.                 if (i % 4 == 0)
  14.                 {
  15.                         cout << endl;
  16.                 }
  17.                 cout << setw(3) << setfill(' ') << i << "、" << list[i] << "\t\t";
  18.         }
  19.         cout << endl;
  20.         cout << "-------------------------------------------------------" << endl;
  21. }

  22. int main()
  23. {
  24.         int a, b, p, x, k;
  25.         Key key;
  26.         cout << "椭圆曲线方程为:" << "y^2 = x^3 + ax + b (mod p)" << endl;
  27.         //选取方程参数
  28. input:        cout << "请输入a的值(a是整数,a>0):";
  29.         cin >> a;
  30.         cout << "请输入b的值(b是整数,b>0):";
  31.         cin >> b;
  32.         cout << "请输入p的值(p是大素数,但目前用Int32表示):";
  33.         cin >> p;
  34.         if (ECC::isPrime(p) == false)
  35.         {
  36.                 cout << "p不是素数,请重新输入!" << endl;
  37.                 goto input;
  38.         }
  39.         if ((4 * (a * a * a) + 27 * (b * b)) % p == 0)
  40.         {//当4a^3+27b^2≠0时,是一条非奇异椭圆曲线,此时可以在E(a,b)定义一个阿贝尔群
  41.                 cout << "输入的参数有误,请重新输入!" << endl;
  42.                 goto input;
  43.         }
  44.         //初始化椭圆曲线方程
  45.         ECC ecc(a, b, p);
  46.         //获取所有生成元以及对应的阶
  47.         vector<Generator> generators = ecc.getGenerators();
  48.         cout << "下面是生成元及对应的阶数:" << endl;
  49.         print(generators);
  50.         //选择基点G
  51.         cout << "请选择基点G(x,y)的序号:";//G=P
  52.         cin >> k;
  53.         //输入私钥
  54.         cout << "请输入私钥(x<" << generators[k].Order << "):x = ";
  55.         cin >> x;
  56.         //产生公私钥对
  57.         ecc.genKey(key, k, x);
  58.         if (generators[k] != key.getGenerator())
  59.         {
  60.                 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
  61.                 cout << "你选择的生成元为:G = " << generators[k] << endl;
  62.                 cout << "该生成元的阶数为:ord(G) = " << generators[k].Order << ",不是素数" << endl;
  63.                 cout << "生成元已自动变更为:G = " << key.getGenerator() << endl;
  64.                 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
  65.         }
  66.         cout << "生成的公钥为:Q = " << key.getPublicKey() << endl;
  67.         cout << "目前的私钥为:x = " << key.getPrivateKey() << endl;
  68.         //输入随机数k
  69.         cout << "请输入k的值来计算 kG,kQ+Pm,输入负数使用随机值(1<k<" << key.getGenerator().Order << "):k = ";
  70.         cin >> k;

  71.         vector<Point> encodedPoints;
  72.         vector<Cipher> cipheredPoints;
  73.         //将明文m编码为椭圆曲线上的点
  74.         char text[]="";
  75.         cout << "请输入需要加密的字符串:";
  76.         cin >> text;
  77.         char* plainText = text;
  78.         ecc.encodePlainText(plainText, encodedPoints);
  79.         cout << "编码后的明文点集为:Pme = " << endl;
  80.         print(encodedPoints);
  81.         //加密
  82.         ecc.encrypt(encodedPoints, key, cipheredPoints, k);
  83.         cout << "加密后的密文点集为:Pc = " << endl;
  84.         print(cipheredPoints);

  85.         vector<Point> decryptedPoints;
  86.         string decodedText;
  87.         //解密
  88.         ecc.decrypt(cipheredPoints, key.getPrivateKey(), decryptedPoints);
  89.         cout << "解密后的明文点集为:Pm = " << endl;
  90.         print(decryptedPoints);
  91.         //解码明文点集,得到明文字符串
  92.         ecc.decodePlainPoints(decryptedPoints, decodedText);
  93.         cout << "解码后的字符串明文为:" << endl;
  94.         cout << decodedText << endl;
  95.         system("Pause");
  96.         return 0;
  97. }
复制代码


三、运行截图


本帖子中包含更多资源

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

x
回复

使用道具 举报

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

本版积分规则

教学服务系统

GMT+8, 2025-4-30 07:45 , Processed in 0.015663 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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