?? ibe_encx.cpp
字號:
/*
Boneh & Franklin's Identity Based Encryption
y^2=x^3+x version
Using this curve has certain advantages. In particular the "denominator"
that arises in the context of Miller's algorithm is in Fp, and hence
"disappears" with the final exponentiation. So it can be left out
altogther.
Encryption phase
Generates a random AES session key, and uses it to encrypt a file.
Outputs ciphertext <filename>.ibe.
The session key is IBE encrypted, and written to <filename>.key
NOTE: Uses Tate Pairing only
NOTE: New fast Tate pairing algorithm
Compile as
cl /O2 /GX /DZZNS=16 ibe_encx.cpp zzn2.cpp big.cpp zzn.cpp ecn.cpp miracl.lib
where miracl is built using the Comba method.
*/
#include <iostream>
#include <fstream>
#include <cstring>
#include "ecn.h"
#include "zzn.h"
#include "ebrick.h"
#include "zzn2.h"
using namespace std;
#define HASH_LEN 20
#define PBITS 512
#define QBITS 160
// Using SHA-1 as basic hash algorithm
//
// 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)
//
ZZn2 line(ECn& A,ECn& C,ZZn& slope,ZZn& Qx,ZZn2& Qy)
{
ZZn2 w=Qy;
ZZn x,y,z,t,m=Qx;
#ifdef AFFINE
extract(A,x,y);
w-=y; m-=x; m*=slope; w-=m; // 1 ZZn mul
#endif
#ifdef PROJECTIVE
extract(A,x,y,z);
x*=z; t=z; z*=z; z*=t; // 9 ZZn muls
m*=z; m-=x; m*=slope;
w*=z; w-=y;
extract(C,x,y,z);
w*=z; w-=m;
#endif
return w;
}
//
// Add A=A+B (or A=A+A)
//
// AFFINE doubling - 8 ZZn muls, plus 1 inversion
// AFFINE adding - 7 ZZn muls, plus 1 inversion
//
// PROJECTIVE doubling - 20 ZZn muls
// PROJECTIVE adding - 28 ZZn muls
//
void g(ECn& A,ECn& B,ZZn& Qx,ZZn2& Qy,ZZn2& num)
{
int type;
ZZn lam;
ZZn2 u;
ECn P=A;
big ptr;
if (num.iszero()) return;
type=A.add(B,&ptr);
if (!type) return;
lam=ptr;
if (A.iszero()) return;
u=line(P,A,lam,Qx,Qy);
num*=u; // 3 ZZn muls
}
//
// Tate Pairing
//
// Special optimized and deterministic version of Tate Pairing algorithm
// P and Q(x,y) linearly independent, that is P!=r.Q for any r, and odd order q.
// If P & Q are linearly dependent it might fail, but this will be detected.
//
// P & Q(x,y) are both points of order q.
// Note that P is a point on the curve over Fp, Q(x,y) a point on the
// quadratic extension field Fp^2
//
BOOL fast_tate_pairing(ECn& P,ZZn& Qx,ZZn2& Qy,Big& q,ZZn2& res)
{
int i;
Big p;
ECn A;
res=1;
// q.P = 2^17*(2^142.P +P) + P
A=P; // reset A
for (i=0;i<142;i++)
{
res*=res;
g(A,A,Qx,Qy,res); // 10 ZZn muls + 1 inverse
} // 22 ZZn muls (Projective)
g(A,P,Qx,Qy,res); // 9 ZZn muls + 1 inverse
for (i=0;i<17;i++) // 28 ZZn muls (Projective)
{
res*=res;
g(A,A,Qx,Qy,res); // 10 ZZn muls + 1 inverse
} // 22 ZZn muls (Projective)
g(A,P,Qx,Qy,res); // 9 ZZn muls + 1 inverse
if (res.iszero()) return FALSE;
if (!A.iszero()) return FALSE;
// 28 ZZn muls (Projective)
p=get_modulus(); // get p
res= pow(res,(p+1)/q); // raise to power of (p^2-1)/q
res=conj(res)/res;
if (res.isunity()) return FALSE;
return TRUE;
}
//
// ecap(.) function
//
BOOL ecap(ECn& P,ECn& Q,Big& order,ZZn2& res)
{
ZZn Qx;
ZZn2 Qy;
Big xx,yy; /* apply distortion map x,y -> -x,iy */
Q.get(xx,yy); /* Q*=[(-1,0),(0,1)] */
Qx=-xx;
Qy.set((Big)0,yy);
return fast_tate_pairing(P,Qx,Qy,order,res);
}
//
// 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;
}
int H2(ZZn2 x,char *s)
{ // Hash an Fp2 to an n-byte string s[.]. Return n
sha sh;
Big a,b;
int m;
shs_init(&sh);
x.get(a,b);
while (a>0)
{
m=a%256;
shs_process(&sh,m);
a/=256;
}
while (b>0)
{
m=b%256;
shs_process(&sh,m);
b/=256;
}
shs_hash(&sh,s);
return HASH_LEN;
}
Big H3(char *x1,char *x2)
{
sha sh;
char h[HASH_LEN];
Big a;
int i;
shs_init(&sh);
for (i=0;i<HASH_LEN;i++)
shs_process(&sh,x1[i]);
for (i=0;i<HASH_LEN;i++)
shs_process(&sh,x2[i]);
shs_hash(&sh,h);
a=from_binary(HASH_LEN,h);
return a;
}
void H4(char *x,char *y)
{ // hashes y=h(x)
int i;
sha sh;
shs_init(&sh);
for (i=0;i<HASH_LEN;i++)
shs_process(&sh,x[i]);
shs_hash(&sh,y);
}
//
// MapToPoint
//
ECn map_to_point(char *ID)
{
ECn Q;
Big x0=H1(ID);
if (is_on_curve(x0)) Q.set(x0);
else Q.set(-x0);
return Q;
}
void strip(char *name)
{ /* strip off filename extension */
int i;
for (i=0;name[i]!='\0';i++)
{
if (name[i]!='.') continue;
name[i]='\0';
break;
}
}
int main()
{
miracl *mip=mirsys(16,0); // thread-safe ready. (32,0) for 1024 bit p
ifstream common("commonx.ibe");
ifstream plaintext;
ofstream key_file,ciphertext;
ECn U,P,Ppub,Qid,infinity;
ZZn2 gid,w;
char key[HASH_LEN],pad[HASH_LEN],rho[HASH_LEN],V[HASH_LEN],W[HASH_LEN];
char ifname[100],ofname[100],ch,iv[16];
Big p,q,r,x,y,cof;
int i,bits;
long seed;
aes a;
cout << "Enter 9 digit random number seed = ";
cin >> seed;
irand(seed);
// ENCRYPT
common >> bits;
mip->IOBASE=16;
common >> p >> q;
cof=(p+1)/q;
common >> x >> y;
EBrick B(x,y,(Big)1,(Big)0,p,8,QBITS); // precomputation based on fixed P, 8-bit window
#ifdef AFFINE
ecurve(1,0,p,MR_AFFINE);
#endif
#ifdef PROJECTIVE
ecurve(1,0,p,MR_PROJECTIVE);
#endif
P.set(x,y);
common >> x >> y;
Ppub.set(x,y);
char id[1000];
cout << "Enter your correspondents email address (lower case)" << endl;
cin.get();
cin.getline(id,1000);
mip->IOBASE=10;
Qid=map_to_point(id);
// This can be done before we know the message to encrypt
if (!ecap(Ppub,Qid,q,gid)) // ** change argument order
{ // Qid must be second
cout << "Bad Parameters" << endl;
exit(0);
}
//
// prepare to encrypt file with random session key
//
for (i=0;i<HASH_LEN;i++) key[i]=(char)brand();
for (i=0;i<16;i++) iv[i]=i; // set CFB IV
aes_init(&a,MR_CFB1,16,key,iv);
// figure out where input is coming from
cout << "Text file to be encoded = " ;
cin >> ifname;
/* set up input file */
strcpy(ofname,ifname);
strip(ofname);
strcat(ofname,".ibe");
plaintext.open(ifname,ios::in);
if (!plaintext)
{
cout << "Unable to open file " << ifname << "\n";
return 0;
}
cout << "encoding message\n";
ciphertext.open(ofname,ios::binary|ios::out);
// now encrypt the plaintext file
forever
{ // encrypt input ..
plaintext.get(ch);
if (plaintext.eof()) break;
aes_encrypt(&a,&ch);
ciphertext << ch;
}
aes_end(&a);
//
// Now IBE encrypt the session key
//
for (i=0;i<HASH_LEN;i++) rho[i]=(char)brand();
r=H3(rho,key)%q;
B.mul(r,x,y); // U=r*P
U.set(x,y);
w=pow(gid,r);
H2(w,pad);
for (i=0;i<HASH_LEN;i++)
{
V[i]=rho[i]^pad[i];
pad[i]=0;
}
H4(rho,rho);
for (i=0;i<HASH_LEN;i++)
{
W[i]=key[i]^rho[i];
rho[i]=0;
}
strip(ofname);
strcat(ofname,".key");
mip->IOBASE=16;
key_file.open(ofname);
U.get(x,y);
key_file << x << endl;
key_file << y << endl;
x=from_binary(HASH_LEN,V); // output bit strings in handy Big format
key_file << x << endl;
x=from_binary(HASH_LEN,W);
key_file << x << endl;
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -