Data update
This commit is contained in:
parent
61b93a2cd1
commit
5af6d93694
858 changed files with 20572 additions and 2082 deletions
|
|
@ -1,7 +1,7 @@
|
|||
;Elliptic curves.
|
||||
|
||||
An [[wp:Elliptic_curve|elliptic curve]] E over ℤp (p ≥ 5) is defined by an equation of the form
|
||||
'''y^2 = x^3 + ax + b''', where a, b ∈ ℤp and the discriminant ≢ 0 (mod p),
|
||||
'''y²= x³ + ax + b''', where a, b ∈ ℤp and the discriminant ≢ 0 (mod p),
|
||||
together with a special point 𝒪 called the point at infinity.
|
||||
The set '''E(ℤp)''' consists of all points (x, y), with x, y ∈ ℤp,
|
||||
which satisfy the above defining equation, together with 𝒪.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,300 @@
|
|||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
const int32_t MAX_MODULUS = 1073741789;
|
||||
const int32_t MAX_ORDER_G = MAX_MODULUS + 65536;
|
||||
|
||||
std::random_device random;
|
||||
std::mt19937 generator(random());
|
||||
std::uniform_real_distribution<double> distribution(0.0F, 1.0F);
|
||||
|
||||
class Point {
|
||||
public:
|
||||
Point(const int64_t& x, const int64_t& y) : x(x), y(y) {}
|
||||
|
||||
Point() : x(0),y(0) {}
|
||||
|
||||
bool isZero() {
|
||||
return x == INT64_MAX && y == 0;
|
||||
}
|
||||
|
||||
int64_t x, y;
|
||||
};
|
||||
|
||||
const Point ZERO_POINT(INT64_MAX, 0);
|
||||
|
||||
class Pair {
|
||||
public:
|
||||
Pair(const int64_t& a, const int64_t& b) : a(a), b(b) {}
|
||||
|
||||
const int64_t a, b;
|
||||
};
|
||||
|
||||
class Parameter {
|
||||
public:
|
||||
Parameter(const int64_t& a, const int64_t& b, const int64_t& n, const Point& g, const int64_t& r)
|
||||
: a(a), b(b), n(n), g(g), r(r) {}
|
||||
|
||||
const int64_t a, b, n;
|
||||
const Point g;
|
||||
const int64_t r;
|
||||
};
|
||||
|
||||
int64_t signum(const int64_t& x) {
|
||||
return ( x < 0 ) ? -1 : ( x > 0 ) ? 1 : 0;
|
||||
}
|
||||
|
||||
int64_t floor_mod(const int64_t& num, const int64_t& mod) {
|
||||
const int64_t signs = ( signum(num % mod) == -signum(mod) ) ? 1 : 0;
|
||||
return ( num % mod ) + signs * mod;
|
||||
}
|
||||
|
||||
int64_t floor_div(const int64_t& number, const int64_t& modulus) {
|
||||
const int32_t signs = ( signum(number % modulus) == -signum(modulus) ) ? 1 : 0;
|
||||
return ( number / modulus ) - signs;
|
||||
}
|
||||
|
||||
// Return 1 / aV modulus aU
|
||||
int64_t extended_GCD(int64_t v, int64_t u) {
|
||||
if ( v < 0 ) {
|
||||
v += u;
|
||||
}
|
||||
|
||||
int64_t result = 0;
|
||||
int64_t s = 1;
|
||||
while ( v != 0 ) {
|
||||
const int64_t quotient = floor_div(u, v);
|
||||
u = floor_mod(u, v);
|
||||
std::swap(u, v);
|
||||
result -= quotient * s;
|
||||
std::swap(result, s);
|
||||
}
|
||||
|
||||
if ( u != 1 ) {
|
||||
throw std::runtime_error("Cannot inverse modulo N, gcd = " + u);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class Elliptic_Curve {
|
||||
public:
|
||||
Elliptic_Curve(const Parameter& parameter) {
|
||||
n = parameter.n;
|
||||
if ( n < 5 || n > MAX_MODULUS ) {
|
||||
throw std::invalid_argument("Invalid value for modulus: " + n);
|
||||
}
|
||||
|
||||
a = floor_mod(parameter.a, n);
|
||||
b = floor_mod(parameter.b, n);
|
||||
g = parameter.g;
|
||||
r = parameter.r;
|
||||
|
||||
if ( r < 5 || r > MAX_ORDER_G ) {
|
||||
throw std::invalid_argument("Invalid value for the order of g: " + r);
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Elliptic curve: y^2 = x^3 + " << a << "x + " << b << " (mod " << n << ")" << std::endl;
|
||||
print_point_with_prefix(g, "base point G");
|
||||
std::cout << "order(G, E) = " << r << std::endl;
|
||||
}
|
||||
|
||||
Point add(Point p, Point q) {
|
||||
if ( p.isZero() ) {
|
||||
return q;
|
||||
}
|
||||
if ( q.isZero() ) {
|
||||
return p;
|
||||
}
|
||||
|
||||
int64_t la;
|
||||
if ( p.x != q.x ) {
|
||||
la = floor_mod(( p.y - q.y ) * extended_GCD(p.x - q.x, n), n);
|
||||
} else if ( p.y == q.y && p.y != 0 ) {
|
||||
la = floor_mod(floor_mod(floor_mod(p.x * p.x, n) * 3 + a, n) * extended_GCD(2 * p.y, n), n);
|
||||
} else {
|
||||
return ZERO_POINT;
|
||||
}
|
||||
|
||||
const int64_t x_coord = floor_mod(la * la - p.x - q.x, n);
|
||||
const int64_t y_coord = floor_mod(la * ( p.x - x_coord ) - p.y, n);
|
||||
return Point(x_coord, y_coord);
|
||||
}
|
||||
|
||||
Point multiply(Point point, int64_t k) {
|
||||
Point result = ZERO_POINT;
|
||||
|
||||
while ( k != 0 ) {
|
||||
if ( ( k & 1 ) == 1 ) {
|
||||
result = add(result, point);
|
||||
}
|
||||
point = add(point, point);
|
||||
k >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool contains(Point point) {
|
||||
if ( point.isZero() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t r = floor_mod(floor_mod(a + point.x * point.x, n) * point.x + b, n);
|
||||
int64_t s = floor_mod(point.y * point.y, n);
|
||||
return r == s;
|
||||
}
|
||||
|
||||
uint64_t discriminant() {
|
||||
const int64_t constant = 4 * floor_mod(a * a, n) * floor_mod(a, n);
|
||||
return floor_mod(-16 * ( floor_mod(b * b, n) * 27 + constant ), n);
|
||||
}
|
||||
|
||||
void print_point_with_prefix(Point point, const std::string& prefix) {
|
||||
int64_t y = point.y;
|
||||
if ( point.isZero() ) {
|
||||
std::cout << prefix + " (0)" << std::endl;
|
||||
} else {
|
||||
if ( y > n - y ) {
|
||||
y -= n;
|
||||
}
|
||||
std::cout << prefix + " (" << point.x << ", " << y << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t a, b, n, r;
|
||||
Point g;
|
||||
};
|
||||
|
||||
double random_number() {
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
Pair signature(Elliptic_Curve curve, const int64_t& s, const int64_t& f) {
|
||||
int64_t c, d, u;
|
||||
Point v;
|
||||
|
||||
while ( true ) {
|
||||
while ( true ) {
|
||||
u = 1 + (int64_t) ( random_number() * (double) ( curve.r - 1 ) );
|
||||
v = curve.multiply(curve.g, u);
|
||||
c = floor_mod(v.x, curve.r);
|
||||
if ( c != 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d = floor_mod(extended_GCD(u, curve.r) * floor_mod(f + s * c, curve.r), curve.r);
|
||||
if ( d != 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "one-time u = " << u << std::endl;
|
||||
curve.print_point_with_prefix(v, "V = uG");
|
||||
return Pair(c, d);
|
||||
}
|
||||
|
||||
bool verify(Elliptic_Curve curve, Point point, const int64_t& f, const Pair& signature) {
|
||||
if ( signature.a < 1 || signature.a >= curve.r || signature.b < 1 || signature.b >= curve.r ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "\n" << "signature verification" << std::endl;
|
||||
const int64_t h = extended_GCD(signature.b, curve.r);
|
||||
const int64_t h1 = floor_mod(f * h, curve.r);
|
||||
const int64_t h2 = floor_mod(signature.a * h, curve.r);
|
||||
std::cout << "h1, h2 = " << h1 << ", " << h2 << std::endl;
|
||||
Point v = curve.multiply(curve.g, h1);
|
||||
Point v2 = curve.multiply(point, h2);
|
||||
curve.print_point_with_prefix(v, "h1G");
|
||||
curve.print_point_with_prefix(v2, "h2W");
|
||||
v = curve.add(v, v2);
|
||||
curve.print_point_with_prefix(v, "+ =");
|
||||
|
||||
if ( v.isZero() ) {
|
||||
return false;
|
||||
}
|
||||
int64_t c1 = floor_mod(v.x, curve.r);
|
||||
std::cout << "c' = " << c1 << std::endl;
|
||||
return c1 == signature.a;
|
||||
}
|
||||
|
||||
// Build the digital signature for a message using the hash aF with error bit aD
|
||||
void ecdsa(Elliptic_Curve curve, int64_t f, int32_t d) {
|
||||
Point point = curve.multiply(curve.g, curve.r);
|
||||
|
||||
if ( curve.discriminant() == 0 || curve.g.isZero() || ! point.isZero() || ! curve.contains(curve.g) ) {
|
||||
throw std::invalid_argument("Invalid parameter in the method ecdsa");
|
||||
}
|
||||
|
||||
std::cout << "\n" << "key generation" << std::endl;
|
||||
const int64_t s = 1 + (int64_t) ( random_number() * (double) ( curve.r - 1 ) );
|
||||
point = curve.multiply(curve.g, s);
|
||||
std::cout << "private key s = " << s << std::endl;
|
||||
curve.print_point_with_prefix(point, "public key W = sG");
|
||||
|
||||
// Find the next highest power of two minus one.
|
||||
int64_t t = curve.r;
|
||||
int64_t i = 1;
|
||||
while ( i < 64 ) {
|
||||
t |= t >> i;
|
||||
i <<= 1;
|
||||
}
|
||||
while ( f > t ) {
|
||||
f >>= 1;
|
||||
}
|
||||
std::cout << "\n" << "aligned hash " << std::hex << std::setfill('0') << std::setw(8) << f
|
||||
<< std::dec << std::endl;
|
||||
|
||||
const Pair signature_pair = signature(curve, s, f);
|
||||
std::cout << "signature c, d = " << signature_pair.a << ", " << signature_pair.b << std::endl;
|
||||
|
||||
if ( d > 0 ) {
|
||||
while ( d > t ) {
|
||||
d >>= 1;
|
||||
}
|
||||
f ^= d;
|
||||
std::cout << "\n" << "corrupted hash " << std::hex << std::setfill('0') << std::setw(8) << f
|
||||
<< std::dec << std::endl;
|
||||
}
|
||||
|
||||
std::cout << ( verify(curve, point, f, signature_pair) ? "Valid" : "Invalid" ) << std::endl;
|
||||
std::cout << "-----------------" << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Test parameters for elliptic curve digital signature algorithm,
|
||||
// using the short Weierstrass model: y^2 = x^3 + ax + b (mod N).
|
||||
//
|
||||
// Parameter: a, b, modulus N, base point G, order of G in the elliptic curve.
|
||||
|
||||
const std::vector<Parameter> parameters {
|
||||
Parameter( 355, 671, 1073741789, Point(13693, 10088), 1073807281 ),
|
||||
Parameter( 0, 7, 67096021, Point( 6580, 779), 16769911 ),
|
||||
Parameter( -3, 1, 877073, Point( 0, 1), 878159 ),
|
||||
Parameter( 0, 14, 22651, Point( 63, 30), 151 ),
|
||||
Parameter( 3, 2, 5, Point( 2, 1), 5 ) };
|
||||
|
||||
// Parameters which cause failure of the algorithm for the given reasons
|
||||
// the base point is of composite order
|
||||
// Parameter( 0, 7, 67096021, Point( 2402, 6067), 33539822 ),
|
||||
// the given order is of composite order
|
||||
// Parameter( 0, 7, 67096021, Point( 6580, 779), 67079644 ),
|
||||
// the modulus is not prime (deceptive example)
|
||||
// Parameter( 0, 7, 877069, Point( 3, 97123), 877069 ),
|
||||
// fails if the modulus divides the discriminant
|
||||
// Parameter( 39, 387, 22651, Point( 95, 27), 22651 ) );
|
||||
|
||||
const int64_t f = 0x789abcde; // The message's digital signature hash which is to be verified
|
||||
const int32_t d = 0; // Set d > 0 to simulate corrupted data
|
||||
|
||||
for ( const Parameter& parameter : parameters ) {
|
||||
Elliptic_Curve elliptic_curve(parameter);
|
||||
ecdsa(elliptic_curve, f, d);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public final class EllipticCurveDigitalSignatureAlgorithm {
|
||||
|
||||
public static void main(String[] aArgs) {
|
||||
// Test parameters for elliptic curve digital signature algorithm,
|
||||
// using the short Weierstrass model: y^2 = x^3 + ax + b (mod N).
|
||||
//
|
||||
// Parameter: a, b, modulus N, base point G, order of G in the elliptic curve.
|
||||
|
||||
List<Parameter> parameters = List.of(
|
||||
new Parameter( 355, 671, 1073741789, new Point(13693, 10088), 1073807281 ),
|
||||
new Parameter( 0, 7, 67096021, new Point( 6580, 779), 16769911 ),
|
||||
new Parameter( -3, 1, 877073, new Point( 0, 1), 878159 ),
|
||||
new Parameter( 0, 14, 22651, new Point( 63, 30), 151 ),
|
||||
new Parameter( 3, 2, 5, new Point( 2, 1), 5 ) );
|
||||
|
||||
// Parameters which cause failure of the algorithm for the given reasons
|
||||
// the base point is of composite order
|
||||
// new Parameter( 0, 7, 67096021, new Point( 2402, 6067), 33539822 ),
|
||||
// the given order is of composite order
|
||||
// new Parameter( 0, 7, 67096021, new Point( 6580, 779), 67079644 ),
|
||||
// the modulus is not prime (deceptive example)
|
||||
// new Parameter( 0, 7, 877069, new Point( 3, 97123), 877069 ),
|
||||
// fails if the modulus divides the discriminant
|
||||
// new Parameter( 39, 387, 22651, new Point( 95, 27), 22651 ) );
|
||||
|
||||
final long f = 0x789abcde; // The message's digital signature hash which is to be verified
|
||||
final int d = 0; // Set d > 0 to simulate corrupted data
|
||||
|
||||
for ( Parameter parameter : parameters ) {
|
||||
EllipticCurve ellipticCurve = new EllipticCurve(parameter);
|
||||
ecdsa(ellipticCurve, f, d);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the digital signature for a message using the hash aF with error bit aD
|
||||
private static void ecdsa(EllipticCurve aCurve, long aF, int aD) {
|
||||
Point point = aCurve.multiply(aCurve.g, aCurve.r);
|
||||
|
||||
if ( aCurve.discriminant() == 0 || aCurve.g.isZero() || ! point.isZero() || ! aCurve.contains(aCurve.g) ) {
|
||||
throw new AssertionError("Invalid parameter in method ecdsa");
|
||||
}
|
||||
|
||||
System.out.println(System.lineSeparator() + "key generation");
|
||||
final long s = 1 + (long) ( random() * (double) ( aCurve.r - 1 ) );
|
||||
point = aCurve.multiply(aCurve.g, s);
|
||||
System.out.println("private key s = " + s);
|
||||
aCurve.printPointWithPrefix(point, "public key W = sG");
|
||||
|
||||
// Find the next highest power of two minus one.
|
||||
long t = aCurve.r;
|
||||
long i = 1;
|
||||
while ( i < 64 ) {
|
||||
t |= t >> i;
|
||||
i <<= 1;
|
||||
}
|
||||
long f = aF;
|
||||
while ( f > t ) {
|
||||
f >>= 1;
|
||||
}
|
||||
System.out.println(System.lineSeparator() + "aligned hash " + String.format("%08x", f));
|
||||
|
||||
Pair signature = signature(aCurve, s, f);
|
||||
System.out.println("signature c, d = " + signature.a + ", " + signature.b);
|
||||
|
||||
long d = aD;
|
||||
if ( d > 0 ) {
|
||||
while ( d > t ) {
|
||||
d >>= 1;
|
||||
}
|
||||
f ^= d;
|
||||
System.out.println(System.lineSeparator() + "corrupted hash " + String.format("%08x", f));
|
||||
}
|
||||
|
||||
System.out.println(verify(aCurve, point, f, signature) ? "Valid" : "Invalid");
|
||||
System.out.println("-----------------");
|
||||
}
|
||||
|
||||
private static boolean verify(EllipticCurve aCurve, Point aPoint, long aF, Pair aSignature) {
|
||||
if ( aSignature.a < 1 || aSignature.a >= aCurve.r || aSignature.b < 1 || aSignature.b >= aCurve.r ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System.out.println(System.lineSeparator() + "signature verification");
|
||||
final long h = extendedGCD(aSignature.b, aCurve.r);
|
||||
final long h1 = Math.floorMod(aF * h, aCurve.r);
|
||||
final long h2 = Math.floorMod(aSignature.a * h, aCurve.r);
|
||||
System.out.println("h1, h2 = " + h1 + ", " + h2);
|
||||
Point v = aCurve.multiply(aCurve.g, h1);
|
||||
Point v2 = aCurve.multiply(aPoint, h2);
|
||||
aCurve.printPointWithPrefix(v, "h1G");
|
||||
aCurve.printPointWithPrefix(v2, "h2W");
|
||||
v = aCurve.add(v, v2);
|
||||
aCurve.printPointWithPrefix(v, "+ =");
|
||||
|
||||
if ( v.isZero() ) {
|
||||
return false;
|
||||
}
|
||||
long c1 = Math.floorMod(v.x, aCurve.r);
|
||||
System.out.println("c' = " + c1);
|
||||
return c1 == aSignature.a;
|
||||
}
|
||||
|
||||
private static Pair signature(EllipticCurve aCurve, long aS, long aF) {
|
||||
long c = 0;
|
||||
long d = 0;
|
||||
long u;
|
||||
Point v;
|
||||
System.out.println("Signature computation");
|
||||
|
||||
while ( true ) {
|
||||
while ( true ) {
|
||||
u = 1 + (long) ( random() * (double) ( aCurve.r - 1 ) );
|
||||
v = aCurve.multiply(aCurve.g, u);
|
||||
c = Math.floorMod(v.x, aCurve.r);
|
||||
if ( c != 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d = Math.floorMod(extendedGCD(u, aCurve.r) * Math.floorMod(aF + aS * c, aCurve.r), aCurve.r);
|
||||
if ( d != 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("one-time u = " + u);
|
||||
aCurve.printPointWithPrefix(v, "V = uG");
|
||||
return new Pair(c, d);
|
||||
}
|
||||
|
||||
// Return 1 / aV modulus aU
|
||||
private static long extendedGCD(long aV, long aU) {
|
||||
if ( aV < 0 ) {
|
||||
aV += aU;
|
||||
}
|
||||
|
||||
long result = 0;
|
||||
long s = 1;
|
||||
while ( aV != 0 ) {
|
||||
final long quotient = Math.floorDiv(aU, aV);
|
||||
aU = Math.floorMod(aU, aV);
|
||||
long temp = aU; aU = aV; aV = temp;
|
||||
result -= quotient * s;
|
||||
temp = result; result = s; s = temp;
|
||||
}
|
||||
|
||||
if ( aU != 1 ) {
|
||||
throw new AssertionError("Cannot inverse modulo N, gcd = " + aU);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static double random() {
|
||||
return RANDOM.nextDouble();
|
||||
}
|
||||
|
||||
private static class EllipticCurve {
|
||||
|
||||
public EllipticCurve(Parameter aParameter) {
|
||||
n = aParameter.n;
|
||||
if ( n < 5 || n > MAX_MODULUS ) {
|
||||
throw new AssertionError("Invalid value for modulus: " + n);
|
||||
}
|
||||
|
||||
a = Math.floorMod(aParameter.a, n);
|
||||
b = Math.floorMod(aParameter.b, n);
|
||||
g = aParameter.g;
|
||||
r = aParameter.r;
|
||||
|
||||
if ( r < 5 || r > MAX_ORDER_G ) {
|
||||
throw new AssertionError("Invalid value for the order of g: " + r);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Elliptic curve: y^2 = x^3 + " + a + "x + " + b + " (mod " + n + ")");
|
||||
printPointWithPrefix(g, "base point G");
|
||||
System.out.println("order(G, E) = " + r);
|
||||
}
|
||||
|
||||
private Point add(Point aP, Point aQ) {
|
||||
if ( aP.isZero() ) {
|
||||
return aQ;
|
||||
}
|
||||
if ( aQ.isZero() ) {
|
||||
return aP;
|
||||
}
|
||||
|
||||
long la;
|
||||
if ( aP.x != aQ.x ) {
|
||||
la = Math.floorMod(( aP.y - aQ.y ) * extendedGCD(aP.x - aQ.x, n), n);
|
||||
} else if ( aP.y == aQ.y && aP.y != 0 ) {
|
||||
la = Math.floorMod(Math.floorMod(Math.floorMod(
|
||||
aP.x * aP.x, n) * 3 + a, n) * extendedGCD(2 * aP.y, n), n);
|
||||
} else {
|
||||
return Point.ZERO;
|
||||
}
|
||||
|
||||
final long xCoordinate = Math.floorMod(la * la - aP.x - aQ.x, n);
|
||||
final long yCoordinate = Math.floorMod(la * ( aP.x - xCoordinate ) - aP.y, n);
|
||||
return new Point(xCoordinate, yCoordinate);
|
||||
}
|
||||
|
||||
public Point multiply(Point aPoint, long aK) {
|
||||
Point result = Point.ZERO;
|
||||
|
||||
while ( aK != 0 ) {
|
||||
if ( ( aK & 1 ) == 1 ) {
|
||||
result = add(result, aPoint);
|
||||
}
|
||||
aPoint = add(aPoint, aPoint);
|
||||
aK >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean contains(Point aPoint) {
|
||||
if ( aPoint.isZero() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final long r = Math.floorMod(Math.floorMod(a + aPoint.x * aPoint.x, n) * aPoint.x + b, n);
|
||||
final long s = Math.floorMod(aPoint.y * aPoint.y, n);
|
||||
return r == s;
|
||||
}
|
||||
|
||||
public long discriminant() {
|
||||
final long constant = 4 * Math.floorMod(a * a, n) * Math.floorMod(a, n);
|
||||
return Math.floorMod(-16 * ( Math.floorMod(b * b, n) * 27 + constant ), n);
|
||||
}
|
||||
|
||||
public void printPointWithPrefix(Point aPoint, String aPrefix) {
|
||||
long y = aPoint.y;
|
||||
if ( aPoint.isZero() ) {
|
||||
System.out.println(aPrefix + " (0)");
|
||||
} else {
|
||||
if ( y > n - y ) {
|
||||
y -= n;
|
||||
}
|
||||
System.out.println(aPrefix + " (" + aPoint.x + ", " + y + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private final long a, b, n, r;
|
||||
private final Point g;
|
||||
|
||||
}
|
||||
|
||||
private static class Point {
|
||||
|
||||
public Point(long aX, long aY) {
|
||||
x = aX;
|
||||
y = aY;
|
||||
}
|
||||
|
||||
public boolean isZero() {
|
||||
return x == INFINITY && y == 0;
|
||||
}
|
||||
|
||||
private long x, y;
|
||||
|
||||
private static final long INFINITY = Long.MAX_VALUE;
|
||||
private static final Point ZERO = new Point(INFINITY, 0);
|
||||
|
||||
}
|
||||
|
||||
private static record Pair(long a, long b) {}
|
||||
|
||||
private static record Parameter(long a, long b, long n, Point g, long r) {}
|
||||
|
||||
private static final int MAX_MODULUS = 1073741789;
|
||||
private static final int MAX_ORDER_G = MAX_MODULUS + 65536;
|
||||
|
||||
private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
|
||||
|
||||
}
|
||||
|
|
@ -1,89 +1,101 @@
|
|||
use Digest::SHA256::Native;
|
||||
module EC {
|
||||
use FiniteField;
|
||||
|
||||
# Following data taken from the C entry
|
||||
our (\A,\B,\P,\O,\Gx,\Gy) = (355, 671, 1073741789, 1073807281, 13693, 10088);
|
||||
our class Point {
|
||||
has ($.x, $.y);
|
||||
submethod TWEAK { fail unless $!y**2 == $!x**3 + $*a*$!x + $*b }
|
||||
multi method gist(::?CLASS:U:) { "Point at Horizon" }
|
||||
multi method new($x, $y) { samewith :$x, :$y }
|
||||
}
|
||||
multi infix:<==>(Point:D $A, Point:D $B) is export { $A.x == $B.x and $A.y == $B.y }
|
||||
|
||||
#`{ Following data taken from the Julia entry; 256-bit; tested | ||||