A private key is random generated and it is not correlated with any wallet.
I want to prepare custom (naive) implementation of public key generation for a Bitcoin. However, after a few attempts my results was incorrect. I compared them with online generators. I've recognized I used division instead of modinv. Unfortunately, after changing division into modinv I got "java.lang.ArithmeticException: BigInteger not invertible.". I tired to follow https://www.mobilefish.com/services/cryptocurrency/cryptocurrency.html#refProdedure and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Could you help me recognize where I did a mistake?
public class ECDSAUtils {
private static final CurvePoint G = new CurvePoint(new BigInteger("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16), new BigInteger("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16));
private static CurvePoint zero;
private static BigInteger base;
private static final BigInteger three = new BigInteger("3", 10);
public static void main(String[] args){
ECDSAUtils e = new ECDSAUtils();
BigInteger privateKey = new BigInteger("fdc668381ab251673ef8552851a2c7cf346a6e09ea86be0f55a94d2a12253557", 16);
CurvePoint r = e.mult(G, privateKey);
System.out.println(r.x.toString(16).toUpperCase() + " " + r.y.toString(16).toUpperCase());
}
public ECDSAUtils(){
zero = new CurvePoint(new BigInteger("0", 16), new BigInteger("0", 16));
base = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
}
public static CurvePoint add(CurvePoint p, CurvePoint q){
CurvePoint result = null;
if (p.equals(zero)){
result = q;
} else if (q.equals(zero)){
result = p;
} else {
BigInteger lambda = q.y.subtract(p.y).modInverse(q.x.subtract(p.x)).mod(base);
BigInteger x = lambda.multiply(lambda).subtract(p.x).subtract(q.x).mod(base);
BigInteger y = lambda.multiply(p.x.subtract(x)).subtract(p.y).mod(base);
result = new CurvePoint(x, y);
}
return result;
}
public static CurvePoint doublePoint(CurvePoint p){
BigInteger lambda = p.x.multiply(p.x).multiply(three).modInverse(p.y.add(p.y)).mod(base);
BigInteger x = lambda.multiply(lambda).subtract(p.x).subtract(p.x).mod(base);
BigInteger y = lambda.multiply(p.x.subtract(x)).subtract(p.y).mod(base);
return new CurvePoint(x, y);
}
public CurvePoint mult(CurvePoint N, BigInteger p) {
CurvePoint Q = zero;
//EDIT:
for (int i = p.bitLength() - 1; i > -1; i --) {
if (p.testBit(i)) {
Q = add(Q, N);
}
N = doublePoint(N);
}
return Q;
}
}
public class CurvePoint {
BigInteger x;
BigInteger y;
public CurvePoint(BigInteger x, BigInteger y) {
this.x = x;
this.y = y;
}
}
Exception in thread "main" java.lang.ArithmeticException: BigInteger not invertible.
at java.math.MutableBigInteger.mutableModInverse(MutableBigInteger.java:1986)
at java.math.BigInteger.modInverse(BigInteger.java:3154)
at naive.ECDSAUtils.doublePoint(ECDSAUtils.java:41)
at naive.ECDSAUtils.mult(ECDSAUtils.java:51)
at naive.ECDSAUtils.main(ECDSAUtils.java:15)
Currently the expression
is coded as follows:
y.modInverse(x).mod(p)
This is wrong and causes the observed error message. The following applies:
which must be coded as follows:
y.multiply(x.modInverse(p)).mod(p)
In the add method, the case:
is not handled. Here, the add method must return zero (i.e. the point representing the point at infinity). Geometrically, this case corresponds to a vertical secant (2 intersections).
Analogously, the case
is not handled in the doublePoint method. Here, the doublePoint method must return zero as well. Geometrically, this case corresponds to a vertical tangent (1 intersection).
The mult method doesn't work. But with regard to the comment in the code this is probably known.
Testing is easier if a small prime finite field is used. Here you can specify elliptical curves and determine the corresponding points. Note, that a curve with b != 0 must be used, otherwise the point (0,0) is a regular point of the curve and could not be used as a representative of the point at infinity.
Related
I was given a task to make a program to break the RSA encryption with the modulus and public keys of both parties and the cipher text. I have found solutions that brute force to find the prime values that are multiplied for the modulus. However with the size of the numbers that I have to use, it doesn't seem like it can even finish processing.(the modulus is 30 digits long or so)
This is the example data we were given:
{
"alice": {
"modulus": "66056083785421544972111685239",
"publicKey": "38933338385103628492607145193"
},
"bob": {
"modulus": "71994651332404115788173195239",
"publicKey": "28763302913765661132800185637"
},
"cipherText": "5b8sot9g2168mp3nw51"
}
This is the solution I'm currently trying, using the Fermat algorithm to try and find the primes faster:
import java.math.BigInteger;
public class ferr
{
static BigInteger r1;
static BigInteger r2;
static BigInteger aliceModulus = new BigInteger("107182711767121947041078387099");
public static void main (){
System.out.println("running");
ferr x = new ferr();
x.fermat(aliceModulus);
}
public void fermat(BigInteger N)
{
BigInteger a = calcSQR(N);
BigInteger b2 = (a.multiply(a).subtract(N));
while(Square(b2) == false) {
a = a.add(BigInteger.valueOf(1));
b2 = (a.multiply(a).subtract(N));
} // end while
r1 = a.subtract(calcSQR(b2));
r2 = N.divide(r1);
System.out.println("Roots = ("+ r1 +") , ("+ r2 +")");
}
public boolean Square(BigInteger N)
{
BigInteger sqRoot = calcSQR(N);
if(sqRoot.multiply(sqRoot).equals(N)) {
return true;
} // end if
else {
return false;
} // end else
}
public BigInteger calcSQR(BigInteger N)
{
if(N == BigInteger.ZERO || N == BigInteger.ONE) {
return N;
} // end if
BigInteger two = BigInteger.valueOf(2L);
BigInteger x;
// Starting with x = N/2 avoids magnitude issues with x squared
for(x = N.divide(two); x.compareTo(N.divide(x)) > 0; x = ((N.divide(x)).add(x)).divide(two)) {
if(N.compareTo(x.multiply(x)) == 0) {
return x;
} // end if
else {
return x.add(BigInteger.ONE);
} // end else
} // end for-loop
return null;
}
}
Is there any faster solution to break the encryption? I've left this program running for a few hours and it's still no where near the end.
As you noticed, Brute-Forcing the prime numbers is quite slow.
But there are easier ways.
Notice that you have two modulo, one for Bob, one for Alice.
A trivial shot is to calculate the greatest common divisor of both:
BigInteger bobM = new BigInteger("66056083785421544972111685239");
BigInteger aliceM = new BigInteger("71994651332404115788173195239");
System.out.println(bobM.gcd(aliceM));
This will output 535006138814359, which is one factor of both Bob and Alice.
It might be pure luck that this works here, or it could be crafted that way by your instructor.
Use a faster factorization method.
One of those is Pollard's Rho algorithm, which is quite easy to implement.
private static BigInteger pollardroh(BigInteger n, BigInteger x) {
BigInteger y = x;
BigInteger d = BigInteger.ONE;
while (d.equals(BigInteger.ONE)) {
x = x.modPow(BigInteger.TWO, n).add(BigInteger.ONE);
y = y.modPow(BigInteger.TWO, n).add(BigInteger.ONE);
y = y.modPow(BigInteger.TWO, n).add(BigInteger.ONE);
d = x.subtract(y).abs().gcd(n);
}
return d;
}
Use it with a starting value of x = BigInteger.TWO.
This will run for ~ 1 minute on my machine, and output 134567897654321 for Alice's modulo.
In the end, here are the factorization of both Alice & Bob's modulo:
Bob:
p1: 535006138814359
p2: 123467898764321
Alice:
p1: 535006138814359
p2: 134567897654321
The second primes look a bit suspicions, and not randomly selected at all.
I tried to calculate Tr(x) operation for x coordinate of the elliptical curve F2m (m = 163). For that, I used "Bouncy Castle" with corresponding types. Trace for my elliptical curve is equal to either 0 or 1 and my code is the following:
public int CalculateTrace_Test(byte[] array)
{
int m = 163;
BigInteger two = new BigInteger("2", 10);
BigInteger x = new BigInteger(array);
BigInteger xi = x;
BigInteger temp = x;
for (int i = 1; i < m; i++)
{
var next = xi.ModPow(two.Pow(i), fx);
temp = temp.Xor(next);
}
return temp.IntValue;
}
Here fx is an integer formed from the irreducible polynomial f(x) = x^163+x^7+x^6+x^3 + 1.
So my problem that it doesn't work and as result, I have everything but not 1 or 0. Could anyone please tell me what is wrong in my implementation of the trace?
It doesn't look like you are properly doing field arithmetic in GF(2m). The classes that support correct field arithmetic are in the package org.bouncycastle.math.ec. Take a look at ECFieldElement.F2m and ECCurve.F2m. Also, for your specific case which corresponds to the SECT163 reduction polynomial, the class SecT163FieldElement may be particularly useful.
Here some code copied directly from the class org.bouncycastle.math.ec.tools.TraceOptimizer. The code assumes the the finite field is of characteristic 2.
private static int calculateTrace(ECFieldElement fe) {
int m = fe.getFieldSize();
ECFieldElement tr = fe;
for (int i = 1; i < m; ++i) {
fe = fe.square();
tr = tr.add(fe);
}
BigInteger b = tr.toBigInteger();
if (b.bitLength() > 1) {
throw new IllegalStateException();
}
return b.intValue();
I have a class with two float variables and hashCode method (without equals in current code snippet):
public class TestPoint2D {
private float x;
private float z;
public TestPoint2D(float x, float z) {
this.x = x;
this.z = z;
}
#Override
public int hashCode() {
int result = (x != +0.0f ? Float.floatToIntBits(x) : 0);
result = 31 * result + (z != +0.0f ? Float.floatToIntBits(z) : 0);
return result;
}
}
The following test
#Test
public void tempTest() {
TestPoint2D p1 = new TestPoint2D(3, -1);
TestPoint2D p2 = new TestPoint2D(-3, 1);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
returns same values:
-2025848832
In this case I can't use my TestPoint2D within HashSet / HashMap
Can anyone suggest how to implement hashCode in this case or workarounds related to this?
P.S.
Added one more test:
#Test
public void hashCodeTest() {
for (float a = 5; a < 100000; a += 1.5f) {
float b = a + 1000 / a; // negative value depends on a
TestPoint3D p1 = new TestPoint3D(a, -b);
TestPoint3D p2 = new TestPoint3D(-a, b);
Assert.assertEquals(p1.hashCode(), p2.hashCode());
}
}
And it is passed that proves that
TestPoint2D(a, -b).hashCode() == TestPoint2D(-a, b).hashCode()
I would use Objects.hash():
public int hashCode() {
return Objects.hash(x, z);
}
From the Javadoc:
public static int hash(Object... values)
Generates a hash code for a sequence of input values. The hash code is generated as if all the input values were placed into an array, and that array were hashed by calling Arrays.hashCode(Object[]).
This method is useful for implementing Object.hashCode() on objects containing multiple fields. For example, if an object that has three fields, x, y, and z, one could write:
These auto-generated hashcode functions are not very good.
The problem is that small integers cause very "sparse" and similar bitcodes.
To understand the problem, look at the actual computation.
System.out.format("%x\n", Float.floatToIntBits(1));
System.out.format("%x\n", Float.floatToIntBits(-1));
System.out.format("%x\n", Float.floatToIntBits(3));
System.out.format("%x\n", Float.floatToIntBits(-3));
gives:
3f800000
bf800000
40400000
c0400000
As you can see, the - is the most significant bit in IEEE floats. Multiplication with 31 changes them not substantially:
b0800000
30800000
c7c00000
47c00000
The problem are all the 0s at the end. They get preserved by integer multiplication with any prime (because they are base-2 0s, not base-10!).
So IMHO, the best strategy is to employ bit shifts, e.g.:
final int h1 = Float.floatToIntBits(x);
final int h2 = Float.floatToIntBits(z);
return h1 ^ ((h2 >>> 16) | (h2 << 16));
But you may want to look at Which hashing algorithm is best for uniqueness and speed? and test for your particular case of integers-as-float.
according to the java specification, 2 objects can have the same hashCode and this doesnt mean they are equal...
the probability is small but exist...
on the other hand is always a good practice to override both equals and hashcode...
As I understand the problem, you expect a lot of symmetrical pairs of points among your keys, so you need a hashCode method that does not tend to give them the same code.
I did some tests, and deliberately giving extra significance to the sign of x tends to map symmetrical points away from each other. See this test program:
public class Test {
private float x;
private float y;
public static void main(String[] args) {
int collisions = 0;
for (int ix = 0; ix < 100; ix++) {
for (int iz = 0; iz < 100; iz++) {
Test t1 = new Test(ix, -iz);
Test t2 = new Test(-ix, iz);
if (t1.hashCode() == t2.hashCode()) {
collisions++;
}
}
}
System.out.println(collisions);
}
public Test(float x, float y) {
super();
this.x = x;
this.y = y;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (x >= 0) ? 1 : -1;
result = prime * result + Float.floatToIntBits(x);
result = prime * result + Float.floatToIntBits(y);
return result;
}
// Equals omitted for compactness
}
Without the result = (x >= 0) ? 1 : -1; line it is the hashCode() generated by Eclipse, and counts 9802 symmetrical point collisions. With that line, it counts one symmetrical point collision.
I'm implementing Fermat Factorization algorithm using BigInteger so I can factor. But at the moment, the code is not working; it hangs for some reason. Could someone direct me to where the issue is, or let me know if my algorithm is incorrect? BigInteger makes life difficult, so I had to look for a square root method.
import java.math.BigInteger;
import java.util.Scanner;
public class Fermat
{
/** Fermat factor **/
public void FermatFactor(BigInteger N)
{
BigInteger a = sqrt(N);
BigInteger b2 = a.multiply(a).subtract(N);
while (!isSquare(b2)) {
a = a.add(a);
b2 = a.multiply(a).subtract(N);
}
BigInteger r1 = a.subtract(sqrt(b2));
BigInteger r2 = N.divide(r1);
display(r1, r2);
}
/** function to display roots **/
public void display(BigInteger r1, BigInteger r2) {
System.out.println("\nRoots = "+ r1 +" , "+ r2);
}
/** function to check if N is a perfect square or not **/
public boolean isSquare(BigInteger N) {
BigInteger ONE = new BigInteger("1");
BigInteger sqr = sqrt(N);
if (sqr.multiply(sqr) == N || (sqr.add(ONE)).multiply(sqr.add(ONE)) == N)
return true;
return false;
}
public static BigInteger sqrt(BigInteger x)
throws IllegalArgumentException {
if (x.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("Negative argument.");
}
// square roots of 0 and 1 are trivial and
// y == 0 will cause a divide-by-zero exception
if (x == BigInteger.ZERO || x == BigInteger.ONE) {
return x;
} // end if
BigInteger two = BigInteger.valueOf(2L);
BigInteger y;
// starting with y = x / 2 avoids magnitude issues with x squared
for (y = x.divide(two);
y.compareTo(x.divide(y)) > 0;
y = ((x.divide(y)).add(y)).divide(two));
if (x.compareTo(y.multiply(y)) == 0) {
return y;
} else {
return y.add(BigInteger.ONE);
}
} // end bigIntSqRootCeil
/** main method **/
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Fermat Factorization Test\n");
System.out.println("Enter odd number");
BigInteger N = scan.nextBigInteger();
Fermat ff = new Fermat();
ff.FermatFactor(N);
scan.close();
}
}
I know I have a lot of mistakes, but any help is appreciated. Thanks.
Your "for" loop :
for (y = x.divide(two);
y.compareTo(x.divide(y)) > 0;
y = ((x.divide(y)).add(y)).divide(two));
does not terminate. Perhaps you could keep track of the values of the variable 'y', to guess when you have to stop.
Edit : that was wrong (see comments). The problem is in the line
a = a.add(a)
inside procedure FermatFactor. It should rather be
a = a.add(ONE)
In my machine I also had troubles with testing equalities using 'A == B'. The method 'A.equals(B)' fixed it.
I have a BigInteger value, let's say it is 282 and is inside the variable x. I now want to write a while loop that states:
while b2 isn't a perfect square:
a ← a + 1
b2 ← a*a - N
endwhile
How would I do such a thing using BigInteger?
EDIT: The purpose for this is so I can write this method. As the article states one must check if b2 is not square.
Compute the integer square root, then check that its square is your number. Here is my method of computing the square root using Heron's method:
private static final BigInteger TWO = BigInteger.valueOf(2);
/**
* Computes the integer square root of a number.
*
* #param n The number.
*
* #return The integer square root, i.e. the largest number whose square
* doesn't exceed n.
*/
public static BigInteger sqrt(BigInteger n)
{
if (n.signum() >= 0)
{
final int bitLength = n.bitLength();
BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);
while (!isSqrt(n, root))
{
root = root.add(n.divide(root)).divide(TWO);
}
return root;
}
else
{
throw new ArithmeticException("square root of negative number");
}
}
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I found a sqrt method used here, and simplified the square test.
private static final BigInteger b100 = new BigInteger("100");
private static final boolean[] isSquareResidue;
static{
isSquareResidue = new boolean[100];
for(int i =0;i<100;i++){
isSquareResidue[(i*i)%100]=true;
}
}
public static boolean isSquare(final BigInteger r) {
final int y = (int) r.mod(b100).longValue();
boolean check = false;
if (isSquareResidue[y]) {
final BigInteger temp = sqrt(r);
if (r.compareTo(temp.pow(2)) == 0) {
check = true;
}
}
return check;
}
public static BigInteger sqrt(final BigInteger val) {
final BigInteger two = BigInteger.valueOf(2);
BigInteger a = BigInteger.ONE.shiftLeft(val.bitLength() / 2);
BigInteger b;
do {
b = val.divide(a);
a = (a.add(b)).divide(two);
} while (a.subtract(b).abs().compareTo(two) >= 0);
return a;
}
public static Boolean PerfectSQR(BigInteger A){BigInteger B=A.sqrt(), C=B.multiply(B);return (C.equals(A));}
DON'T use this...
BigInteger n = ...;
double n_as_double = n.doubleValue();
double n_sqrt = Math.sqrt(n_as_double);
BigInteger n_sqrt_as_int = new BigDecimal(n_sqrt).toBigInteger();
if (n_sqrt_as_int.pow(2).equals(n)) {
// number is perfect square
}
As Christian Semrau commented below - this doesn't work. I am sorry for posting incorrect answer.
using System.Numerics; // needed for BigInteger
/* Variables */
BigInteger a, b, b2, n, p, q;
int flag;
/* Assign Data */
n = 10147;
a = iSqrt(n);
/* Algorithm */
do
{ a = a + 1;
b2 = (a * a) – n;
b = iSqrt(b2);
flag = BigInteger.Compare(b * b, b2);
} while(flag != 0);
/* Output Data */
p = a + b;
q = a – b;
/* Method */
private static BigInteger iSqrt(BigInteger num)
{ // Finds the integer square root of a positive number
if (0 == num) { return 0; } // Avoid zero divide
BigInteger n = (num / 2) + 1; // Initial estimate, never low
BigInteger n1 = (n + (num / n)) / 2;
while (n1 < n)
{ n = n1;
n1 = (n + (num / n)) / 2;
}
return n;
} // end iSqrt()
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I tried the above using JavaScript BigInt:
function isPerfectSqrt(n, root) {
const lowerBound = root**2n;
const upperBound = (root+1n)**2n
return lowerBound <= n && n < upperBound;
}
And found it was only about 60% as fast (in Node V8) as the one-liner:
function isPerfectSqrt(n, root) {
return (n/root === root && n%root === 0n)
}
The number you want to do a perfect square test on is A. B is the integer square root of A and the .sqrt() function returns the integer lower floor of the square root. The Boolean of B*B=A is returned. The Boolean return is "true" if it is a perfect square and "false" if it is not a perfect square.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger B = A.sqrt();
return B.multiply(B).equals(A);
}
An alternative is to use the sqrtAndRemainder() function. If the remainder, B[1], is zero it is a perfect square. The boolean TRUE then is returned as shown below.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger [] B=A.sqrtAndRemainder();
return B[1].equals(BigInteger.ZERO);
}