現代應用密碼學中橢圓曲線求點集E以及點乘演算法的java程式碼實現
阿新 • • 發佈:2019-01-29
【問題】:
(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都可以表示為:
結果正確。