/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
// package ellipticCurve;
import static java.
lang.
Math.
cbrt; import static java.
lang.
Math.
pow; import static java.
lang.
Math.
sqrt; import java.util.ArrayList;
import java.util.Locale;
/**
*
* @author Trần Hoàng
*/
double x, y;
public static void main
(String[] args
) { // /**-----------------------**/
// ELLIPTIC (E) trên trường hữu hạn F(M): y^2 mod M = x^3 + a*x + b mod M
// Khởi tạo các hệ số của (E), M
long a, b, M;
a = (long)1;
b = (long)1;
M = (long)17;
// Chọn điểm cơ sở
// In điểm cơ sở ra
p.inString("P");
// Tìm bậc của (E)
caculateRankECC(p, a, b, M);
/**-----------------------**/
}
}
// Contructor có đối số của thằng Point
public Point(double x,
double y
) { this.x = x;
this.y = y;
}
// Tìm tạo độ điểm x từ điểm y
public Point calXfromY
(double y,
int a,
int b
) { return new Point(cbrt
(pow
(y,
2) - b
), y
); }
// Tạo một điểm zeroPoint ~ 0
public Point zeroPoint
() { }
// Kiểm tra một điểm có là zeroPoint hay không
public static boolean isZeroPoint
(Point p
) { return p.x > 1e18 || p.x < -1e18;
}
// Tạo điểm đối xứng qua trục hoành
public Point negativePoint
() { return new Point(this.
x,
-this.
y); }
public static long pow_modulo(long base, long exponent, long M) {
if(exponent == 0) return 1;
if(exponent == 1) return base;
long half = pow_modulo(base, exponent/2, M);
if((exponent&1) > 0) return (((half*half)%M)*base)%M;
else return (half*half)%M;
}
public static long modulo_invert_fermat(long n, long M) {
return pow_modulo(n, M-2, M);
}
public static long modNegative(long y, long N) {
if(y < (long)0) {
return ((y+N)%N);
}
return (y%N);
}
public static Point duplicatedPointModN
(Point p,
long a,
long b,
long N
) { if( isZeroPoint(p) ) {
return p;
}
// delta = (3*(xP^2) + a) / ( 2*(yP)
long delta_tu = (long)(3*p.x*p.x) + a;
long delta_mau = 2*(long)p.y;
// vì sau khi tính delta có thể âm nên ta cần mod cho N để hết âm
delta_tu = modNegative(delta_tu, N);
delta_mau = modNegative(delta_mau, N);
// delta = delta_tu/delta_mau => cần tính mod nghịch đảo
// Nếu delta_mau chia hết cho N thì không tồn tại modulo nghịch đảo.
if(delta_mau%N == 0) {
System.
out.
println("Khong ton tai modulo nghich dao"); return new Point().
zeroPoint(); }
else {
delta_mau = modulo_invert_fermat(delta_mau, N);
}
long delta = (delta_tu*delta_mau)%N;
System.
out.
println("Nhan delta: " + delta
); // R = 2*P; xR = delta^2 - 2*xP theo (IV)
long xR = ((delta*delta) - 2*(long)p.x);
System.
out.
println("xR: " + xR
); xR = modNegative(xR, N);
System.
out.
println("xR: " + xR
); // R = 2*P; yR = delta*(xP - xR) - yP theo(V)
long yR = (delta*((long)p.x - xR) - (long)p.y);
// System.out.println("yR: " + yR);
yR = modNegative(yR, N);
return new Point((double)xR,
(double )yR
); }
// check 2 điểm P, Q bằng nhau => dùng công thức nhân đôi
if( p.x == q.x && p.y == q.y )
return duplicatedPointModN(p,a, b, N);
// check zeroPoint P
if( isZeroPoint(q) )
return p;
// check zeroPoint Q
if( isZeroPoint(p) )
return q;
/*
Công thức cộng 2 điểm P(xP, yP) và Q(xQ, yQ) trên đường cong Elliptic
P # Q, P #O, Q # O
delta = delta_tu/ delta_mau = (yQ - yP) / (xQ - xP)
*/
long delta_tu = modNegative(((long)q.y - (long)p.y), N);
long delta_mau = modNegative(((long)q.x - (long)p.x), N);
// delta = delta_tu/delta_mau => cần tính mod nghịch đảo
// Nếu delta_mau chia hết cho N thì không tồn tại modulo nghịch đảo.
if(delta_mau%N == 0) {
System.
out.
println("Khong ton tai modulo nghich dao"); return new Point().
zeroPoint(); }
else {
delta_mau = modulo_invert_fermat(delta_mau, N);
}
long delta = (delta_tu*delta_mau)%N;
System.
out.
println("plus - delta: " + delta
); long xR = ((delta*delta) - ((long)p.x + (long)q.x));
System.
out.
println("xR: " + xR
); xR = modNegative(xR, N);
long yR = (delta*((long)p.x - (long)xR) - (long)p.y);
System.
out.
println("yR: " + yR
); yR = modNegative(yR, N);
return new Point((double)xR,
(double)yR
); }
public void inString
(String msg
) { System.
out.
println( msg
+ "(" + x
+ ", " + y
+ ")"); }
public static void caculateRankECC
(Point p,
long a,
long b,
long N
) { int cnt = 0;
// điểm temp là điểm trung gian, dùng để lưu 1 điểm vừa tính được
// Lặp đến khi tìm thấy bậc của ECC
for( int i = 2;; i++) {
cnt++;
if(i == 2) {
temp = duplicatedPointModN(p, a, b, N);
}
else {
temp = plusModN(p, temp, a, b, N);
}
if(isZeroPoint(temp)) {
msg = i + "P = 0\nBậc của #E" + N + " = " + i;
// Kết thúc việc tìm bậc
return;
}
else msg = i+ "P";
temp.inString(msg);
}
}
}
LyoKICogVG8gY2hhbmdlIHRoaXMgbGljZW5zZSBoZWFkZXIsIGNob29zZSBMaWNlbnNlIEhlYWRlcnMgaW4gUHJvamVjdCBQcm9wZXJ0aWVzLgogKiBUbyBjaGFuZ2UgdGhpcyB0ZW1wbGF0ZSBmaWxlLCBjaG9vc2UgVG9vbHMgfCBUZW1wbGF0ZXMKICogYW5kIG9wZW4gdGhlIHRlbXBsYXRlIGluIHRoZSBlZGl0b3IuCiAqLwovLyBwYWNrYWdlIGVsbGlwdGljQ3VydmU7CmltcG9ydCBzdGF0aWMgamF2YS5sYW5nLk1hdGguY2JydDsKaW1wb3J0IHN0YXRpYyBqYXZhLmxhbmcuTWF0aC5wb3c7CmltcG9ydCBzdGF0aWMgamF2YS5sYW5nLk1hdGguc3FydDsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTG9jYWxlOwoKLyoqCiAqCiAqIEBhdXRob3IgVHLhuqduIEhvw6BuZwogKi8KCmNsYXNzIFBvaW50IHsKICAgIAogICAgZG91YmxlIHgsIHk7CiAgICAKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKLy8gICAgICAvKiotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoqLwovLwkJRUxMSVBUSUMgKEUpIHRyw6puIHRyxrDhu51uZyBo4buvdSBo4bqhbiBGKE0pOiAgICAgICAgICAgIHleMiBtb2QgTSA9IHheMyArIGEqeCArIGIgbW9kIE0KLy8JCUto4bufaSB04bqhbyBjw6FjIGjhu4cgc+G7kSBj4bunYSAoRSksIE0KCQlsb25nIGEsIGIsIE07CgkJYSA9IChsb25nKTE7IAoJCWIgPSAobG9uZykxOwoJCU0gPSAobG9uZykxNzsKLy8JCUNo4buNbiDEkWnhu4NtIGPGoSBz4bufCiAgICAgICAgUG9pbnQgcCA9IG5ldyBQb2ludCgwLCAxKTsKLy8JCUluIMSRaeG7g20gY8ahIHPhu58gcmEKICAgICAgICBwLmluU3RyaW5nKCJQIik7Ci8vCQlUw6xtIGLhuq1jIGPhu6dhIChFKQogICAgICAgIGNhY3VsYXRlUmFua0VDQyhwLCBhLCBiLCBNKTsKICAgICAgICAvKiotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoqLyAgICAKICAgIH0KCiAgICBwdWJsaWMgUG9pbnQoKSB7CiAgICB9CiAgICAKICAgIC8vIENvbnRydWN0b3IgY8OzIMSR4buRaSBz4buRIGPhu6dhIHRo4bqxbmcgUG9pbnQKICAgIHB1YmxpYyBQb2ludChkb3VibGUgeCwgZG91YmxlIHkpIHsKICAgICAgICB0aGlzLnggPSB4OwogICAgICAgIHRoaXMueSA9IHk7CiAgICB9CiAgICAvLyBUw6xtIHThuqFvIMSR4buZIMSRaeG7g20geCB04burIMSRaeG7g20geQogICAgcHVibGljIFBvaW50IGNhbFhmcm9tWShkb3VibGUgeSwgaW50IGEsIGludCBiKSB7CiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChjYnJ0KHBvdyh5LDIpIC0gYiksIHkpOwogICAgfQogICAgLy8gVOG6oW8gbeG7mXQgxJFp4buDbSB6ZXJvUG9pbnQgfiAwCiAgICBwdWJsaWMgUG9pbnQgemVyb1BvaW50KCkgewogICAgICAgIHJldHVybiBuZXcgUG9pbnQoRG91YmxlLlBPU0lUSVZFX0lORklOSVRZLCBEb3VibGUuUE9TSVRJVkVfSU5GSU5JVFkpOwogICAgfQogICAgLy8gS2nhu4NtIHRyYSBt4buZdCDEkWnhu4NtIGPDsyBsw6AgemVyb1BvaW50IGhheSBraMO0bmcKICAgIHB1YmxpYyBzdGF0aWMgYm9vbGVhbiBpc1plcm9Qb2ludChQb2ludCBwKSB7CiAgICAgICAgcmV0dXJuIHAueCA+IDFlMTggfHwgcC54IDwgLTFlMTg7CiAgICB9CiAgICAvLyBU4bqhbyDEkWnhu4NtIMSR4buRaSB44bupbmcgcXVhIHRy4bulYyBob8OgbmgKICAgIHB1YmxpYyBQb2ludCBuZWdhdGl2ZVBvaW50KCkgewogICAgICAgIHJldHVybiBuZXcgUG9pbnQodGhpcy54LCAtdGhpcy55KTsKICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyBsb25nIHBvd19tb2R1bG8obG9uZyBiYXNlLCBsb25nIGV4cG9uZW50LCBsb25nIE0pIHsKICAgICAgICBpZihleHBvbmVudCA9PSAwKSByZXR1cm4gMTsKICAgICAgICBpZihleHBvbmVudCA9PSAxKSByZXR1cm4gYmFzZTsKICAgICAgICBsb25nIGhhbGYgPSBwb3dfbW9kdWxvKGJhc2UsIGV4cG9uZW50LzIsIE0pOwogICAgICAgIGlmKChleHBvbmVudCYxKSA+IDApIHJldHVybiAoKChoYWxmKmhhbGYpJU0pKmJhc2UpJU07CiAgICAgICAgZWxzZSByZXR1cm4gKGhhbGYqaGFsZiklTTsgCiAgICB9CiAgICAKICAgIHB1YmxpYyBzdGF0aWMgbG9uZyBtb2R1bG9faW52ZXJ0X2Zlcm1hdChsb25nIG4sIGxvbmcgTSkgewogICAgICAgIHJldHVybiBwb3dfbW9kdWxvKG4sIE0tMiwgTSk7CiAgICB9CiAgICAKICAgIHB1YmxpYyBzdGF0aWMgbG9uZyBtb2ROZWdhdGl2ZShsb25nIHksIGxvbmcgTikgewogICAgICAgIGlmKHkgPCAobG9uZykwKSB7CiAgICAgICAgICAgIHkgPSBOKk1hdGguYWJzKHkvTikgKyB5OwogICAgICAgICAgICByZXR1cm4gKCh5K04pJU4pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKHklTik7CiAgICB9CiAgICAKICAgIHB1YmxpYyBzdGF0aWMgUG9pbnQgZHVwbGljYXRlZFBvaW50TW9kTihQb2ludCBwLCBsb25nIGEsIGxvbmcgYiwgbG9uZyBOKSB7CiAgICAgICAgaWYoIGlzWmVyb1BvaW50KHApICkgewogICAgICAgICAgICByZXR1cm4gcDsKICAgICAgICB9CiAgICAgICAgLy8gZGVsdGEgPSAoMyooeFBeMikgKyBhKSAvICggMiooeVApCiAgICAgICAgbG9uZyBkZWx0YV90dSA9IChsb25nKSgzKnAueCpwLngpICsgYTsKICAgICAgICBsb25nIGRlbHRhX21hdSA9ICAyKihsb25nKXAueTsKICAgICAgICAvLyB2w6wgc2F1IGtoaSB0w61uaCBkZWx0YSBjw7MgdGjhu4Mgw6JtIG7Dqm4gdGEgY+G6p24gbW9kIGNobyBOIMSR4buDIGjhur90IMOibQogICAgICAgIGRlbHRhX3R1ID0gbW9kTmVnYXRpdmUoZGVsdGFfdHUsIE4pOwogICAgICAgIGRlbHRhX21hdSA9IG1vZE5lZ2F0aXZlKGRlbHRhX21hdSwgTik7CiAgICAgICAgLy8gZGVsdGEgPSBkZWx0YV90dS9kZWx0YV9tYXUgPT4gY+G6p24gdMOtbmggbW9kIG5naOG7i2NoIMSR4bqjbwogICAgICAgIC8vIE7hur91IGRlbHRhX21hdSBjaGlhIGjhur90IGNobyBOIHRow6wga2jDtG5nIHThu5NuIHThuqFpIG1vZHVsbyBuZ2jhu4tjaCDEkeG6o28uCiAgICAgICAgaWYoZGVsdGFfbWF1JU4gPT0gMCkgewogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIktob25nIHRvbiB0YWkgbW9kdWxvIG5naGljaCBkYW8iKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludCgpLnplcm9Qb2ludCgpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZGVsdGFfbWF1ID0gbW9kdWxvX2ludmVydF9mZXJtYXQoZGVsdGFfbWF1LCBOKTsKICAgICAgICB9CiAgICAgICAgbG9uZyBkZWx0YSA9IChkZWx0YV90dSpkZWx0YV9tYXUpJU47CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJOaGFuIGRlbHRhOiAiICsgZGVsdGEpOwogICAgICAgIC8vIFIgPSAyKlA7IHhSID0gZGVsdGFeMiAtIDIqeFAgdGhlbyAoSVYpCiAgICAgICAgbG9uZyB4UiA9ICgoZGVsdGEqZGVsdGEpIC0gMioobG9uZylwLngpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigieFI6ICIgKyB4Uik7CiAgICAgICAgeFIgPSBtb2ROZWdhdGl2ZSh4UiwgTik7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJ4UjogIiArIHhSKTsKICAgICAgICAvLyBSID0gMipQOyB5UiA9IGRlbHRhKih4UCAtIHhSKSAtIHlQIHRoZW8oVikKICAgICAgICBsb25nIHlSID0gKGRlbHRhKigobG9uZylwLnggLSB4UikgLSAobG9uZylwLnkpOwovLyAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJ5UjogIiArIHlSKTsKICAgICAgICB5UiA9IG1vZE5lZ2F0aXZlKHlSLCBOKTsKICAgICAgICByZXR1cm4gbmV3IFBvaW50KChkb3VibGUpeFIsIChkb3VibGUgKXlSKTsKICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyBQb2ludCBwbHVzTW9kTihQb2ludCBwLCBQb2ludCBxLCBsb25nIGEsIGxvbmcgYiwgbG9uZyBOKSB7CiAgICAgICAgLy8gY2hlY2sgMiDEkWnhu4NtIFAsIFEgYuG6sW5nIG5oYXUgPT4gZMO5bmcgY8O0bmcgdGjhu6ljIG5ow6JuIMSRw7RpCiAgICAgICAgaWYoIHAueCA9PSBxLnggJiYgcC55ID09IHEueSApIAogICAgICAgICAgICByZXR1cm4gZHVwbGljYXRlZFBvaW50TW9kTihwLGEsIGIsIE4pOwogICAgICAgIC8vIGNoZWNrIHplcm9Qb2ludCBQCiAgICAgICAgaWYoIGlzWmVyb1BvaW50KHEpICkKICAgICAgICAgICAgcmV0dXJuIHA7CiAgICAgICAgLy8gY2hlY2sgemVyb1BvaW50IFEKICAgICAgICBpZiggaXNaZXJvUG9pbnQocCkgKQogICAgICAgICAgICByZXR1cm4gcTsKICAgICAgICAvKgogICAgICAgICAgICBDw7RuZyB0aOG7qWMgY+G7mW5nIDIgxJFp4buDbSBQKHhQLCB5UCkgdsOgIFEoeFEsIHlRKSB0csOqbiDEkcaw4budbmcgY29uZyBFbGxpcHRpYwogICAgICAgICAgICBQICMgUSwgUCAjTywgUSAjIE8KICAgICAgICAgICAgZGVsdGEgPSBkZWx0YV90dS8gZGVsdGFfbWF1ID0gKHlRIC0geVApIC8gKHhRIC0geFApCiAgICAgICAgKi8KICAgICAgICBsb25nIGRlbHRhX3R1ID0gbW9kTmVnYXRpdmUoKChsb25nKXEueSAtIChsb25nKXAueSksIE4pOwogICAgICAgIGxvbmcgZGVsdGFfbWF1ID0gbW9kTmVnYXRpdmUoKChsb25nKXEueCAtIChsb25nKXAueCksIE4pOwogICAgICAgIAogICAgICAgIC8vIGRlbHRhID0gZGVsdGFfdHUvZGVsdGFfbWF1ID0+IGPhuqduIHTDrW5oIG1vZCBuZ2jhu4tjaCDEkeG6o28KICAgICAgICAvLyBO4bq/dSBkZWx0YV9tYXUgY2hpYSBo4bq/dCBjaG8gTiB0aMOsIGtow7RuZyB04buTbiB04bqhaSBtb2R1bG8gbmdo4buLY2ggxJHhuqNvLgogICAgICAgIGlmKGRlbHRhX21hdSVOID09IDApIHsKICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJLaG9uZyB0b24gdGFpIG1vZHVsbyBuZ2hpY2ggZGFvIik7CiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoKS56ZXJvUG9pbnQoKTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGRlbHRhX21hdSA9IG1vZHVsb19pbnZlcnRfZmVybWF0KGRlbHRhX21hdSwgTik7CiAgICAgICAgfQogICAgICAgIGxvbmcgZGVsdGEgPSAoZGVsdGFfdHUqZGVsdGFfbWF1KSVOOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigicGx1cyAtIGRlbHRhOiAiICsgZGVsdGEpOwogICAgICAgIGxvbmcgeFIgPSAoKGRlbHRhKmRlbHRhKSAtICgobG9uZylwLnggKyAobG9uZylxLngpKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInhSOiAiICsgeFIpOwogICAgICAgIHhSID0gbW9kTmVnYXRpdmUoeFIsIE4pOwogICAgICAgIGxvbmcgeVIgPSAoZGVsdGEqKChsb25nKXAueCAtIChsb25nKXhSKSAtIChsb25nKXAueSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJ5UjogIiArIHlSKTsKICAgICAgICB5UiA9IG1vZE5lZ2F0aXZlKHlSLCBOKTsKICAgICAgICByZXR1cm4gbmV3IFBvaW50KChkb3VibGUpeFIsIChkb3VibGUpeVIpOwogICAgfQogICAgCiAgICBwdWJsaWMgdm9pZCBpblN0cmluZyhTdHJpbmcgbXNnKSB7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCBtc2cgKyAiKCIgKyB4ICsgIiwgIiArIHkgKyAiKSIpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBjYWN1bGF0ZVJhbmtFQ0MoUG9pbnQgcCwgbG9uZyBhLCBsb25nIGIsIGxvbmcgTikgewogICAgICAgIGludCBjbnQgPSAwOwogICAgICAgIC8vIMSRaeG7g20gdGVtcCBsw6AgxJFp4buDbSB0cnVuZyBnaWFuLCBkw7luZyDEkeG7gyBsxrB1IDEgxJFp4buDbSB24burYSB0w61uaCDEkcaw4bujYwogICAgICAgIFBvaW50IHRlbXAgPSBuZXcgUG9pbnQoKS56ZXJvUG9pbnQoKTsKICAgICAgICAvLyBM4bq3cCDEkeG6v24ga2hpIHTDrG0gdGjhuqV5IGLhuq1jIGPhu6dhIEVDQwogICAgICAgIGZvciggaW50IGkgPSAyOzsgaSsrKSB7CiAgICAgICAgICAgIGNudCsrOwogICAgICAgICAgICBpZihpID09IDIpIHsKICAgICAgICAgICAgICAgIHRlbXAgPSBkdXBsaWNhdGVkUG9pbnRNb2ROKHAsIGEsIGIsIE4pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdGVtcCA9IHBsdXNNb2ROKHAsIHRlbXAsIGEsIGIsIE4pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIFN0cmluZyBtc2cgPSAiIjsKICAgICAgICAgICAgaWYoaXNaZXJvUG9pbnQodGVtcCkpIHsKICAgICAgICAgICAgICAgIG1zZyA9IGkgKyAiUCA9IDBcbkLhuq1jIGPhu6dhICNFIiArIE4gKyAiID0gIiArIGk7CiAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4obXNnKTsKICAgICAgICAgICAgICAgIC8vIEvhur90IHRow7pjIHZp4buHYyB0w6xtIGLhuq1jCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBtc2cgPSBpKyAiUCI7CiAgICAgICAgICAgIHRlbXAuaW5TdHJpbmcobXNnKTsKICAgICAgICB9CiAgICB9Cn0K