1. 程式人生 > >現代應用密碼學中橢圓曲線求點集E以及點乘演算法的java程式碼實現

現代應用密碼學中橢圓曲線求點集E以及點乘演算法的java程式碼實現

【問題】:


(1)生成橢圓曲線有限域上的點集。給定p=211,a=0,b=-4

(2) 給定生成元G(2,2)找出其他點與生成元之間的關係。

【解答】:面多較大的有限域p,依靠手動計算以及不符合實際,因此我在理解橢圓曲線數學原理和點乘演算法的基礎上,用java程式編寫完成了兩個題目的運算。

【程式設計環境】:Eclipse

【程式原始碼】:

import java.lang.Math;
//題目實現:實現有限域上的橢圓曲線群的點乘運算
//y^2=x^3+ax+b p=221,a=0,b=-4, G(2,2) 階為241
public class test2 {        
     final static int P=211;  
     final static int MAX_OF_TIMES = 241;//241
     public int[] dotSet_x= new int[10*P];
     public int[] dotSet_y=new int[10*P];
     public static int i=0,j=0;
     public static int a,b,p;
     public static int x1,y1,x2,y2,Xq,Yq,x,y;//(Xq,Yq)是生成元;(x,y)是結果點
     public static int k;//表示倍點的斜率

     public void createECC(int a1,int b1,int Gx1,int Gy1){
    	 a=a1;
    	 b=b1;
    	 p=P;
    	 Xq=Gx1;
    	 Yq=Gy1; 	   	 
     }
     
     //取模函式
    public static int quyu(int f){
    	 int z=f/P;
    	 int mo= f-(z*P);
    	 if(mo>=0)
    		 return mo;
    	 else
    		 return mo+P;
     }
   //判斷該數的平方根是不是整數
     public int getIntSqrt(int n){
    	 double temp=Math.sqrt(n);
    	 int k=0;
    	 k=(int)temp;
    	 if(k*k==n)
    	   return k;
    	 else
    		 return -1;    	 
     }
     
     public int getDotSet(){   	 
    	 //y^2=x^3+ax+b
    	 int right=0,x=0,y=0;
    	 int modValue;
    	 int sqrtRe,temp=0,n=0;
    	 //0<=x<=P-1
    	 for(x=0;x<=P-1;x++){
    		 right=x*x*x+a*x+b;
    		 if(right>=0){//右邊>=0,可以開平方   			 
    			 modValue=quyu(right);     			
    			 while(y<=P-1){			
    				 temp= modValue+n*P; 
    				 sqrtRe=getIntSqrt(temp);
    		         if(sqrtRe>=0)//表明是整數
    		         {  
    		        	 y=(int)Math.sqrt(temp); 
    		        	 //System.out.println("x="+x+","+"y="+y+","+"n="+n+","+"temp="+temp+"i="+i);
    		        	 dotSet_x[i++]=x;
        		         dotSet_y[j++]=y; 
    		         }    		          		         
    				n++; 
    				y++;
    			 }//while   			   			 
    		 }//if
   		  n=0;//n重置為0
   		  y=0;
    	 }   	 
    	 return i;
     }
     
     //顯示出橢圓曲線的點集
     public void showDotSet(){
    	 for(int i1=0;i1<i;i1++){   
    		 if(i1%10==0) System.out.print("\n");
    		  System.out.print(("("+dotSet_x[i1]+","+dotSet_y[i1]+")"));  		 
    	 }
    	 System.out.println("\ndotSet中元素個數:"+i);
     }
     
 	// 實現倍點運算的方法
 	public static void beidian() {
 		int m = (3 * Xq * Xq + a) * qiuni(2 * Yq);
 		k = quyu(m);
 		int Sx = k * k - 2 * Xq;
 		x = quyu(Sx);
 		int Sy = -Yq + k * (Xq - x);
 		y = quyu(Sy);
 	}

 	// 實現求逆的方法(必須保證z為正數;
 	public static int qiuni(int z) {
 		int s = 0;
 		int u = 0;
 		do {
 			s = u * z % p;
 			u++;
 		} while (s != 1);
 		return u - 1;
 	}
 
 	//點乘運算
     public void getMultiply(int n){
    		if (n == 1) {System.out.print("1*G("+Xq+","+Yq+")=("+x+","+y+")     ");}
			// 倍點計算
			else if (n == 2) {beidian();}
			// 點乘計算
			else {
				int k1;
				// 將2Q作為點P(x1,y1)
				beidian();
				x1 = x;
				y1 = y;
				// 將Q (x2,y2)作為點加的另一個點
				x2 = Xq;
				y2 = Yq;
				// 迴圈實現點乘運算,nQ分解成2Q+(n-2)Q,每次加上一個Q直至算完nQ;
				for (int i = 1; i <= n - 2; i++) {
					if ((x2 - x1) >= 0) {
						k1 = (y2 - y1) * qiuni(x2 - x1);
						k = quyu(k1);
						int Sx = k * k - x1 - x2;
						x = quyu(Sx);
						int Sy = -y1 + k * (x1 - x);
						y = quyu(Sy);
					}else {
						k1 = (y1 - y2) * qiuni(x1 - x2);
						k = quyu(k1);
						int Sx = k * k - x1 - x2;
						x = quyu(Sx);
						int Sy = -y1 + k * (x1 - x);
						y = quyu(Sy);
					}
					x1 = x;
					y1 = y;
				}
        }   	
     }
     //顯示生成元與點集中其他點的點乘關係
     public void showRel(){
    	int n=1;
    	int temp,i1,count=0;
    	for(n=1;n<MAX_OF_TIMES;n++){
    		getMultiply(n);
    	//	System.out.println("倍乘結果:"+x+","+y);  		
    		for(i1=0;i1<i;i1++){
    			if(x==dotSet_x[i1]&&y==dotSet_y[i1])
    				{count++;
    				 if(count%5==0) System.out.print("\n");
    				  System.out.print(n+"*G("+Xq+","+Yq+")=("+x+","+y+")     ");break;
    				}//if
    		}//for
    	}//for  
    	System.out.print("\nthe num of rel is :"+(count+1));
     }

     public static void main(String arg[]){
    	 test2 e1=new test2();
    	 e1.createECC(0, -4, 2, 2);//依次輸入a,b,生成元G的橫座標、縱座標
    	 e1.getDotSet();
    	 e1.showDotSet();   
    	 e1.showRel();   	 
     } 
}

【執行結果截圖】:

按照如下輸入:a=0,b=-4,G(2,2)


可以得到該橢圓曲線在有限域上的點集,一共包含238個元素:


從下圖結果中可以看到,點集中任意一點都和生成元是點乘關係,即點集中任意一點Q都可以表示為


結果正確。