|

楼主 |
发表于 2022-6-2 08:59:15
|
显示全部楼层
2.源文件
(1)ECC.cpp
- #include "StdAfx.h"
- #include "ECC.h"
- #include <math.h>
- #include <sstream>
- //E29(4,20) G(13,23) ord(G)=37 x=25,Q(14,6)
- //k=6
- ECC::ECC(int a = 4, int b = 20, int p = 29)
- {
- this->mA = a;
- this->mB = b;
- this->mP = p;
- this->getAllPoints();
- this->getAllOrders();
- }
- ECC::~ECC(void)
- {
- }
- //计算曲线上的点
- void ECC::getAllPoints()
- {
- int left, right = 0;
- for (int x = 0; x < mP; x++)
- {
- right = x * x * x + mA * x + mB;//先计算式子右边的值
- for (int y = 0; y < mP; y++)//判断右边是不是左边的平方剩余
- {
- left = y * y;
- if (mod(left, mP) == mod(right, mP))//如果两边相等
- {
- mPoints.push_back(Point(x, y));//则该点在曲线上
- }
- }
- }
- }
- //计算所有生成元的阶
- void ECC::getAllOrders()
- {
- for (std::vector<Point>::const_iterator it = mPoints.begin(); it != mPoints.end(); it++)
- {
- mGenerators.push_back(Generator(*it, getOrder(*it)));
- }
- }
- int ECC::getOrder(const Point& p)
- {
- int i = 1;
- Point q = add(p, p);
- while (q != p && q.isInfinity() == false)
- {
- i++;
- q = add(p, q);
- }
- return ++i;
- }
- int ECC::ex_gcd(int a, int b, int& x, int& y)
- {
- if (b == 0)
- {
- x = 1;
- y = 0;
- return a;
- }
- int ans = this->ex_gcd(b, a % b, x, y);
- int tmp = x;
- x = y;
- y = tmp - a / b * y;
- return ans;
- }
- int ECC::getInverse(int a, int p)
- {
- int x, y;
- int n = ex_gcd(a, p, x, y);
- if (1 % n != 0) return -1;
- x *= 1 / n;
- p = abs(p);
- int ans = x % p;
- if (ans <= 0) ans += p;
- return ans;
- }
- Point ECC::getMultiplePoint(int k, const Point& p)
- {
- Point q(p);
- for (int i = 1; i < k; i++)
- {
- q = add(p, q);
- }
- return q;
- }
- Point ECC::add(const Point& p, const Point& q)
- {
- int lambda, m, n;//斜率lambda=m/n
- int x, y;
- if (p.isInfinity())//p是无穷远点P+Q=O+Q=Q
- {
- return q;
- }
- if (q.isInfinity())//q是无穷远点P+Q=P+O=P
- {
- return p;
- }
- if (p == q)//P=Q
- {
- m = mod(3 * p.X * p.X + mA, mP);
- n = mod(2 * p.Y, mP);
- //n不能为0,0没有乘法逆元
- }
- else//P≠Q
- {
- m = mod(q.Y - p.Y, mP);
- n = mod(q.X - p.X, mP);
- //n不能为0
- //如果n=0,P、Q横坐标相同,即P、Q互逆P+Q=P+(-P)=O
- }
- if (n == 0)
- {
- return Point::Infinity();
- }
- lambda = mod(m * getInverse(n, mP), mP);
- x = mod(lambda * lambda - p.X - q.X, mP);
- y = mod(lambda * (p.X - x) - p.Y, mP);
- return Point(x, y);
- }
- int ECC::mod(int a, int p)
- {
- if (a >= 0)
- {
- return a % p;
- }
- else
- {
- return ((a % p) + p) % p;
- }
- }
- void ECC::encrypt(const std::vector<Point>& Pm, Key& key, std::vector<Cipher>& result, int k)
- {
- bool flag = k <= 1 || k > key.getGenerator().Order;
- //开始加密
- for (std::vector<Point>::const_iterator it = Pm.begin(); it != Pm.end(); it++)
- {
- if (flag)//如果k不符合条件
- {
- k = rand() % (key.getGenerator().Order - 1) + 1;//随机选取整数k,满足1<k<n
- }
- Point C1 = getMultiplePoint(k, key.getGenerator().Value);//C1=kP
- Point C2 = add(*it, getMultiplePoint(k, key.getPublicKey()));//C2=Pm+kQ
- result.push_back(Cipher(C1, C2));//密文c=(C1,C2)
- }
- }
- void ECC::encodePlainText(const char* plainText, std::vector<Point>& result)
- {
- mDictionary = Dictionary(plainText);
- while (*plainText != '\0')
- {
- int index = mDictionary.getIndex(*plainText);//获取该字符在字典中的索引
- //把该字符映射到曲线上的一个点,如果字典中元素个数多于曲线上点的个数,会发生数组越界
- result.push_back(mPoints[index]);
- plainText++;
- }
- }
- void ECC::decodePlainPoints(const std::vector<Point>& Pm, std::string& result)
- {
- std::stringstream ss;
- for (std::vector<Point>::const_iterator it = Pm.begin(); it != Pm.end(); it++)
- {
- for (unsigned int i = 0; i < mPoints.size(); i++)
- {
- if (mPoints[i] == *it)
- {
- unsigned char ch = mDictionary.getChar(i);
- ss << ch;
- break;
- }
- }
- }
- ss >> result;
- }
- void ECC::decrypt(const std::vector<Cipher>& ciphers, int x, std::vector<Point>& result)
- {
- for (std::vector<Cipher>::const_iterator it = ciphers.begin(); it != ciphers.end(); it++)
- {
- Point C1R = Point(it->C1.X, -it->C1.Y);//求C1的加法逆元P+(-P)=(x,y)+(x,-y)=O
- Point Pm = add(it->C2, getMultiplePoint(x, C1R));
- result.push_back(Pm);
- }
- }
- bool ECC::isPrime(int n)
- {
- if (n < 2)
- return false;
- if (n == 2 || n == 3)
- return true;
- if (n % 6 != 1 && n % 6 != 5)
- return false;
- float n_sqrt = floor(sqrt((float)n));
- for (int i = 5; i <= n_sqrt; i += 6)
- {
- if (n % i == 0 || n % (i + 2) == 0)
- return false;
- }
- return true;
- }
- //g是生成元,x是私钥
- void ECC::genKey(Key& result, int gIndex, int x)
- {
- int n;
- Generator G;
- if (gIndex < 0 || isPrime(mGenerators[gIndex].Order) == false)
- {
- do
- {
- gIndex = rand() % mGenerators.size();//随机选取一个阶为n的生成元,在数组中的下标为index
- n = mGenerators[gIndex].Order;
- } while (isPrime(n) == false);//如果选取的生成元的阶数不是素数,就重新选取
- }
- else
- {
- n = mGenerators[gIndex].Order;
- }
- G = mGenerators[gIndex];//最终选择的生成元
- if (x >= n || x <= 1)//传入的私钥不对
- {
- x = rand() % (n - 1) + 1;//随机选取整数x,满足1<x<n
- }
- Point Q = getMultiplePoint(x, G.Value);//计算Q=xG
- result = Key(G, x, Q);//生成元为mGenerators[index],公钥为Q,私钥为x
- }
- const std::vector<Generator> ECC::getGenerators()const
- {
- return mGenerators;
- }
复制代码
(2)Key.cpp
- #include "StdAfx.h"
- #include "Key.h"
- Key::Key(const Generator& g, int x, const Point& Q)
- {
- this->m_g = g;
- this->m_Q = Q;
- this->m_x = x;
- }
- Key::Key(void)
- {
- }
- Key::~Key(void)
- {
- }
- const Point& Key::getPublicKey()const
- {
- return m_Q;
- }
- const int Key::getPrivateKey()const
- {
- return m_x;
- }
- const Generator& Key::getGenerator()const
- {
- return m_g;
- }
复制代码
(3)Test.cpp
- #include "stdafx.h"
- #include "ECC.h"
- #include <stdlib.h>
- #include <string>
- #include <iomanip>
- #include <vector>
- using namespace std;
- template <typename T>
- void print(const vector<T>& list)//打印数组内容
- {
- for (unsigned int i = 0; i < list.size(); i++)
- {
- if (i % 4 == 0)
- {
- cout << endl;
- }
- cout << setw(3) << setfill(' ') << i << "、" << list[i] << "\t\t";
- }
- cout << endl;
- cout << "-------------------------------------------------------" << endl;
- }
- int main()
- {
- int a, b, p, x, k;
- Key key;
- cout << "椭圆曲线方程为:" << "y^2 = x^3 + ax + b (mod p)" << endl;
- //选取方程参数
- input: cout << "请输入a的值(a是整数,a>0):";
- cin >> a;
- cout << "请输入b的值(b是整数,b>0):";
- cin >> b;
- cout << "请输入p的值(p是大素数,但目前用Int32表示):";
- cin >> p;
- if (ECC::isPrime(p) == false)
- {
- cout << "p不是素数,请重新输入!" << endl;
- goto input;
- }
- if ((4 * (a * a * a) + 27 * (b * b)) % p == 0)
- {//当4a^3+27b^2≠0时,是一条非奇异椭圆曲线,此时可以在E(a,b)定义一个阿贝尔群
- cout << "输入的参数有误,请重新输入!" << endl;
- goto input;
- }
- //初始化椭圆曲线方程
- ECC ecc(a, b, p);
- //获取所有生成元以及对应的阶
- vector<Generator> generators = ecc.getGenerators();
- cout << "下面是生成元及对应的阶数:" << endl;
- print(generators);
- //选择基点G
- cout << "请选择基点G(x,y)的序号:";//G=P
- cin >> k;
- //输入私钥
- cout << "请输入私钥(x<" << generators[k].Order << "):x = ";
- cin >> x;
- //产生公私钥对
- ecc.genKey(key, k, x);
- if (generators[k] != key.getGenerator())
- {
- cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
- cout << "你选择的生成元为:G = " << generators[k] << endl;
- cout << "该生成元的阶数为:ord(G) = " << generators[k].Order << ",不是素数" << endl;
- cout << "生成元已自动变更为:G = " << key.getGenerator() << endl;
- cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
- }
- cout << "生成的公钥为:Q = " << key.getPublicKey() << endl;
- cout << "目前的私钥为:x = " << key.getPrivateKey() << endl;
- //输入随机数k
- cout << "请输入k的值来计算 kG,kQ+Pm,输入负数使用随机值(1<k<" << key.getGenerator().Order << "):k = ";
- cin >> k;
- vector<Point> encodedPoints;
- vector<Cipher> cipheredPoints;
- //将明文m编码为椭圆曲线上的点
- char text[]="";
- cout << "请输入需要加密的字符串:";
- cin >> text;
- char* plainText = text;
- ecc.encodePlainText(plainText, encodedPoints);
- cout << "编码后的明文点集为:Pme = " << endl;
- print(encodedPoints);
- //加密
- ecc.encrypt(encodedPoints, key, cipheredPoints, k);
- cout << "加密后的密文点集为:Pc = " << endl;
- print(cipheredPoints);
- vector<Point> decryptedPoints;
- string decodedText;
- //解密
- ecc.decrypt(cipheredPoints, key.getPrivateKey(), decryptedPoints);
- cout << "解密后的明文点集为:Pm = " << endl;
- print(decryptedPoints);
- //解码明文点集,得到明文字符串
- ecc.decodePlainPoints(decryptedPoints, decodedText);
- cout << "解码后的字符串明文为:" << endl;
- cout << decodedText << endl;
- system("Pause");
- return 0;
- }
复制代码
三、运行截图
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|