-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove eddsa library dependency as I have re-implemented the function…
…ality we require
- Loading branch information
Showing
4 changed files
with
89 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package com.lmax.solana4j.util; | ||
|
||
import java.math.BigInteger; | ||
import java.nio.ByteBuffer; | ||
|
||
public class Ed25519 | ||
{ | ||
private static final BigInteger P = new BigInteger("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16); | ||
private static final BigInteger D = new BigInteger("52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3", 16); | ||
private static final BigInteger PM5D8 = P.subtract(BigInteger.valueOf(5)).divide(BigInteger.valueOf(8)); | ||
|
||
/** | ||
* Checks if the public key represented by a 32-byte array is on the Ed25519 curve. | ||
* | ||
* @param publicKeyBytes The 32-byte array representing the public key. | ||
* @return true if the point is on the curve, false otherwise. | ||
*/ | ||
public static boolean isOnCurve(final byte[] publicKeyBytes) | ||
{ | ||
if (publicKeyBytes.length != 32) | ||
{ | ||
throw new IllegalArgumentException("Public key must be 32 bytes long"); | ||
} | ||
|
||
// elliptic curve equation dx^2y^2 + x^2 = y^2 - 1 (mod P) | ||
// let x^2 = u/v where u = y^2 - 1 & v = dy^2 + 1 (mod P) | ||
byte[] yBytes = publicKeyBytes.clone(); | ||
yBytes[31] &= 0x7F; | ||
// publicKey is in little endian encoding, so we must reverse the byte array before we "math" | ||
final BigInteger y = new BigInteger(1, reverseByteArray(yBytes)); | ||
final BigInteger y2 = y.multiply(y).mod(P); | ||
|
||
final BigInteger u = y2.subtract(BigInteger.ONE).mod(P); | ||
final BigInteger v = D.multiply(y2).add(BigInteger.ONE).mod(P); | ||
|
||
final BigInteger x1 = calculateCandidateRoot(u, v); | ||
|
||
return isCandidateRootValid(x1, v, u); | ||
} | ||
|
||
private static BigInteger calculateCandidateRoot(final BigInteger u, final BigInteger v) | ||
{ | ||
final BigInteger v3 = v.modPow(BigInteger.TEN, P).multiply(v).mod(P); | ||
final BigInteger v7 = v3.multiply(v3).multiply(v).mod(P); | ||
|
||
final BigInteger uv3 = u.multiply(v3).mod(P); | ||
|
||
final BigInteger uv7 = u.multiply(v7).mod(P); | ||
final BigInteger uv7Pow22523 = uv7.modPow(PM5D8, P); | ||
|
||
// after some transformations, given the properties of the e25519 curve we can say | ||
// x^2 = (u/v) | ||
// x1 = (u/v)^(P+3/8) where x1 is the candidate root | ||
// x1 = uv^3(uv^7)^(P-5/8) | ||
return uv3.multiply(uv7Pow22523).mod(P); | ||
} | ||
|
||
private static boolean isCandidateRootValid(final BigInteger x1, final BigInteger v, final BigInteger u) | ||
{ | ||
// given x1 = uv^3(uv^7)^(P-5/8) we can check to see if the candidate root satisfies | ||
// vx^2 = u (mod P) for x = x1 is a candidate root | ||
// vx^2 = -u (mod P) for x = x1 is a candidate root | ||
// if no roots then the point does not lie on the curve | ||
final BigInteger vx12 = v.multiply(x1.modPow(BigInteger.TWO, P)).mod(P); | ||
|
||
if (vx12.equals(u)) | ||
{ | ||
return true; | ||
} | ||
|
||
return vx12.equals(u.negate().mod(P)); | ||
} | ||
|
||
private static byte[] reverseByteArray(final byte[] array) | ||
{ | ||
final ByteBuffer buffer = ByteBuffer.allocate(array.length); | ||
|
||
for (int i = array.length - 1; i >= 0; i--) | ||
{ | ||
buffer.put(array[i]); | ||
} | ||
|
||
buffer.flip(); | ||
|
||
return buffer.array(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters