📄 ake6.cpp
字号:
/*
Scott's AKE Client/Server testbed
See http://www.compapp.dcu.ie/research/CA_Working_Papers/wp02.html#0202
Compile as
cl /O2 /GX /DZZNS=5 ake6.cpp zzn6.cpp ecn6.cpp big.cpp zzn.cpp ecn.cpp miracl.lib
using COMBA build
The required file mnt.ecs is created from a curve generated by the mnt
utility, and created by the cm utility. For convenience the value of
(p^2-p+1)/q has been manually appended to this file.
NOTE: Irreducible polynomial MUST be of the form x^6+x^2+n
Use the irred utility
Modified to prevent sub-group confinement attack
NOTE: Key exchange bandwidth could be reduce by two-thirds using ideas from
"Doing more with Fewer Bits", Brouwer, Pellikaan & Verheul, Asiacrypt
'99
*/
#include <iostream>
#include <fstream>
#include <string.h>
#include "ecn.h"
#include <ctime>
#include "ecn6.h"
#include "zzn6.h"
using namespace std;
Miracl precision(8,0);
// Using SHA-1 as basic hash algorithm
#define HASH_LEN 20
//
// Define one or the other of these
//
// Which is faster depends on the I/M ratio - See imratio.c
// Roughly if I/M ratio > 16 use PROJECTIVE, otherwise use AFFINE
//
// #define AFFINE
#define PROJECTIVE
//
// Tate Pairing Code
//
// Extract ECn point in internal ZZn format
//
void extract(ECn& A,ZZn& x,ZZn& y)
{
x=(A.get_point())->X;
y=(A.get_point())->Y;
}
void extract(ECn& A,ZZn& x,ZZn& y,ZZn& z)
{
big t;
x=(A.get_point())->X;
y=(A.get_point())->Y;
t=(A.get_point())->Z;
if (A.get_status()!=MR_EPOINT_GENERAL) z=1;
else z=t;
}
//
// Line from A to destination C. Let A=(x,y)
// Line Y-slope.X-c=0, through A, so intercept c=y-slope.x
// Line Y-slope.X-y+slope.x = (Y-y)-slope.(X-x) = 0
// Now evaluate at Q -> return (Qy-y)-slope.(Qx-x)
//
ZZn6 line(ECn& A,ECn& C,ZZn& slope,ZZn6& Qx,ZZn6& Qy)
{
ZZn6 n=Qx,w=Qy;
ZZn x,y,z,t;
#ifdef AFFINE
extract(A,x,y);
n-=x; n*=slope;
w-=y; n-=w;
#endif
#ifdef PROJECTIVE
extract(A,x,y,z);
x*=z; t=z; z*=z; z*=t;
n*=z; n-=x;
w*=z; w-=y;
extract(C,x,y,z);
w*=z; n*=slope; n-=w;
#endif
return n;
}
//
// Add A=A+B (or A=A+A)
// Bump up num
//
void g(ECn& A,ECn& B,ZZn6& Qx,ZZn6& Qy,ZZn6& num,BOOL first)
{
ZZn lam;
ZZn6 u;
big ptr;
ECn P=A;
// Evaluate line from A
ptr=A.add(B);
if (ptr==NULL) return;
else lam=ptr;
if (A.iszero()) return;
u=line(P,A,lam,Qx,Qy);
if (first) num= u;
else num*=u;
}
//
// Tate Pairing - note denominator elimination has been applied
//
// P is a point of order q. Q(x,y) is a point of order m.q.
// Note that P is a point on the curve over Fp, Q(x,y) a point on the
// extension field Fp^6
//
BOOL fast_tate_pairing(ECn& P,ZZn6& Qx,ZZn6& Qy,Big& q,Big &cf,ZZn6& res)
{
int i,j,n,nb,nbw,nzs;
ECn A,P2,t[16];
ZZn6 w,hc,z2n,zn[16],b[2];
Big a[2];
res=zn[0]=1;
t[0]=P2=A=P;
g(P2,P2,Qx,Qy,z2n,TRUE); // P2=P+P
//
// Build windowing table
//
for (i=1;i<16;i++)
{
g(A,P2,Qx,Qy,hc,TRUE);
t[i]=A;
zn[i]=z2n*zn[i-1]*hc;
}
A=P; // reset A
/* Left to right method */
nb=bits(q);
for (i=nb-2;i>=0;i-=(nbw+nzs))
{
n=window(q,i,&nbw,&nzs); // standard MIRACL windowing
for (j=0;j<nbw;j++)
{
res*=res;
g(A,A,Qx,Qy,res,FALSE);
}
if (n>0)
{
res*=zn[n/2];
g(A,t[n/2],Qx,Qy,res,FALSE);
}
for (j=0;j<nzs;j++)
{
res*=res;
g(A,A,Qx,Qy,res,FALSE);
}
if (res.iszero()) return FALSE;
}
if (!A.iszero() || res.iszero()) return FALSE;
w=res;
w.powq();
res*=w; // ^(p+1)
w=res;
w.powq(); w.powq(); w.powq();
res=w/res; // ^(p^3-1)
// res=pow(res,cf); // ^(p*p-p+1)/q
// exploit the clever "trick" for a half-length exponentiation!
w=res.powq();
res.powq(); res*=pow(w,cf);
if (res.isunity()) return FALSE;
return TRUE;
}
//
// ecap(.) function
//
BOOL ecap(ECn& P,ECn6& Q,Big& order,Big& cf,ZZn6& res)
{
BOOL Ok;
ECn PP=P;
ZZn6 Qx,Qy;
normalise(PP);
Q.get(Qx,Qy);
Ok=fast_tate_pairing(PP,Qx,Qy,order,cf,res);
if (Ok) return TRUE;
return FALSE;
}
//
// Hash functions
//
Big H1(char *string)
{ // Hash a zero-terminated string to a number < modulus
Big h,p;
char s[HASH_LEN];
int i,j;
sha sh;
shs_init(&sh);
for (i=0;;i++)
{
if (string[i]==0) break;
shs_process(&sh,string[i]);
}
shs_hash(&sh,s);
p=get_modulus();
h=1; j=0; i=1;
forever
{
h*=256;
if (j==HASH_LEN) {h+=i++; j=0;}
else h+=s[j++];
if (h>=p) break;
}
h%=p;
return h;
}
Big H2(ZZn6 x)
{ // Hash an Fp6 to a big number
sha sh;
Big a,h,p,xx[6];
char s[20];
int i,j,m;
shs_init(&sh);
x.get(xx);
for (i=0;i<6;i++)
{
a=xx[i];
while (a>0)
{
m=a%256;
shs_process(&sh,m);
a/=256;
}
}
shs_hash(&sh,s);
h=from_binary(20,s);
return h;
}
ECn6 Trace(ECn6 R)
{
ECn6 W,P;
ZZn6 X,Y;
R.get(X,Y);
W=R;
P=W;
for (int i=1;i<=5;i++)
{
if(!W.set(X.powq(),Y.powq())) cout << "Trace error" << endl;
P+=W;
}
return P;
}
// Hash and map a Server Identity to a curve point E_(Fp6)
ECn6 hash_and_map6(char *ID)
{
ECn6 S;
ZZn6 X,Y;
Big xx[6],x,x0=H1(ID);
forever
{
xx[5]=xx[3]=xx[2]=xx[1]=xx[0]=0; // Set X in Fp3
xx[4]=x0; // Map & Hash "Identity" to curve point
x0+=1;
X.set(xx);
S.set(X); // this will never fail!
S.get(X,Y);
Y.get(x); // check Y for degenerate form...
if (!x.iszero()) continue;
break;
}
cout << "S= " << S << endl;
return S;
}
// Hash and map a Client Identity to a curve point E_(Fp)
ECn hash_and_map(char *ID)
{
ECn Q;
Big x0=H1(ID);
while (!Q.set(x0,x0)) x0+=1;
return Q;
}
int main()
{
ifstream common("mnt.ecs"); // MNT elliptic curve parameters
miracl* mip=&precision;
ECn Alice,Bob,sA,sB;
ECn6 B6,Server,sS;
ZZn6 X,Y,res,sp,ap,bp;
Big a,b,s,ss,p,q,x,y,B,xx[6],yy[6],cf,cfp;
int i,bits,A;
long seed;
common >> bits;
mip->IOBASE=16;
common >> p;
common >> A;
common >> B >> q >> x >> y >> cf;
init_zzn6(p);
cout << "Initialised... " << endl;
time(&seed);
irand(seed);
#ifdef AFFINE
ecurve(A,B,p,MR_AFFINE);
#endif
#ifdef PROJECTIVE
ecurve(A,B,p,MR_PROJECTIVE);
#endif
//cout << "p= " << p << endl;
//cout << "cf= " << cf << endl;
//cout << "cf-p= " << cf-p << endl;
// This is a bit clever... exploit the fact that for this curve cf and p are very close...
cfp=cf-p; // = (t-1)
mip->IOBASE=16;
// hash Identities to curve point
ss=rand(q); // TA's super-secret
cout << "Mapping Server ID to point" << endl;
Server=hash_and_map6("Server");
cout << "Mapping Alice & Bob ID's to points" << endl;
Alice=hash_and_map("Alice");
Bob= hash_and_map("Robert");
cout << "Alice, Bob and the Server visit Trusted Authority" << endl;
sS=ss*Server;
sA=ss*Alice;
sB=ss*Bob;
cout << "Alice and Server Key Exchange" << endl;
a=rand(q); // Alice's random number
s=rand(q); // Server's random number
if (!ecap(sA,Server,q,cfp,res)) cout << "Trouble" << endl;
if (pow(res,q)!=(ZZn6)1)
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
ap=pow(res,a);
if (!ecap(Alice,sS,q,cfp,res)) cout << "Trouble" << endl;
if (pow(res,q)!=(ZZn6)1)
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
sp=pow(res,s);
cout << "Alice Key= " << H2(pow(sp,a)) << endl;
cout << "Server Key= " << H2(pow(ap,s)) << endl;
cout << "Bob and Server Key Exchange" << endl;
b=rand(q); // Bob's random number
s=rand(q); // Server's random number
if (!ecap(sB,Server,q,cfp,res)) cout << "Trouble" << endl;
if (pow(res,q)!=(ZZn6)1)
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
bp=pow(res,b);
if (!ecap(Bob,sS,q,cfp,res)) cout << "Trouble" << endl;
if (pow(res,q)!=(ZZn6)1)
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
sp=pow(res,s);
cout << "Bob's Key= " << H2(pow(sp,b)) << endl;
cout << "Server Key= " << H2(pow(bp,s)) << endl;
cout << "Alice and Bob's attempted Key exchange" << endl;
Bob.get(x,y);
for (i=0;i<6;i++) xx[i]=yy[i]=0;
xx[0]=x; yy[0]=y;
X.set(xx); Y.set(yy);
B6.set(X,Y);
ecap(Alice,B6,q,cf,res);
cout << "But Tate Pairing evaluates as.... :( " << res << endl;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -