椭圆曲线ECC倍点运算forJava

前段时间写一个审计系统时,用到了椭圆曲线的数字签名技术。 在计算其倍点时,一开始我使用点与点相加的基本算式进行迭代运算。 但发现效率很低。最后想了想,进行了如下的改进(其实也是参考《密码编码学与网络安全》第6版一书中的一个思路,进行了如下的书写)。


package com.pathfinder.function;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName:  Algorithm   
 * @Description:倍点运算
 * @author: muliming / mulming@163.com
 * @date:   2017年10月29日 下午6:56:39     
 * @Copyright: 2017
 */
public class Algorithm {
private int a;
private int b;
private int q; 

public Algorithm(int a, int b, int q) {
this.a = a;
this.b = b;
this.q = q;
}

public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public int getQ() {
return q;
}
public void setQ(int q) {
this.q = q;
}

/**
* @Title: OutsAlgorithm   
* @Description: 倍点运算,给定一个点,进行倍数的计算【具体:把要计算的值,转为二进制数,然后在二进制的每位上做相应的二倍运算,最后再把所有的相加】
* @param: @param    s: 点      n: 需要计算的倍数
* @return: String      
*/
public String OutsAlgorithm(long n,String s)
{
List<Byte> er=new ArrayList<Byte>();//存放转化为二进制的数
List<String> dian=new ArrayList<String>();
if(n!=0)
{
//把要计算的值,转为二进制数,然后在二进制的每位上做相应的二倍运算,最后再把所有的相加
while(n!=0)
{
byte i=(byte)(n%2);
er.add(i);
n=n/2;
}
for(int i=0;i<er.size();i++)
{
if(er.get(i)==1)
dian.add(s);
s=multiple2Operation(s);//二倍  倍点运算算法 计算一个点的n倍的算法
}
s=dian.get(0);

for(int i=1;i<dian.size();i++)
{
s=addOperation(s, dian.get(i));//计算两个不同点相加的运算
}
return s;
}
else
{
return "0v0";
}
}


/**
* @Title: multiple2Operation   
* @Description:计算一个点的2倍的值
* @param: @param g:要计算的点
* @return: String   v点的2倍的值  
*/
public String multiple2Operation(String g)
{
int x=2;
String[] vp=g.split("v");
int xp=Integer.parseInt(vp[0]);
int yp=Integer.parseInt(vp[1]);

if(yp==0)
{
return  "0v0"; //TODO y为0的时候怎么办?
}
else
{
long Numerator=3*xp*xp+a;//分子
    long denominator=2*yp;//分母
    
    denominator=niyuan(denominator,q,1,0);// 计算分母的逆元
    
    while(denominator<0)
    {
    denominator=denominator+q;
    }

    long ratio=(long)(Numerator*denominator)%q;//计算  入  的值  及斜率

long xrr=(long)(ratio*ratio-2*xp);
while(xrr<0)
{
xrr=xrr+q;
}
int Xr=(int)(xrr%q);//横坐标

long Yrr=(long)(ratio*(xp-Xr)-yp);
while(Yrr<0)
{
Yrr=Yrr+q;
}
int Yr=(int)(Yrr%q);

return Xr+"v"+Yr;//返回2倍点的坐标
}
}

/**
* @Title: addOperation   
* @Description: 计算两个不同点相加的运算
* @param: @param V  点
* @param: @param v1 点
* @return: String    
*/
public String addOperation(String V,String v1)
{
if(v1.equals(V))
{
return multiple2Operation(V);//如果两个点相等,直接调用倍点运算
}
else
{
String[] vp=V.split("v");
String[] vq=v1.split("v");
if(vp[0].equals(vq[0]))//两个的x值相等
{
return "0v0";
}
else
{
//排错
if(v1.equals("0v0"))
return V;
else if(V.equals("0v0"))
return v1;
//运算
else
{
//第一个点的x y坐标
int xp=Integer.parseInt(vp[0]);
int yp=Integer.parseInt(vp[1]);
//第二个点的x y坐标
int xq=Integer.parseInt(vq[0]);
int yq=Integer.parseInt(vq[1]);

long DValueY=(long)yq-yp;//y的差值

while(DValueY<0)
{
DValueY=DValueY+q;
}
long DValueX=(long)xq-xp;//x的差值
while(DValueX<0)
{
DValueX=DValueX+q;
}

DValueX=niyuan(DValueX,q,1,0);
    while(DValueX<0)
    {
    DValueX=DValueX+q;
    }

    long ratio=(long)(DValueY*DValueX)%q;

long xrr=(long)(ratio*ratio-xp-xq);
while(xrr<0)
{
xrr=xrr+q;
}
int xr=(int)(xrr%q);
long yrr=(long)(ratio*(xp-xr)-yp);
while(yrr<0)
{
yrr=yrr+q;
}
int yr=(int)(yrr%q);
//返回值
return xr+"v"+yr;
}
}
}
}


/**
* @Title: niyuan  就是扩展的欧几里得算法,具体可参看我的另一篇   
* @Description: 计算逆元  及分数得模运算
* @param: @param r1L2 --》2yp  先计算r1分之1关于r2的逆元
* @param: @param r2p:椭圆曲线参数p
* @param: @param x11
* @param: @param x20
* @param: @return   分母的逆元
* @return: long      
*/
public long niyuan(long r1,long r2,long x1,long x2)
{
long qr=r1/r2;
long r=r1%r2;
long x=x1-qr*x2;
if(r==1)
{
return x;
}
else
return niyuan(r2,r,x2,x);
}
//END
}

欢迎各位大侠提出意见。相互学习

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值