}
函数原型为:int putin(mp_int *a,char *ch,int chlong) 成功返回0
2.函数chdraw()实现将mp_int数a中的比特串还原为字符串并赋给字符串ch:
chdraw和putin是相反过程,将putin存入字符的过程反过来取出字符。
函数原型为:int chdraw(mp_int *a,char *ch) 成功返回0
六、密文的存取和读入
此过程难点是如何保证存入文件后,再从文件中读取密文并存入mp_int型数后,和原存放密文的mp_int型数不能有一个比特位的改变。 存取时先存*mp->dp的最高8位,再依次往下存后面3个8位。依据*mp->dp的特点,最高8位为0000xxxx,因此,可将255作为一个密
文段的结束标志,把前一密文段和后一密文段区分开。这样在密文文件中,密文的存取结构为:
0000xxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|0000xxxx|……|11111111|0000xxxx|xxxxxxxx|…..
0字节 1字节 2字节 3字节 4字节 4x字节 下一加密段x为1或0利用fgetc每次读取一个字符,并赋值给一个字符数组。当a[i]=255,且i%4=0时截止。 读出之后赋值就简单了。
存密文:int chmistore(mp_int *a,FILE *fp) 成功返回0把密文赋给mp_int型数a:int miwendraw(mp_int *a,char *ch,int chlong) 成功返回0
七、ECC加密的实现
加密时因P长度取值为200比特,所以所取明文长度应在0到199比特之间,另外需要一个附加的标志字节char(255),所以一次取明文最大长为191比特。在本程序中一次取20字节。和RSA不同,ECC运算是基于点的运算。一个点有两个参数,一个X坐标,一个Y坐标。所以取明文时需一次取两段,前一段做X坐标,后一段做Y坐标。因此,一次加密明文为40字节。由于每次加密要取两段,引发了另外一个问题:当加密文件末尾所剩明文长度小于20字节时的处理。在本程序中,
我们的解决是将剩余明文取作X,而将Y取作0,且不加标志字节char(255),这样解密时,程序在Y中找不到标志字节char(255),就 不会往解密文中存任何东西。
取得明文后,产生一个随机整数r(r<有限域p),计算点C1=M+rK;C2=rG。将点C1、C2坐标c1x,c1y,c2x,c2y依次存入密文文件。
putin(&mx, miwenx,Residue+1);//文件存入 mp_zero(&my);
for(i=0; i 0)// Residue为剩余字符数 {
if (Residue <= enlongtemp )
{
fread(miwenx,1,Residue,fp);//读入字符串 miwenx[Residue]=char(255);
}
串
else {
fread(miwenx,1,enlongtemp,fp);//读入字符
miwenx[enlongtemp]=char(255);
fread(miweny,1,Residue-enlongtemp,fp);//
读入字符串 入
putin(&my,
putin(&mx, miwenx,enlongtemp+1);//文件存
miweny[Residue-enlongtemp]=char(255);
miweny,Residue-enlongtemp+1);//文件存入
}
//加密
Ecc_points_mul(&c2x,&c2y,px,py,&r,a,p); //C2=rG
Ecc_points_mul(&tempx,&tempy,qx,qy,&r,a,p); // rK
Two_points_add(&mx,&my,&tempx,&tempy,&c1x,&c1y,a,zero,
p);// C1=M+rK
//保存密文
chmistore(&c1x,fq); }
chmistore(&c1y,fq); chmistore(&c2x,fq); chmistore(&c2y,fq);
函数原型为:void Ecc_encipher(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *a,mp_int *p);
八、ECC解密的实现
解密时,依据存密文时放入的结束标志255,读入密文。依次取4段,调用miwendraw将密文存入mp_int型数中,还原为加密时存入的点C1和C2坐标c1x,c1y,c2x,c2y。依据
C1-dC2=M+rK-k(rG)=M+rK-r(kG)=M。计算C1-dC2 (d为私钥),得到明文点坐标mx,my。其中两点减的计算可如下: