|

楼主 |
发表于 2022-6-2 17:16:57
|
显示全部楼层
ECC椭圆曲线加密
1. 椭圆曲线加密算法(ECC):
椭圆曲线加密算法,简称ECC,是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全,RSA加密算法也是一种非对称加密算法,在公开密钥加密和电子商业中RSA被广泛使用。
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;
- }
复制代码
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;
- }
复制代码
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编码为椭圆曲线上的点
- ecc.encodePlainText("Hello,我是明文",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
|