素域上椭圆曲线
E
(
F
p
)
E(F_p)
E(Fp)的C++实现
E
C
.
h
EC.h
EC.h
#pragma once
#include <iostream>
#include <NTL/ZZ.h> // integers
#include <NTL/ZZ_p.h> // integers mod p
using namespace std;
using namespace NTL;
#pragma comment(lib, "NTL")
typedef char int8;
typedef int int32;
typedef long long int64;
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
// 换行
#define pn puts("")
// 异常
#define ErrorInfo(format, ...) {\
printf("File:%s, Line:%d, Function:%s, ",\
__FILE__, __LINE__ , __FUNCTION__);\
printf(format, ##__VA_ARGS__);}
/*
E(F_p)上椭圆曲线点
*/
struct Point
{
uint8 PC; //标识。无穷远点PC=00,点的未压缩表示PC=04
ZZ x; //横坐标
ZZ y; //纵坐标
};
//打印
ostream& operator<<(ostream& cout, Point& P);
/*
Elliptic curve
素域上椭圆曲线,E(F_p)
y^2 = x^3 + ax + b
*/
class EC
{
private:
ZZ p;
ZZ a;
ZZ b;
public:
/*
椭圆曲线初始化
*/
void init(ZZ& p, ZZ& a, ZZ& b);
/*
判断是否是椭圆曲线上的点
*/
bool IsECPoint(Point& op1);
/*
加法
*/
void Add(Point& res, Point& op1, Point& op2);
/*
倍点
*/
void Double(Point& res, Point& op1);
/*
多倍点
*/
void Multiple(Point& res, ZZ& k, Point& op1);
/*
打印EC参数
*/
void Param();
};
E
C
.
c
p
p
EC.cpp
EC.cpp
#include "EC.h"
ostream& operator<<(ostream& cout, Point& P)
{
printf("struct Point\n\tPC = %02x\n", P.PC);
if (P.PC != 0)
{
cout << "\tx = " << P.x; pn;
cout << "\ty = " << P.y; pn;
}
return cout;
}
void EC::init(ZZ&p, ZZ& a, ZZ& b)
{
if ((4 * PowerMod(a%p, 3, p) + 27 * PowerMod(b%p, 2, p)) % p == 0)
{
ErrorInfo("%s\n", "4*a^3 + 27*b^2 = 0 mod p");
return;
}
this->p = p;
this->a = a;
this->b = b;
}
bool EC::IsECPoint(Point& op1)
{
if (op1.PC == 0)
return 1;
else
return PowerMod(op1.y, 2, p) == (PowerMod(op1.x, 3, p) + a * op1.x + b) % p;
}
void EC::Add(Point& res, Point& op1, Point& op2)
{
if (op1.PC == 0 || op2.PC == 0)
{
if (op1.PC != 0)
{
res = op1;
return;
}
if (op2.PC != 0)
{
res = op2;
return;
}
res.PC = 0;
return;
}
if (op1.x == op2.x)
{
if (op1.y == op2.y)
Double(res, op1);
else if (op1.y + op2.y == p)
res.PC = 0;
else
ErrorInfo("%s\n", "x1 == x2, but y1 != y2 and y1 != -y2");
}
else
{
res.PC = 4;
ZZ xx = op2.x + (p - op1.x);
if (xx >= p)
xx -= p;
ZZ lambda = ((op2.y + (p - op1.y))*InvMod(xx, p)) % p;
ZZ x = (PowerMod(lambda, 2, p) + (p - op1.x) + (p - op2.x)) % p;
res.y = (lambda*(op1.x - x) + (p - op1.y)) % p;
res.x = x;
}
}
void EC::Double(Point& res, Point& op1)
{
if (op1.PC == 0)
{
res.PC = 0;
return;
}
if (op1.y == 0)
{
ErrorInfo("%s\n", "y1 == 0");
}
else
{
res.PC = 4;
ZZ yy = 2 * op1.y;
if (yy >= p)
yy -= p;
ZZ lambda = ((3 * PowerMod(op1.x, 2, p) + a)*InvMod(yy, p)) % p;
ZZ x = (PowerMod(lambda, 2, p) + 2 * (p - op1.x)) % p;
res.y = (lambda*(op1.x - x) + (p - op1.y)) % p;
res.x = x;
}
}
void EC::Multiple(Point& res, ZZ& k, Point& op1)
{
if (op1.PC == 0)
{
res.PC = 0;
return;
}
Point op = op1;
ZZ kk = k;
res.PC = 0;
while (kk > 0)
{
if ((kk & 1) == 1)
Add(res, res, op);
Double(op, op);
kk >>= 1;
}
}
void EC::Param()
{
cout << "class EC\n";
cout << "\ta=" << a; pn;
cout << "\tb=" << b; pn;
cout << "\tp=" << p; pn; pn;
}