/*
* 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+G7kSBj4bunYSAoRSksIE0KCQlsb25nIGEsIGIsIE07CgkJYSA9IChsb25nKTE7IAoJCWIgPSAobG9uZykxOwoJCU0gPSAobG9uZykxNzsKLy8JCUNo4buNbiDEkWnhu4NtIGPGoSBz4bufCiAgICAgICAgUG9pbnQgcCA9IG5ldyBQb2ludCgxNiwgMTMpOwovLwkJSW4gxJFp4buDbSBjxqEgc+G7nyByYQogICAgICAgIHAuaW5TdHJpbmcoIlAiKTsKLy8JCVTDrG0gYuG6rWMgY+G7p2EgKEUpCiAgICAgICAgY2FjdWxhdGVSYW5rRUNDKHAsIGEsIGIsIE0pOwogICAgICAgIC8qKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKiovICAgIAogICAgfQoKICAgIHB1YmxpYyBQb2ludCgpIHsKICAgIH0KICAgIAogICAgLy8gQ29udHJ1Y3RvciBjw7MgxJHhu5FpIHPhu5EgY+G7p2EgdGjhurFuZyBQb2ludAogICAgcHVibGljIFBvaW50KGRvdWJsZSB4LCBkb3VibGUgeSkgewogICAgICAgIHRoaXMueCA9IHg7CiAgICAgICAgdGhpcy55ID0geTsKICAgIH0KICAgIC8vIFTDrG0gdOG6oW8gxJHhu5kgxJFp4buDbSB4IHThu6sgxJFp4buDbSB5CiAgICBwdWJsaWMgUG9pbnQgY2FsWGZyb21ZKGRvdWJsZSB5LCBpbnQgYSwgaW50IGIpIHsKICAgICAgICByZXR1cm4gbmV3IFBvaW50KGNicnQocG93KHksMikgLSBiKSwgeSk7CiAgICB9CiAgICAvLyBU4bqhbyBt4buZdCDEkWnhu4NtIHplcm9Qb2ludCB+IDAKICAgIHB1YmxpYyBQb2ludCB6ZXJvUG9pbnQoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBQb2ludChEb3VibGUuUE9TSVRJVkVfSU5GSU5JVFksIERvdWJsZS5QT1NJVElWRV9JTkZJTklUWSk7CiAgICB9CiAgICAvLyBLaeG7g20gdHJhIG3hu5l0IMSRaeG7g20gY8OzIGzDoCB6ZXJvUG9pbnQgaGF5IGtow7RuZwogICAgcHVibGljIHN0YXRpYyBib29sZWFuIGlzWmVyb1BvaW50KFBvaW50IHApIHsKICAgICAgICByZXR1cm4gcC54ID4gMWUxOCB8fCBwLnggPCAtMWUxODsKICAgIH0KICAgIC8vIFThuqFvIMSRaeG7g20gxJHhu5FpIHjhu6luZyBxdWEgdHLhu6VjIGhvw6BuaAogICAgcHVibGljIFBvaW50IG5lZ2F0aXZlUG9pbnQoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBQb2ludCh0aGlzLngsIC10aGlzLnkpOwogICAgfQogICAgCiAgICBwdWJsaWMgc3RhdGljIGxvbmcgcG93X21vZHVsbyhsb25nIGJhc2UsIGxvbmcgZXhwb25lbnQsIGxvbmcgTSkgewogICAgICAgIGlmKGV4cG9uZW50ID09IDApIHJldHVybiAxOwogICAgICAgIGlmKGV4cG9uZW50ID09IDEpIHJldHVybiBiYXNlOwogICAgICAgIGxvbmcgaGFsZiA9IHBvd19tb2R1bG8oYmFzZSwgZXhwb25lbnQvMiwgTSk7CiAgICAgICAgaWYoKGV4cG9uZW50JjEpID4gMCkgcmV0dXJuICgoKGhhbGYqaGFsZiklTSkqYmFzZSklTTsKICAgICAgICBlbHNlIHJldHVybiAoaGFsZipoYWxmKSVNOyAKICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyBsb25nIG1vZHVsb19pbnZlcnRfZmVybWF0KGxvbmcgbiwgbG9uZyBNKSB7CiAgICAgICAgcmV0dXJuIHBvd19tb2R1bG8obiwgTS0yLCBNKTsKICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyBsb25nIG1vZE5lZ2F0aXZlKGxvbmcgeSwgbG9uZyBOKSB7CiAgICAgICAgaWYoeSA8IChsb25nKTApIHsKICAgICAgICAgICAgeSA9IE4qTWF0aC5hYnMoeS9OKSArIHk7CiAgICAgICAgICAgIHJldHVybiAoKHkrTiklTik7CiAgICAgICAgfQogICAgICAgIHJldHVybiAoeSVOKTsKICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyBQb2ludCBkdXBsaWNhdGVkUG9pbnRNb2ROKFBvaW50IHAsIGxvbmcgYSwgbG9uZyBiLCBsb25nIE4pIHsKICAgICAgICBpZiggaXNaZXJvUG9pbnQocCkgKSB7CiAgICAgICAgICAgIHJldHVybiBwOwogICAgICAgIH0KICAgICAgICAvLyBkZWx0YSA9ICgzKih4UF4yKSArIGEpIC8gKCAyKih5UCkKICAgICAgICBsb25nIGRlbHRhX3R1ID0gKGxvbmcpKDMqcC54KnAueCkgKyBhOwogICAgICAgIGxvbmcgZGVsdGFfbWF1ID0gIDIqKGxvbmcpcC55OwogICAgICAgIC8vIHbDrCBzYXUga2hpIHTDrW5oIGRlbHRhIGPDsyB0aOG7gyDDom0gbsOqbiB0YSBj4bqnbiBtb2QgY2hvIE4gxJHhu4MgaOG6v3Qgw6JtCiAgICAgICAgZGVsdGFfdHUgPSBtb2ROZWdhdGl2ZShkZWx0YV90dSwgTik7CiAgICAgICAgZGVsdGFfbWF1ID0gbW9kTmVnYXRpdmUoZGVsdGFfbWF1LCBOKTsKICAgICAgICAvLyBkZWx0YSA9IGRlbHRhX3R1L2RlbHRhX21hdSA9PiBj4bqnbiB0w61uaCBtb2Qgbmdo4buLY2ggxJHhuqNvCiAgICAgICAgLy8gTuG6v3UgZGVsdGFfbWF1IGNoaWEgaOG6v3QgY2hvIE4gdGjDrCBraMO0bmcgdOG7k24gdOG6oWkgbW9kdWxvIG5naOG7i2NoIMSR4bqjby4KICAgICAgICBpZihkZWx0YV9tYXUlTiA9PSAwKSB7CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiS2hvbmcgdG9uIHRhaSBtb2R1bG8gbmdoaWNoIGRhbyIpOwogICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KCkuemVyb1BvaW50KCk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBkZWx0YV9tYXUgPSBtb2R1bG9faW52ZXJ0X2Zlcm1hdChkZWx0YV9tYXUsIE4pOwogICAgICAgIH0KICAgICAgICBsb25nIGRlbHRhID0gKGRlbHRhX3R1KmRlbHRhX21hdSklTjsKLy8gICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiTmhhbiBkZWx0YTogIiArIGRlbHRhKTsKICAgICAgICAvLyBSID0gMipQOyB4UiA9IGRlbHRhXjIgLSAyKnhQIHRoZW8gKElWKQogICAgICAgIGxvbmcgeFIgPSAoKGRlbHRhKmRlbHRhKSAtIDIqKGxvbmcpcC54KTsKLy8gICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigieFI6ICIgKyB4Uik7CiAgICAgICAgeFIgPSBtb2ROZWdhdGl2ZSh4UiwgTik7Ci8vICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInhSOiAiICsgeFIpOwogICAgICAgIC8vIFIgPSAyKlA7IHlSID0gZGVsdGEqKHhQIC0geFIpIC0geVAgdGhlbyhWKQogICAgICAgIGxvbmcgeVIgPSAoZGVsdGEqKChsb25nKXAueCAtIHhSKSAtIChsb25nKXAueSk7Ci8vICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInlSOiAiICsgeVIpOwogICAgICAgIHlSID0gbW9kTmVnYXRpdmUoeVIsIE4pOwogICAgICAgIHJldHVybiBuZXcgUG9pbnQoKGRvdWJsZSl4UiwgKGRvdWJsZSApeVIpOwogICAgfQogICAgCiAgICBwdWJsaWMgc3RhdGljIFBvaW50IHBsdXNNb2ROKFBvaW50IHAsIFBvaW50IHEsIGxvbmcgYSwgbG9uZyBiLCBsb25nIE4pIHsKICAgICAgICAvLyBjaGVjayAyIMSRaeG7g20gUCwgUSBi4bqxbmcgbmhhdSA9PiBkw7luZyBjw7RuZyB0aOG7qWMgbmjDom4gxJHDtGkKICAgICAgICBpZiggcC54ID09IHEueCAmJiBwLnkgPT0gcS55ICkgCiAgICAgICAgICAgIHJldHVybiBkdXBsaWNhdGVkUG9pbnRNb2ROKHAsYSwgYiwgTik7CiAgICAgICAgLy8gY2hlY2sgemVyb1BvaW50IFAKICAgICAgICBpZiggaXNaZXJvUG9pbnQocSkgKQogICAgICAgICAgICByZXR1cm4gcDsKICAgICAgICAvLyBjaGVjayB6ZXJvUG9pbnQgUQogICAgICAgIGlmKCBpc1plcm9Qb2ludChwKSApCiAgICAgICAgICAgIHJldHVybiBxOwogICAgICAgIC8qCiAgICAgICAgICAgIEPDtG5nIHRo4bupYyBj4buZbmcgMiDEkWnhu4NtIFAoeFAsIHlQKSB2w6AgUSh4USwgeVEpIHRyw6puIMSRxrDhu51uZyBjb25nIEVsbGlwdGljCiAgICAgICAgICAgIFAgIyBRLCBQICNPLCBRICMgTwogICAgICAgICAgICBkZWx0YSA9IGRlbHRhX3R1LyBkZWx0YV9tYXUgPSAoeVEgLSB5UCkgLyAoeFEgLSB4UCkKICAgICAgICAqLwogICAgICAgIGxvbmcgZGVsdGFfdHUgPSBtb2ROZWdhdGl2ZSgoKGxvbmcpcS55IC0gKGxvbmcpcC55KSwgTik7CiAgICAgICAgbG9uZyBkZWx0YV9tYXUgPSBtb2ROZWdhdGl2ZSgoKGxvbmcpcS54IC0gKGxvbmcpcC54KSwgTik7CiAgICAgICAgCiAgICAgICAgLy8gZGVsdGEgPSBkZWx0YV90dS9kZWx0YV9tYXUgPT4gY+G6p24gdMOtbmggbW9kIG5naOG7i2NoIMSR4bqjbwogICAgICAgIC8vIE7hur91IGRlbHRhX21hdSBjaGlhIGjhur90IGNobyBOIHRow6wga2jDtG5nIHThu5NuIHThuqFpIG1vZHVsbyBuZ2jhu4tjaCDEkeG6o28uCiAgICAgICAgaWYoZGVsdGFfbWF1JU4gPT0gMCkgewogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIktob25nIHRvbiB0YWkgbW9kdWxvIG5naGljaCBkYW8iKTsKICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludCgpLnplcm9Qb2ludCgpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZGVsdGFfbWF1ID0gbW9kdWxvX2ludmVydF9mZXJtYXQoZGVsdGFfbWF1LCBOKTsKICAgICAgICB9CiAgICAgICAgbG9uZyBkZWx0YSA9IChkZWx0YV90dSpkZWx0YV9tYXUpJU47Ci8vICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInBsdXMgLSBkZWx0YTogIiArIGRlbHRhKTsKICAgICAgICBsb25nIHhSID0gKChkZWx0YSpkZWx0YSkgLSAoKGxvbmcpcC54ICsgKGxvbmcpcS54KSk7Ci8vICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInhSOiAiICsgeFIpOwogICAgICAgIHhSID0gbW9kTmVnYXRpdmUoeFIsIE4pOwogICAgICAgIGxvbmcgeVIgPSAoZGVsdGEqKChsb25nKXAueCAtIChsb25nKXhSKSAtIChsb25nKXAueSk7Ci8vICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInlSOiAiICsgeVIpOwogICAgICAgIHlSID0gbW9kTmVnYXRpdmUoeVIsIE4pOwogICAgICAgIHJldHVybiBuZXcgUG9pbnQoKGRvdWJsZSl4UiwgKGRvdWJsZSl5Uik7CiAgICB9CiAgICAKICAgIHB1YmxpYyB2b2lkIGluU3RyaW5nKFN0cmluZyBtc2cpIHsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIG1zZyArICIoIiArIHggKyAiLCAiICsgeSArICIpIik7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyB2b2lkIGNhY3VsYXRlUmFua0VDQyhQb2ludCBwLCBsb25nIGEsIGxvbmcgYiwgbG9uZyBOKSB7CiAgICAgICAgaW50IGNudCA9IDA7CiAgICAgICAgLy8gxJFp4buDbSB0ZW1wIGzDoCDEkWnhu4NtIHRydW5nIGdpYW4sIGTDuW5nIMSR4buDIGzGsHUgMSDEkWnhu4NtIHbhu6thIHTDrW5oIMSRxrDhu6NjCiAgICAgICAgUG9pbnQgdGVtcCA9IG5ldyBQb2ludCgpLnplcm9Qb2ludCgpOwogICAgICAgIC8vIEzhurdwIMSR4bq/biBraGkgdMOsbSB0aOG6pXkgYuG6rWMgY+G7p2EgRUNDCiAgICAgICAgZm9yKCBpbnQgaSA9IDI7OyBpKyspIHsKICAgICAgICAgICAgY250Kys7CiAgICAgICAgICAgIGlmKGkgPT0gMikgewogICAgICAgICAgICAgICAgdGVtcCA9IGR1cGxpY2F0ZWRQb2ludE1vZE4ocCwgYSwgYiwgTik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB0ZW1wID0gcGx1c01vZE4ocCwgdGVtcCwgYSwgYiwgTik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgU3RyaW5nIG1zZyA9ICIiOwogICAgICAgICAgICBpZihpc1plcm9Qb2ludCh0ZW1wKSkgewogICAgICAgICAgICAgICAgbXNnID0gaSArICJQID0gMFxuQuG6rWMgY+G7p2EgI0UiICsgTiArICIgPSAiICsgaTsKICAgICAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihtc2cpOwogICAgICAgICAgICAgICAgLy8gS+G6v3QgdGjDumMgdmnhu4djIHTDrG0gYuG6rWMKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIG1zZyA9IGkrICJQIjsKICAgICAgICAgICAgdGVtcC5pblN0cmluZyhtc2cpOwogICAgICAgIH0KICAgIH0KfQo=