橢圓曲線算法的基本原理及實現


1、基本概念

1)橢圓曲線方程的一般形式:y^2 = x^3 + a*x + b,其中要求滿足不等式 4*a^3 + 27*b^2 ≠ 0

例如:y^2 = x^3 + x + 1 mod 23

2)橢圓曲線上的點的加法公式(適用於 P ≠ Q 的情況):設 P = (x1, y1),Q = (x2, y2),P + Q = R = (x3, y3),t = (y2-y1)/(x2-x1),x3 = t^2 - x1 - x2,y3 = t*(x1 - x3) - y1

3)橢圓曲線上的點的加法公式(當上面的 P = Q 時):P + P = R = (x3, y3),t = (3*x1^2+a)/(2*y1),x3 = t^2 - x1 - x1,y3 = t*(x1 - x3) - y1

 

2、准備步驟

1)隨機生成一個數 d 做私鑰

2)選橢圓曲線上的一個點 P,計算 Q = d*P 做公鑰

 

設 A 要加密 M 送給 B,B 的私鑰為 d,公鑰為 Q = d*P

3、加密過程

1)A 隨機生成一個數 k

2)計算 k*P 和 k*Q

3)取 k*Q 的橫坐標與 M 異或得到密文 C

4)A 發送 k*P 和密文 C 給 B

 

4、解密過程

1)B 用自己的私鑰 d 計算 d*(k*P)

2)B 用 d*(k*P) 的橫坐標與密文 C 異或得到 M

 

5、加密及解密的實現

  1 import java.util.ArrayList;
  2 import java.util.HashMap;
  3 
  4 public class Main {
  5     // 選用的橢圓曲線為 y^2 = x^3 + x + 1 mod 23
  6     private static int a = 1, b = 1;
  7     private static HashMap<Integer, Integer> myPoints = new HashMap<>();
  8     private static final int MAX = 255;
  9 
 10     public static void main(String[] args) {
 11         // 明文和密文數組的初始化
 12         char[] myInfo = "1700802067GJQ".toCharArray();
 13         int[] i_mingwen = new int[myInfo.length];
 14         int[] miwen = new int[i_mingwen.length];
 15         char[] c_mingwen = new char[miwen.length];
 16         for (int i = 0; i < myInfo.length; i++) {
 17             i_mingwen[i] = (int)myInfo[i];
 18         }
 19 
 20         // 初始化橢圓曲線上的整數點
 21         initPoints();
 22 
 23         // 顯示橢圓曲線上的整數點
 24         // showPoints();
 25         
 26         // 獲取橢圓曲線上點的橫坐標集合
 27         Object[] objArr = myPoints.keySet().toArray();
 28         ArrayList<Integer> myList = new ArrayList<>();
 29         for (Object o: objArr) {
 30             myList.add((Integer) o);
 31         }
 32 
 33         // 隨機取橢圓曲線上一個點
 34         int Px = myList.get((int)(Math.random()*myList.size()));
 35         int Py = myPoints.get(Px);
 36         MyPoint p = new MyPoint(Px, Py);
 37 
 38         // 隨機取一個 8bit 的數作為私鑰
 39         int d = (int)(Math.random()*MAX) + 1;
 40         // 計算Q
 41         MyPoint Q = new MyPoint(p);
 42         myECC(Q, 1, d);
 43 
 44         // 隨機取一個 8bit 的數k
 45         int k = (int)(Math.random()*MAX) + 1;
 46 
 47         // 計算 k*P 和 k*Q
 48         MyPoint kP = new MyPoint(p);
 49         myECC(kP, 1, k);
 50         MyPoint kQ = new MyPoint(Q);
 51         myECC(kQ, 1, k);
 52         
 53         // 加密
 54         int kQx = kQ.getX();
 55         for (int i = 0; i < i_mingwen.length; i++) {
 56             miwen[i] = i_mingwen[i] ^ kQx;
 57         }
 58         
 59         // 計算d*(k*P)
 60         MyPoint dkP = new MyPoint(kP);
 61         myECC(dkP, 1, d);
 62 
 63         // 解密
 64         int dkPx = dkP.getX();
 65         for (int i = 0; i < miwen.length; i++) {
 66             c_mingwen[i] = (char) (miwen[i] ^ dkPx);
 67         }
 68 
 69         // 輸出對密文解密后的明文
 70         System.out.println(c_mingwen);
 71     }
 72 
 73     public static void initPoints() {
 74         double y;
 75         for (int i = 0; i < 23; i++) {
 76             y = Math.sqrt((Math.pow(i, 3) + i + 1)%23);
 77             if (y == (int)y) myPoints.put(i, (int)y);
 78         }
 79     }
 80 
 81     public static void myECC(MyPoint p, int i, int d){
 82         if (i < d) {
 83             int t = (3*(int)Math.pow(p.getX(), 2)+a)/(2*p.getY());
 84             int x = (int)(Math.pow(t, 2)) - 2*p.getX();
 85             int y = t*(p.getX() - x) - p.getY();
 86             p.setX(x);
 87             p.setY(y);
 88             myECC(p, i+1, d);
 89         }
 90     }
 91 
 92     public static void showPoints() {
 93         myPoints.forEach((k, v) -> {
 94             System.out.println("key: " + k + ", " + "value: " + v);
 95         });
 96     }
 97 }
 98 
 99 class MyPoint {
100     private int x;
101     private int y;
102     MyPoint() {}
103     MyPoint(int x, int y) {
104         this.x = x;
105         this.y = y;
106     }
107     MyPoint(MyPoint P) {
108         this.x = P.getX();
109         this.y = P.getY();
110     }
111     public void setX(int x) {
112         this.x = x;
113     }
114     public void setY(int y) {
115         this.y = y;
116     }
117     public int getX() {
118         return this.x;
119     }
120     public int getY() {
121         return this.y;
122     }
123 }

 

6、注解:

1)A 用 k*P 與 B 用 d*(k*P) = k*(d*P) = k*Q

2)經過兩次異或得到原文(明文)

 

參考文檔:

https://wenku.baidu.com/view/ff42b6610b1c59eef8c7b477.html

遇到的疑問(已解決):

1)Objct[] 數組不能直接轉換為 ArrayList。

2)函數不能返回兩個值,可以將要返回的值放入對象中,在函數中改變對象的值。

遇到的疑問(未解決):

1)P點的橫縱坐標對后續的計算並無影響,即可以不取橢圓曲線上的點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM