diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 106a49c7..55960c8b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,6 +47,31 @@ jobs: - name: Merge Conflict finder uses: olivernybroe/action-conflict-finder@v1.1 + - name: Install & build herumi/mcl + run: | + git clone https://github.com/herumi/mcl + cd mcl + mkdir build + cd build + cmake .. + make + + - name: Copy mcl library to /usr/local/lib + run: | + sudo cp $HOME/work/java-crypto/java-crypto/mcl/build/lib/libmcl.a /usr/local/lib/ + + - name: Build Java FFI + run: | + cd $HOME/work/java-crypto/java-crypto/mcl/ffi/java + mkdir build + cd build + cmake .. + cmake --build . --config Release + + - name: Copy libmcljava.so to /usr/local/lib + run: | + sudo cp $HOME/work/java-crypto/java-crypto/mcl/ffi/java/build/libmcljava.so /usr/local/lib/ + - name: Install Nix uses: cachix/install-nix-action@v27 @@ -57,7 +82,7 @@ jobs: NIX_PATH: $HOME/.nix-profile/bin - name: Set LD_LIBRARY_PATH - run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV + run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:$HOME/.nix-profile/lib" >> $GITHUB_ENV - name: Use Java Version 22 uses: actions/setup-java@v2 diff --git a/build.gradle b/build.gradle index 31eb39ef..ba943cdb 100644 --- a/build.gradle +++ b/build.gradle @@ -26,8 +26,20 @@ dependencies { implementation 'org.bitcoinj:bitcoinj-core:0.16.3' implementation files('libs/secp256k1-api-0.0.1.jar') implementation files('libs/secp256k1-foreign-0.0.1.jar') + // @see https://github.com/miracl/core/tree/master/java + implementation files('libs/core-4.0-SNAPSHOT.jar') implementation 'com.google.code.gson:gson:2.11.0' implementation 'com.google.guava:guava:30.2.0-jre' + implementation 'org.bouncycastle:bcprov-jdk15on:1.70' + // // https://mvnrepository.com/artifact/io.github.novacrypto/BIP39 + // implementation 'io.github.novacrypto:BIP39:0.1.9' + // // https://mvnrepository.com/artifact/com.github.komputing.kethereum/bip39 + // implementation 'com.github.komputing.kethereum:bip39:0.85.7' + // https://mvnrepository.com/artifact/org.nightcode/jbip39 + implementation 'org.nightcode:jbip39:0.1.1' + + + testImplementation 'org.slf4j:slf4j-api:2.0.13' testRuntimeOnly 'org.slf4j:slf4j-simple:2.0.13' @@ -42,7 +54,7 @@ test { useJUnitPlatform() testLogging { events 'PASSED', 'FAILED', 'SKIPPED' - showStandardStreams = true + showStandardStreams = true } } diff --git a/libs/core-4.0-SNAPSHOT.jar b/libs/core-4.0-SNAPSHOT.jar new file mode 100644 index 00000000..061d169e Binary files /dev/null and b/libs/core-4.0-SNAPSHOT.jar differ diff --git a/src/main/java/com/herumi/mcl/CipherText.java b/src/main/java/com/herumi/mcl/CipherText.java new file mode 100644 index 00000000..73de0798 --- /dev/null +++ b/src/main/java/com/herumi/mcl/CipherText.java @@ -0,0 +1,66 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class CipherText { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected CipherText(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(CipherText obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + ElgamalJNI.delete_CipherText(swigCPtr); + } + swigCPtr = 0; + } + } + + public String toStr() { + return ElgamalJNI.CipherText_toStr(swigCPtr, this); + } + + public String toString() { + return ElgamalJNI.CipherText_toString(swigCPtr, this); + } + + public void fromStr(String str) { + ElgamalJNI.CipherText_fromStr(swigCPtr, this, str); + } + + public void add(CipherText c) { + ElgamalJNI.CipherText_add(swigCPtr, this, CipherText.getCPtr(c), c); + } + + public void mul(int m) { + ElgamalJNI.CipherText_mul__SWIG_0(swigCPtr, this, m); + } + + public void mul(String str) { + ElgamalJNI.CipherText_mul__SWIG_1(swigCPtr, this, str); + } + + public CipherText() { + this(ElgamalJNI.new_CipherText(), true); + } +} diff --git a/src/main/java/com/herumi/mcl/Elgamal.java b/src/main/java/com/herumi/mcl/Elgamal.java new file mode 100644 index 00000000..40084888 --- /dev/null +++ b/src/main/java/com/herumi/mcl/Elgamal.java @@ -0,0 +1,37 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class Elgamal { + public static SWIGTYPE_p_bool new_p_bool() { + long cPtr = ElgamalJNI.new_p_bool(); + return (cPtr == 0) ? null : new SWIGTYPE_p_bool(cPtr, false); + } + + public static SWIGTYPE_p_bool copy_p_bool(boolean value) { + long cPtr = ElgamalJNI.copy_p_bool(value); + return (cPtr == 0) ? null : new SWIGTYPE_p_bool(cPtr, false); + } + + public static void delete_p_bool(SWIGTYPE_p_bool obj) { + ElgamalJNI.delete_p_bool(SWIGTYPE_p_bool.getCPtr(obj)); + } + + public static void p_bool_assign(SWIGTYPE_p_bool obj, boolean value) { + ElgamalJNI.p_bool_assign(SWIGTYPE_p_bool.getCPtr(obj), value); + } + + public static boolean p_bool_value(SWIGTYPE_p_bool obj) { + return ElgamalJNI.p_bool_value(SWIGTYPE_p_bool.getCPtr(obj)); + } + + public static void SystemInit(String param) { + ElgamalJNI.SystemInit(param); + } +} diff --git a/src/main/java/com/herumi/mcl/ElgamalJNI.java b/src/main/java/com/herumi/mcl/ElgamalJNI.java new file mode 100644 index 00000000..45c36d9a --- /dev/null +++ b/src/main/java/com/herumi/mcl/ElgamalJNI.java @@ -0,0 +1,100 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class ElgamalJNI { + public static final native long new_p_bool(); + + public static final native long copy_p_bool(boolean jarg1); + + public static final native void delete_p_bool(long jarg1); + + public static final native void p_bool_assign(long jarg1, boolean jarg2); + + public static final native boolean p_bool_value(long jarg1); + + public static final native void SystemInit(String jarg1); + + public static final native String CipherText_toStr(long jarg1, CipherText jarg1_); + + public static final native String CipherText_toString(long jarg1, CipherText jarg1_); + + public static final native void CipherText_fromStr(long jarg1, CipherText jarg1_, String jarg2); + + public static final native void CipherText_add( + long jarg1, CipherText jarg1_, long jarg2, CipherText jarg2_); + + public static final native void CipherText_mul__SWIG_0( + long jarg1, CipherText jarg1_, int jarg2); + + public static final native void CipherText_mul__SWIG_1( + long jarg1, CipherText jarg1_, String jarg2); + + public static final native long new_CipherText(); + + public static final native void delete_CipherText(long jarg1); + + public static final native String PublicKey_toStr(long jarg1, PublicKey jarg1_); + + public static final native String PublicKey_toString(long jarg1, PublicKey jarg1_); + + public static final native void PublicKey_fromStr(long jarg1, PublicKey jarg1_, String jarg2); + + public static final native void PublicKey_save(long jarg1, PublicKey jarg1_, String jarg2); + + public static final native void PublicKey_load(long jarg1, PublicKey jarg1_, String jarg2); + + public static final native void PublicKey_enc__SWIG_0( + long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, int jarg3); + + public static final native void PublicKey_enc__SWIG_1( + long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, String jarg3); + + public static final native void PublicKey_rerandomize( + long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_); + + public static final native void PublicKey_add__SWIG_0( + long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, int jarg3); + + public static final native void PublicKey_add__SWIG_1( + long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, String jarg3); + + public static final native long new_PublicKey(); + + public static final native void delete_PublicKey(long jarg1); + + public static final native String PrivateKey_toStr(long jarg1, PrivateKey jarg1_); + + public static final native String PrivateKey_toString(long jarg1, PrivateKey jarg1_); + + public static final native void PrivateKey_fromStr(long jarg1, PrivateKey jarg1_, String jarg2); + + public static final native void PrivateKey_save(long jarg1, PrivateKey jarg1_, String jarg2); + + public static final native void PrivateKey_load(long jarg1, PrivateKey jarg1_, String jarg2); + + public static final native void PrivateKey_init(long jarg1, PrivateKey jarg1_); + + public static final native long PrivateKey_getPublicKey(long jarg1, PrivateKey jarg1_); + + public static final native int PrivateKey_dec__SWIG_0( + long jarg1, PrivateKey jarg1_, long jarg2, CipherText jarg2_, long jarg3); + + public static final native int PrivateKey_dec__SWIG_1( + long jarg1, PrivateKey jarg1_, long jarg2, CipherText jarg2_); + + public static final native void PrivateKey_setCache( + long jarg1, PrivateKey jarg1_, int jarg2, int jarg3); + + public static final native void PrivateKey_clearCache(long jarg1, PrivateKey jarg1_); + + public static final native long new_PrivateKey(); + + public static final native void delete_PrivateKey(long jarg1); +} diff --git a/src/main/java/com/herumi/mcl/Fp.java b/src/main/java/com/herumi/mcl/Fp.java new file mode 100644 index 00000000..7adaaf2c --- /dev/null +++ b/src/main/java/com/herumi/mcl/Fp.java @@ -0,0 +1,106 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class Fp { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected Fp(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(Fp obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + MclJNI.delete_Fp(swigCPtr); + } + swigCPtr = 0; + } + } + + public Fp() { + this(MclJNI.new_Fp__SWIG_0(), true); + } + + public Fp(Fp rhs) { + this(MclJNI.new_Fp__SWIG_1(Fp.getCPtr(rhs), rhs), true); + } + + public Fp(int x) { + this(MclJNI.new_Fp__SWIG_2(x), true); + } + + public Fp(String str, int base) { + this(MclJNI.new_Fp__SWIG_3(str, base), true); + } + + public Fp(String str) { + this(MclJNI.new_Fp__SWIG_4(str), true); + } + + public boolean equals(Fp rhs) { + return MclJNI.Fp_equals(swigCPtr, this, Fp.getCPtr(rhs), rhs); + } + + public boolean isZero() { + return MclJNI.Fp_isZero(swigCPtr, this); + } + + public boolean isOne() { + return MclJNI.Fp_isOne(swigCPtr, this); + } + + public void setStr(String str, int base) { + MclJNI.Fp_setStr__SWIG_0(swigCPtr, this, str, base); + } + + public void setStr(String str) { + MclJNI.Fp_setStr__SWIG_1(swigCPtr, this, str); + } + + public void setInt(int x) { + MclJNI.Fp_setInt(swigCPtr, this, x); + } + + public void clear() { + MclJNI.Fp_clear(swigCPtr, this); + } + + public void setByCSPRNG() { + MclJNI.Fp_setByCSPRNG(swigCPtr, this); + } + + public String toString(int base) { + return MclJNI.Fp_toString__SWIG_0(swigCPtr, this, base); + } + + public String toString() { + return MclJNI.Fp_toString__SWIG_1(swigCPtr, this); + } + + public void deserialize(byte[] cbuf) { + MclJNI.Fp_deserialize(swigCPtr, this, cbuf); + } + + public byte[] serialize() { + return MclJNI.Fp_serialize(swigCPtr, this); + } +} diff --git a/src/main/java/com/herumi/mcl/Fr.java b/src/main/java/com/herumi/mcl/Fr.java new file mode 100644 index 00000000..15103ce2 --- /dev/null +++ b/src/main/java/com/herumi/mcl/Fr.java @@ -0,0 +1,114 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class Fr { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected Fr(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(Fr obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + MclJNI.delete_Fr(swigCPtr); + } + swigCPtr = 0; + } + } + + public Fr() { + this(MclJNI.new_Fr__SWIG_0(), true); + } + + public Fr(Fr rhs) { + this(MclJNI.new_Fr__SWIG_1(Fr.getCPtr(rhs), rhs), true); + } + + public Fr(int x) { + this(MclJNI.new_Fr__SWIG_2(x), true); + } + + public Fr(String str, int base) { + this(MclJNI.new_Fr__SWIG_3(str, base), true); + } + + public Fr(String str) { + this(MclJNI.new_Fr__SWIG_4(str), true); + } + + public boolean equals(Fr rhs) { + return MclJNI.Fr_equals(swigCPtr, this, Fr.getCPtr(rhs), rhs); + } + + public boolean isZero() { + return MclJNI.Fr_isZero(swigCPtr, this); + } + + public boolean isOne() { + return MclJNI.Fr_isOne(swigCPtr, this); + } + + public void setStr(String str, int base) { + MclJNI.Fr_setStr__SWIG_0(swigCPtr, this, str, base); + } + + public void setStr(String str) { + MclJNI.Fr_setStr__SWIG_1(swigCPtr, this, str); + } + + public void setInt(int x) { + MclJNI.Fr_setInt(swigCPtr, this, x); + } + + public void clear() { + MclJNI.Fr_clear(swigCPtr, this); + } + + public void setByCSPRNG() { + MclJNI.Fr_setByCSPRNG(swigCPtr, this); + } + + public String toString(int base) { + return MclJNI.Fr_toString__SWIG_0(swigCPtr, this, base); + } + + public String toString() { + return MclJNI.Fr_toString__SWIG_1(swigCPtr, this); + } + + public void deserialize(byte[] cbuf) { + MclJNI.Fr_deserialize(swigCPtr, this, cbuf); + } + + public void setLittleEndianMod(byte[] cbuf) { + MclJNI.Fr_setLittleEndianMod(swigCPtr, this, cbuf); + } + + public void setHashOf(byte[] cbuf) { + MclJNI.Fr_setHashOf(swigCPtr, this, cbuf); + } + + public byte[] serialize() { + return MclJNI.Fr_serialize(swigCPtr, this); + } +} diff --git a/src/main/java/com/herumi/mcl/G1.java b/src/main/java/com/herumi/mcl/G1.java new file mode 100644 index 00000000..4f36be2c --- /dev/null +++ b/src/main/java/com/herumi/mcl/G1.java @@ -0,0 +1,114 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class G1 { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected G1(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(G1 obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + MclJNI.delete_G1(swigCPtr); + } + swigCPtr = 0; + } + } + + public G1() { + this(MclJNI.new_G1__SWIG_0(), true); + } + + public G1(G1 rhs) { + this(MclJNI.new_G1__SWIG_1(G1.getCPtr(rhs), rhs), true); + } + + public G1(Fp x, Fp y) { + this(MclJNI.new_G1__SWIG_2(Fp.getCPtr(x), x, Fp.getCPtr(y), y), true); + } + + public boolean equals(G1 rhs) { + return MclJNI.G1_equals(swigCPtr, this, G1.getCPtr(rhs), rhs); + } + + public boolean isZero() { + return MclJNI.G1_isZero(swigCPtr, this); + } + + public boolean isValidOrder() { + return MclJNI.G1_isValidOrder(swigCPtr, this); + } + + public void set(Fp x, Fp y) { + MclJNI.G1_set(swigCPtr, this, Fp.getCPtr(x), x, Fp.getCPtr(y), y); + } + + public void clear() { + MclJNI.G1_clear(swigCPtr, this); + } + + public void setStr(String str, int base) { + MclJNI.G1_setStr__SWIG_0(swigCPtr, this, str, base); + } + + public void setStr(String str) { + MclJNI.G1_setStr__SWIG_1(swigCPtr, this, str); + } + + public String toString(int base) { + return MclJNI.G1_toString__SWIG_0(swigCPtr, this, base); + } + + public String toString() { + return MclJNI.G1_toString__SWIG_1(swigCPtr, this); + } + + public void deserialize(byte[] cbuf) { + MclJNI.G1_deserialize(swigCPtr, this, cbuf); + } + + public byte[] serialize() { + return MclJNI.G1_serialize(swigCPtr, this); + } + + public void normalize() { + MclJNI.G1_normalize(swigCPtr, this); + } + + public void tryAndIncMapTo(Fp x) { + MclJNI.G1_tryAndIncMapTo(swigCPtr, this, Fp.getCPtr(x), x); + } + + public Fp getX() { + return new Fp(MclJNI.G1_getX(swigCPtr, this), true); + } + + public Fp getY() { + return new Fp(MclJNI.G1_getY(swigCPtr, this), true); + } + + public Fp getZ() { + return new Fp(MclJNI.G1_getZ(swigCPtr, this), true); + } +} diff --git a/src/main/java/com/herumi/mcl/G2.java b/src/main/java/com/herumi/mcl/G2.java new file mode 100644 index 00000000..152c75e2 --- /dev/null +++ b/src/main/java/com/herumi/mcl/G2.java @@ -0,0 +1,114 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class G2 { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected G2(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(G2 obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + MclJNI.delete_G2(swigCPtr); + } + swigCPtr = 0; + } + } + + public G2() { + this(MclJNI.new_G2__SWIG_0(), true); + } + + public G2(G2 rhs) { + this(MclJNI.new_G2__SWIG_1(G2.getCPtr(rhs), rhs), true); + } + + public G2(Fp ax, Fp ay, Fp bx, Fp by) { + this( + MclJNI.new_G2__SWIG_2( + Fp.getCPtr(ax), + ax, + Fp.getCPtr(ay), + ay, + Fp.getCPtr(bx), + bx, + Fp.getCPtr(by), + by), + true); + } + + public boolean equals(G2 rhs) { + return MclJNI.G2_equals(swigCPtr, this, G2.getCPtr(rhs), rhs); + } + + public boolean isZero() { + return MclJNI.G2_isZero(swigCPtr, this); + } + + public void set(Fp ax, Fp ay, Fp bx, Fp by) { + MclJNI.G2_set( + swigCPtr, + this, + Fp.getCPtr(ax), + ax, + Fp.getCPtr(ay), + ay, + Fp.getCPtr(bx), + bx, + Fp.getCPtr(by), + by); + } + + public void clear() { + MclJNI.G2_clear(swigCPtr, this); + } + + public void setStr(String str, int base) { + MclJNI.G2_setStr__SWIG_0(swigCPtr, this, str, base); + } + + public void setStr(String str) { + MclJNI.G2_setStr__SWIG_1(swigCPtr, this, str); + } + + public String toString(int base) { + return MclJNI.G2_toString__SWIG_0(swigCPtr, this, base); + } + + public String toString() { + return MclJNI.G2_toString__SWIG_1(swigCPtr, this); + } + + public void deserialize(byte[] cbuf) { + MclJNI.G2_deserialize(swigCPtr, this, cbuf); + } + + public byte[] serialize() { + return MclJNI.G2_serialize(swigCPtr, this); + } + + public void normalize() { + MclJNI.G2_normalize(swigCPtr, this); + } +} diff --git a/src/main/java/com/herumi/mcl/GT.java b/src/main/java/com/herumi/mcl/GT.java new file mode 100644 index 00000000..25ceeca6 --- /dev/null +++ b/src/main/java/com/herumi/mcl/GT.java @@ -0,0 +1,82 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class GT { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected GT(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(GT obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + MclJNI.delete_GT(swigCPtr); + } + swigCPtr = 0; + } + } + + public GT() { + this(MclJNI.new_GT__SWIG_0(), true); + } + + public GT(GT rhs) { + this(MclJNI.new_GT__SWIG_1(GT.getCPtr(rhs), rhs), true); + } + + public boolean equals(GT rhs) { + return MclJNI.GT_equals(swigCPtr, this, GT.getCPtr(rhs), rhs); + } + + public boolean isOne() { + return MclJNI.GT_isOne(swigCPtr, this); + } + + public void clear() { + MclJNI.GT_clear(swigCPtr, this); + } + + public void setStr(String str, int base) { + MclJNI.GT_setStr__SWIG_0(swigCPtr, this, str, base); + } + + public void setStr(String str) { + MclJNI.GT_setStr__SWIG_1(swigCPtr, this, str); + } + + public String toString(int base) { + return MclJNI.GT_toString__SWIG_0(swigCPtr, this, base); + } + + public String toString() { + return MclJNI.GT_toString__SWIG_1(swigCPtr, this); + } + + public void deserialize(byte[] cbuf) { + MclJNI.GT_deserialize(swigCPtr, this, cbuf); + } + + public byte[] serialize() { + return MclJNI.GT_serialize(swigCPtr, this); + } +} diff --git a/src/main/java/com/herumi/mcl/Mcl.java b/src/main/java/com/herumi/mcl/Mcl.java new file mode 100644 index 00000000..9cf2f692 --- /dev/null +++ b/src/main/java/com/herumi/mcl/Mcl.java @@ -0,0 +1,135 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class Mcl implements MclConstants { + public static void SystemInit(int curveType) { + MclJNI.SystemInit(curveType); + } + + public static void neg(Fr y, Fr x) { + MclJNI.neg__SWIG_0(Fr.getCPtr(y), y, Fr.getCPtr(x), x); + } + + public static void inv(Fr y, Fr x) { + MclJNI.inv__SWIG_0(Fr.getCPtr(y), y, Fr.getCPtr(x), x); + } + + public static void add(Fr z, Fr x, Fr y) { + MclJNI.add__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void sub(Fr z, Fr x, Fr y) { + MclJNI.sub__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void mul(Fr z, Fr x, Fr y) { + MclJNI.mul__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void mul(G1 z, G1 x, Fr y) { + MclJNI.mul__SWIG_1(G1.getCPtr(z), z, G1.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void mul(G2 z, G2 x, Fr y) { + MclJNI.mul__SWIG_2(G2.getCPtr(z), z, G2.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void div(Fr z, Fr x, Fr y) { + MclJNI.div__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void pow(GT z, GT x, Fr y) { + MclJNI.pow(GT.getCPtr(z), z, GT.getCPtr(x), x, Fr.getCPtr(y), y); + } + + public static void neg(Fp y, Fp x) { + MclJNI.neg__SWIG_1(Fp.getCPtr(y), y, Fp.getCPtr(x), x); + } + + public static void inv(Fp y, Fp x) { + MclJNI.inv__SWIG_1(Fp.getCPtr(y), y, Fp.getCPtr(x), x); + } + + public static void add(Fp z, Fp x, Fp y) { + MclJNI.add__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y); + } + + public static void sub(Fp z, Fp x, Fp y) { + MclJNI.sub__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y); + } + + public static void mul(Fp z, Fp x, Fp y) { + MclJNI.mul__SWIG_3(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y); + } + + public static void div(Fp z, Fp x, Fp y) { + MclJNI.div__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y); + } + + public static void neg(G1 y, G1 x) { + MclJNI.neg__SWIG_2(G1.getCPtr(y), y, G1.getCPtr(x), x); + } + + public static void dbl(G1 y, G1 x) { + MclJNI.dbl__SWIG_0(G1.getCPtr(y), y, G1.getCPtr(x), x); + } + + public static void add(G1 z, G1 x, G1 y) { + MclJNI.add__SWIG_2(G1.getCPtr(z), z, G1.getCPtr(x), x, G1.getCPtr(y), y); + } + + public static void sub(G1 z, G1 x, G1 y) { + MclJNI.sub__SWIG_2(G1.getCPtr(z), z, G1.getCPtr(x), x, G1.getCPtr(y), y); + } + + public static void pairing(GT e, G1 P, G2 Q) { + MclJNI.pairing(GT.getCPtr(e), e, G1.getCPtr(P), P, G2.getCPtr(Q), Q); + } + + public static void hashAndMapToG1(G1 P, byte[] cbuf) { + MclJNI.hashAndMapToG1(G1.getCPtr(P), P, cbuf); + } + + public static void neg(G2 y, G2 x) { + MclJNI.neg__SWIG_3(G2.getCPtr(y), y, G2.getCPtr(x), x); + } + + public static void dbl(G2 y, G2 x) { + MclJNI.dbl__SWIG_1(G2.getCPtr(y), y, G2.getCPtr(x), x); + } + + public static void add(G2 z, G2 x, G2 y) { + MclJNI.add__SWIG_3(G2.getCPtr(z), z, G2.getCPtr(x), x, G2.getCPtr(y), y); + } + + public static void sub(G2 z, G2 x, G2 y) { + MclJNI.sub__SWIG_3(G2.getCPtr(z), z, G2.getCPtr(x), x, G2.getCPtr(y), y); + } + + public static void hashAndMapToG2(G2 P, byte[] cbuf) { + MclJNI.hashAndMapToG2(G2.getCPtr(P), P, cbuf); + } + + public static void mul(GT z, GT x, GT y) { + MclJNI.mul__SWIG_4(GT.getCPtr(z), z, GT.getCPtr(x), x, GT.getCPtr(y), y); + } + + public static void inv(GT y, GT x) { + MclJNI.inv__SWIG_2(GT.getCPtr(y), y, GT.getCPtr(x), x); + } + + public static void verifyOrderG1(boolean doVerify) { + MclJNI.verifyOrderG1(doVerify); + } + + public static void verifyOrderG2(boolean doVerify) { + MclJNI.verifyOrderG2(doVerify); + } +} diff --git a/src/main/java/com/herumi/mcl/MclConstants.java b/src/main/java/com/herumi/mcl/MclConstants.java new file mode 100644 index 00000000..9e20bc9d --- /dev/null +++ b/src/main/java/com/herumi/mcl/MclConstants.java @@ -0,0 +1,15 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public interface MclConstants { + public static final int BN254 = 0; + public static final int BLS12_381 = 5; + public static final int SECP256K1 = 102; +} diff --git a/src/main/java/com/herumi/mcl/MclJNI.java b/src/main/java/com/herumi/mcl/MclJNI.java new file mode 100644 index 00000000..81a4fd9d --- /dev/null +++ b/src/main/java/com/herumi/mcl/MclJNI.java @@ -0,0 +1,284 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class MclJNI { + public static final native void SystemInit(int jarg1); + + public static final native void neg__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_); + + public static final native void inv__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_); + + public static final native void add__SWIG_0( + long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_); + + public static final native void sub__SWIG_0( + long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_); + + public static final native void mul__SWIG_0( + long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_); + + public static final native void mul__SWIG_1( + long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, Fr jarg3_); + + public static final native void mul__SWIG_2( + long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, Fr jarg3_); + + public static final native void div__SWIG_0( + long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_); + + public static final native void pow( + long jarg1, GT jarg1_, long jarg2, GT jarg2_, long jarg3, Fr jarg3_); + + public static final native long new_Fr__SWIG_0(); + + public static final native long new_Fr__SWIG_1(long jarg1, Fr jarg1_); + + public static final native long new_Fr__SWIG_2(int jarg1); + + public static final native long new_Fr__SWIG_3(String jarg1, int jarg2); + + public static final native long new_Fr__SWIG_4(String jarg1); + + public static final native boolean Fr_equals(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_); + + public static final native boolean Fr_isZero(long jarg1, Fr jarg1_); + + public static final native boolean Fr_isOne(long jarg1, Fr jarg1_); + + public static final native void Fr_setStr__SWIG_0( + long jarg1, Fr jarg1_, String jarg2, int jarg3); + + public static final native void Fr_setStr__SWIG_1(long jarg1, Fr jarg1_, String jarg2); + + public static final native void Fr_setInt(long jarg1, Fr jarg1_, int jarg2); + + public static final native void Fr_clear(long jarg1, Fr jarg1_); + + public static final native void Fr_setByCSPRNG(long jarg1, Fr jarg1_); + + public static final native String Fr_toString__SWIG_0(long jarg1, Fr jarg1_, int jarg2); + + public static final native String Fr_toString__SWIG_1(long jarg1, Fr jarg1_); + + public static final native void Fr_deserialize(long jarg1, Fr jarg1_, byte[] jarg2); + + public static final native void Fr_setLittleEndianMod(long jarg1, Fr jarg1_, byte[] jarg2); + + public static final native void Fr_setHashOf(long jarg1, Fr jarg1_, byte[] jarg2); + + public static final native byte[] Fr_serialize(long jarg1, Fr jarg1_); + + public static final native void delete_Fr(long jarg1); + + public static final native void neg__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_); + + public static final native void inv__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_); + + public static final native void add__SWIG_1( + long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_); + + public static final native void sub__SWIG_1( + long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_); + + public static final native void mul__SWIG_3( + long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_); + + public static final native void div__SWIG_1( + long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_); + + public static final native long new_Fp__SWIG_0(); + + public static final native long new_Fp__SWIG_1(long jarg1, Fp jarg1_); + + public static final native long new_Fp__SWIG_2(int jarg1); + + public static final native long new_Fp__SWIG_3(String jarg1, int jarg2); + + public static final native long new_Fp__SWIG_4(String jarg1); + + public static final native boolean Fp_equals(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_); + + public static final native boolean Fp_isZero(long jarg1, Fp jarg1_); + + public static final native boolean Fp_isOne(long jarg1, Fp jarg1_); + + public static final native void Fp_setStr__SWIG_0( + long jarg1, Fp jarg1_, String jarg2, int jarg3); + + public static final native void Fp_setStr__SWIG_1(long jarg1, Fp jarg1_, String jarg2); + + public static final native void Fp_setInt(long jarg1, Fp jarg1_, int jarg2); + + public static final native void Fp_clear(long jarg1, Fp jarg1_); + + public static final native void Fp_setByCSPRNG(long jarg1, Fp jarg1_); + + public static final native String Fp_toString__SWIG_0(long jarg1, Fp jarg1_, int jarg2); + + public static final native String Fp_toString__SWIG_1(long jarg1, Fp jarg1_); + + public static final native void Fp_deserialize(long jarg1, Fp jarg1_, byte[] jarg2); + + public static final native byte[] Fp_serialize(long jarg1, Fp jarg1_); + + public static final native void delete_Fp(long jarg1); + + public static final native void neg__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_); + + public static final native void dbl__SWIG_0(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_); + + public static final native void add__SWIG_2( + long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, G1 jarg3_); + + public static final native void sub__SWIG_2( + long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, G1 jarg3_); + + public static final native void pairing( + long jarg1, GT jarg1_, long jarg2, G1 jarg2_, long jarg3, G2 jarg3_); + + public static final native void hashAndMapToG1(long jarg1, G1 jarg1_, byte[] jarg2); + + public static final native long new_G1__SWIG_0(); + + public static final native long new_G1__SWIG_1(long jarg1, G1 jarg1_); + + public static final native long new_G1__SWIG_2(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_); + + public static final native boolean G1_equals(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_); + + public static final native boolean G1_isZero(long jarg1, G1 jarg1_); + + public static final native boolean G1_isValidOrder(long jarg1, G1 jarg1_); + + public static final native void G1_set( + long jarg1, G1 jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_); + + public static final native void G1_clear(long jarg1, G1 jarg1_); + + public static final native void G1_setStr__SWIG_0( + long jarg1, G1 jarg1_, String jarg2, int jarg3); + + public static final native void G1_setStr__SWIG_1(long jarg1, G1 jarg1_, String jarg2); + + public static final native String G1_toString__SWIG_0(long jarg1, G1 jarg1_, int jarg2); + + public static final native String G1_toString__SWIG_1(long jarg1, G1 jarg1_); + + public static final native void G1_deserialize(long jarg1, G1 jarg1_, byte[] jarg2); + + public static final native byte[] G1_serialize(long jarg1, G1 jarg1_); + + public static final native void G1_normalize(long jarg1, G1 jarg1_); + + public static final native void G1_tryAndIncMapTo(long jarg1, G1 jarg1_, long jarg2, Fp jarg2_); + + public static final native long G1_getX(long jarg1, G1 jarg1_); + + public static final native long G1_getY(long jarg1, G1 jarg1_); + + public static final native long G1_getZ(long jarg1, G1 jarg1_); + + public static final native void delete_G1(long jarg1); + + public static final native void neg__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_); + + public static final native void dbl__SWIG_1(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_); + + public static final native void add__SWIG_3( + long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, G2 jarg3_); + + public static final native void sub__SWIG_3( + long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, G2 jarg3_); + + public static final native void hashAndMapToG2(long jarg1, G2 jarg1_, byte[] jarg2); + + public static final native long new_G2__SWIG_0(); + + public static final native long new_G2__SWIG_1(long jarg1, G2 jarg1_); + + public static final native long new_G2__SWIG_2( + long jarg1, + Fp jarg1_, + long jarg2, + Fp jarg2_, + long jarg3, + Fp jarg3_, + long jarg4, + Fp jarg4_); + + public static final native boolean G2_equals(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_); + + public static final native boolean G2_isZero(long jarg1, G2 jarg1_); + + public static final native void G2_set( + long jarg1, + G2 jarg1_, + long jarg2, + Fp jarg2_, + long jarg3, + Fp jarg3_, + long jarg4, + Fp jarg4_, + long jarg5, + Fp jarg5_); + + public static final native void G2_clear(long jarg1, G2 jarg1_); + + public static final native void G2_setStr__SWIG_0( + long jarg1, G2 jarg1_, String jarg2, int jarg3); + + public static final native void G2_setStr__SWIG_1(long jarg1, G2 jarg1_, String jarg2); + + public static final native String G2_toString__SWIG_0(long jarg1, G2 jarg1_, int jarg2); + + public static final native String G2_toString__SWIG_1(long jarg1, G2 jarg1_); + + public static final native void G2_deserialize(long jarg1, G2 jarg1_, byte[] jarg2); + + public static final native byte[] G2_serialize(long jarg1, G2 jarg1_); + + public static final native void G2_normalize(long jarg1, G2 jarg1_); + + public static final native void delete_G2(long jarg1); + + public static final native void mul__SWIG_4( + long jarg1, GT jarg1_, long jarg2, GT jarg2_, long jarg3, GT jarg3_); + + public static final native void inv__SWIG_2(long jarg1, GT jarg1_, long jarg2, GT jarg2_); + + public static final native long new_GT__SWIG_0(); + + public static final native long new_GT__SWIG_1(long jarg1, GT jarg1_); + + public static final native boolean GT_equals(long jarg1, GT jarg1_, long jarg2, GT jarg2_); + + public static final native boolean GT_isOne(long jarg1, GT jarg1_); + + public static final native void GT_clear(long jarg1, GT jarg1_); + + public static final native void GT_setStr__SWIG_0( + long jarg1, GT jarg1_, String jarg2, int jarg3); + + public static final native void GT_setStr__SWIG_1(long jarg1, GT jarg1_, String jarg2); + + public static final native String GT_toString__SWIG_0(long jarg1, GT jarg1_, int jarg2); + + public static final native String GT_toString__SWIG_1(long jarg1, GT jarg1_); + + public static final native void GT_deserialize(long jarg1, GT jarg1_, byte[] jarg2); + + public static final native byte[] GT_serialize(long jarg1, GT jarg1_); + + public static final native void delete_GT(long jarg1); + + public static final native void verifyOrderG1(boolean jarg1); + + public static final native void verifyOrderG2(boolean jarg1); +} diff --git a/src/main/java/com/herumi/mcl/PrivateKey.java b/src/main/java/com/herumi/mcl/PrivateKey.java new file mode 100644 index 00000000..978e0d37 --- /dev/null +++ b/src/main/java/com/herumi/mcl/PrivateKey.java @@ -0,0 +1,87 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class PrivateKey { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected PrivateKey(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(PrivateKey obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + ElgamalJNI.delete_PrivateKey(swigCPtr); + } + swigCPtr = 0; + } + } + + public String toStr() { + return ElgamalJNI.PrivateKey_toStr(swigCPtr, this); + } + + public String toString() { + return ElgamalJNI.PrivateKey_toString(swigCPtr, this); + } + + public void fromStr(String str) { + ElgamalJNI.PrivateKey_fromStr(swigCPtr, this, str); + } + + public void save(String fileName) { + ElgamalJNI.PrivateKey_save(swigCPtr, this, fileName); + } + + public void load(String fileName) { + ElgamalJNI.PrivateKey_load(swigCPtr, this, fileName); + } + + public void init() { + ElgamalJNI.PrivateKey_init(swigCPtr, this); + } + + public PublicKey getPublicKey() { + return new PublicKey(ElgamalJNI.PrivateKey_getPublicKey(swigCPtr, this), true); + } + + public int dec(CipherText c, SWIGTYPE_p_bool b) { + return ElgamalJNI.PrivateKey_dec__SWIG_0( + swigCPtr, this, CipherText.getCPtr(c), c, SWIGTYPE_p_bool.getCPtr(b)); + } + + public int dec(CipherText c) { + return ElgamalJNI.PrivateKey_dec__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c); + } + + public void setCache(int rangeMin, int rangeMax) { + ElgamalJNI.PrivateKey_setCache(swigCPtr, this, rangeMin, rangeMax); + } + + public void clearCache() { + ElgamalJNI.PrivateKey_clearCache(swigCPtr, this); + } + + public PrivateKey() { + this(ElgamalJNI.new_PrivateKey(), true); + } +} diff --git a/src/main/java/com/herumi/mcl/PublicKey.java b/src/main/java/com/herumi/mcl/PublicKey.java new file mode 100644 index 00000000..db8269c7 --- /dev/null +++ b/src/main/java/com/herumi/mcl/PublicKey.java @@ -0,0 +1,82 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class PublicKey { + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected PublicKey(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(PublicKey obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + @SuppressWarnings("deprecation") + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + ElgamalJNI.delete_PublicKey(swigCPtr); + } + swigCPtr = 0; + } + } + + public String toStr() { + return ElgamalJNI.PublicKey_toStr(swigCPtr, this); + } + + public String toString() { + return ElgamalJNI.PublicKey_toString(swigCPtr, this); + } + + public void fromStr(String str) { + ElgamalJNI.PublicKey_fromStr(swigCPtr, this, str); + } + + public void save(String fileName) { + ElgamalJNI.PublicKey_save(swigCPtr, this, fileName); + } + + public void load(String fileName) { + ElgamalJNI.PublicKey_load(swigCPtr, this, fileName); + } + + public void enc(CipherText c, int m) { + ElgamalJNI.PublicKey_enc__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, m); + } + + public void enc(CipherText c, String str) { + ElgamalJNI.PublicKey_enc__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c, str); + } + + public void rerandomize(CipherText c) { + ElgamalJNI.PublicKey_rerandomize(swigCPtr, this, CipherText.getCPtr(c), c); + } + + public void add(CipherText c, int m) { + ElgamalJNI.PublicKey_add__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, m); + } + + public void add(CipherText c, String str) { + ElgamalJNI.PublicKey_add__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c, str); + } + + public PublicKey() { + this(ElgamalJNI.new_PublicKey(), true); + } +} diff --git a/src/main/java/com/herumi/mcl/SWIGTYPE_p_bool.java b/src/main/java/com/herumi/mcl/SWIGTYPE_p_bool.java new file mode 100644 index 00000000..5f7e951a --- /dev/null +++ b/src/main/java/com/herumi/mcl/SWIGTYPE_p_bool.java @@ -0,0 +1,25 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package com.herumi.mcl; + +public class SWIGTYPE_p_bool { + private transient long swigCPtr; + + protected SWIGTYPE_p_bool(long cPtr, @SuppressWarnings("unused") boolean futureUse) { + swigCPtr = cPtr; + } + + protected SWIGTYPE_p_bool() { + swigCPtr = 0; + } + + protected static long getCPtr(SWIGTYPE_p_bool obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/identities/bls/KeyPairFactory.java b/src/main/java/org/arkecosystem/crypto/identities/bls/KeyPairFactory.java new file mode 100644 index 00000000..2e3c8c5a --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/identities/bls/KeyPairFactory.java @@ -0,0 +1,220 @@ +package org.arkecosystem.crypto.identities.bls; + +import com.herumi.mcl.Fr; +import com.herumi.mcl.G1; +import com.herumi.mcl.Mcl; +import com.herumi.mcl.MclConstants; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.signature.bls.BlsConstants; +import org.arkecosystem.crypto.signature.bls.JNIEnv; +import org.bitcoinj.core.Sha256Hash; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.generators.HKDFBytesGenerator; +import org.bouncycastle.crypto.params.HKDFParameters; +import org.nightcode.bip39.Bip39; +import org.nightcode.bip39.Bip39Exception; +import org.nightcode.bip39.dictionary.EnglishDictionary; + +public class KeyPairFactory { + + static { + String lib = "mcljava"; + JNIEnv env = new JNIEnv(); + env.prepare(); + System.loadLibrary(lib); + } + + private static final BigInteger BLS_R = + new BigInteger( + "52435875175126190479447740508185965837690552500527637822603658699938581184513"); + + public KeyPairFactory() { + Mcl.SystemInit(MclConstants.BLS12_381); + } + + public KeyPair fromPassphrase(String passphrase) { + Bip39 bip39 = new Bip39(EnglishDictionary.instance()); + + try { + byte[] seed = bip39.createSeed(passphrase, ""); + + byte[] masterKey = deriveMaster(seed); + + byte[] privateKey = deriveChild(masterKey, BigInteger.ZERO); + + return fromPrivateKey(privateKey); + } catch (Bip39Exception e) { + throw new RuntimeException("Failed to generate seed from passphrase", e); + } + } + + public static byte[] deriveMaster(byte[] seed) { + return hkdfModR(seed); + } + + public static byte[] deriveChild(byte[] parentKey, BigInteger index) { + try { + byte[] salt = i2osp(index, 4); + + byte[] lamportPK = parentSKToLamportPK(parentKey, salt); + + return hkdfModR(lamportPK); + } catch (Exception e) { + throw new RuntimeException("Failed to derive child key", e); + } + } + + private static byte[] parentSKToLamportPK(byte[] parentSK, byte[] index) { + byte[][] lamport0 = ikmToLamportSK(parentSK, index); + byte[] notParentSK = invertBytes(parentSK); + byte[][] lamport1 = ikmToLamportSK(notParentSK, index); + + byte[][] hashedParts = new byte[lamport0.length + lamport1.length][32]; + + for (int i = 0; i < lamport0.length; i++) { + hashedParts[i] = Sha256Hash.hash(lamport0[i]); + } + + for (int i = 0; i < lamport1.length; i++) { + hashedParts[lamport0.length + i] = Sha256Hash.hash(lamport1[i]); + } + + byte[] concatenated = concatArrays(hashedParts); + + return Sha256Hash.hash(concatenated); + } + + private static byte[][] ikmToLamportSK(byte[] ikm, byte[] salt) { + HKDFParameters hkdfParams = new HKDFParameters(ikm, salt, null); + HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA256Digest()); + hkdf.init(hkdfParams); + + byte[] okm = new byte[32 * 255]; + hkdf.generateBytes(okm, 0, okm.length); + + byte[][] sk = new byte[255][32]; + for (int i = 0; i < 255; i++) { + System.arraycopy(okm, i * 32, sk[i], 0, 32); + } + return sk; + } + + private static byte[] hkdfModR(byte[] ikm) { + try { + byte[] salt = "BLS-SIG-KEYGEN-SALT-".getBytes(StandardCharsets.UTF_8); + + byte[] input = concat(ikm, new byte[] {0x00}); + + byte[] label = new byte[] {0x00, 0x30}; + + byte[] okm = null; + + BigInteger SK = BigInteger.ZERO; + + while (SK.equals(BigInteger.ZERO)) { + salt = Sha256Hash.hash(salt); + + HKDFParameters hkdfParams = new HKDFParameters(input, salt, label); + HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA256Digest()); + hkdf.init(hkdfParams); + + okm = new byte[48]; + hkdf.generateBytes(okm, 0, okm.length); + + SK = new BigInteger(1, okm).mod(BLS_R); + } + + return i2osp(SK, 32); + } catch (Exception e) { + throw new RuntimeException("Failed to derive master key", e); + } + } + + private static byte[] invertBytes(byte[] bytes) { + byte[] inverted = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + inverted[i] = (byte) ~bytes[i]; + } + return inverted; + } + + private static byte[] concatArrays(byte[][] arrays) { + int length = 0; + for (byte[] array : arrays) { + length += array.length; + } + byte[] result = new byte[length]; + int pos = 0; + for (byte[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + private static byte[] i2osp(BigInteger value, int length) { + byte[] result = new byte[length]; + byte[] bytes = value.toByteArray(); + int srcPos = Math.max(0, bytes.length - length); + int destPos = Math.max(0, length - bytes.length); + int len = Math.min(bytes.length, length); + System.arraycopy(bytes, srcPos, result, destPos, len); + return result; + } + + private static byte[] concat(byte[]... arrays) { + int length = 0; + for (byte[] array : arrays) { + length += array.length; + } + byte[] result = new byte[length]; + int pos = 0; + for (byte[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + public KeyPair fromPrivateKey(byte[] privateKeyBytes) { + Fr privateKey = new Fr(); + privateKey.setLittleEndianMod(privateKeyBytes); + + G1 basePoint = new G1(); + basePoint.setStr(BlsConstants.BaseG1); + + G1 publicKey = new G1(); + Mcl.mul(publicKey, basePoint, privateKey); + + byte[] publicKeyBytes = publicKey.serialize(); + String privateKeyHex = Hex.encode(privateKeyBytes); + String publicKeyHex = Hex.encode(publicKeyBytes); + + System.out.println("Private key: " + privateKeyHex); + System.out.println("Public key: " + publicKeyHex); + System.out.println( + "Expected Public key: b4865127896c3c5286296a7b26e7c8002586a3ecf5832bfb59e689336f1f4c75e10491b9dfaed8dfb2c2fbe22d11fa93"); + + return new KeyPair(privateKeyHex, publicKeyHex); + } + + public static class KeyPair { + private final String privateKey; + private final String publicKey; + + public KeyPair(String privateKey, String publicKey) { + this.privateKey = privateKey; + this.publicKey = publicKey; + } + + public String getPrivateKey() { + return privateKey; + } + + public String getPublicKey() { + return publicKey; + } + } +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java b/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java index 40beaf36..b8bef877 100644 --- a/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java +++ b/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java @@ -1,6 +1,6 @@ package org.arkecosystem.crypto.signature; -import org.arkecosystem.crypto.Schnorr; +import org.arkecosystem.crypto.utils.Schnorr; import org.bitcoinj.core.ECKey; import org.bitcoinj.secp256k1.api.P256K1KeyPair; import org.bitcoinj.secp256k1.api.P256k1PrivKey; diff --git a/src/main/java/org/arkecosystem/crypto/signature/bls/Bls.java b/src/main/java/org/arkecosystem/crypto/signature/bls/Bls.java new file mode 100644 index 00000000..ee61bec9 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/bls/Bls.java @@ -0,0 +1,118 @@ +package org.arkecosystem.crypto.signature.bls; + +import com.herumi.mcl.G1; +import com.herumi.mcl.G2; +import com.herumi.mcl.GT; +import com.herumi.mcl.Mcl; +import org.arkecosystem.crypto.utils.Schnorr; + +public class Bls implements BlsConstants { + static { + String lib = "mcljava"; + JNIEnv env = new JNIEnv(); + env.prepare(); + System.loadLibrary(lib); + } + + public void validateBlsPublicKey(String publicKeyHex) { + G1 publicKey = new G1(); + + try { + publicKey.deserialize(Schnorr.hexStringToByteArray(publicKeyHex)); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid BLS public key"); + } + } + + private int curveType; + + /* + * Generate private key + */ + public PrivateKey generateSecKey() { + PrivateKey privateKey = new PrivateKey(curveType); + return privateKey; + } + + public Bls(int curveType) { + this.curveType = curveType; + Mcl.SystemInit(curveType); + } + + /* + * Aggregate signatures + */ + public byte[] aggregateSignature(byte[][] s) { + G2[] ss = new G2[s.length]; + for (int i = 0; i < s.length; i++) { + ss[i] = new G2(); + ss[i].deserialize(s[i]); + } + for (int i = 1; i < s.length; i++) { + Mcl.add(ss[0], ss[0], ss[i]); + } + return ss[0].serialize(); + } + + /* + * Aggregate public key + */ + public byte[] aggregatePublicKey(byte[][] pub) { + G1[] pubs = new G1[pub.length]; + for (int i = 0; i < pub.length; i++) { + pubs[i] = new G1(); + pubs[i].deserialize(pub[i]); + } + for (int i = 1; i < pub.length; i++) { + Mcl.add(pubs[0], pubs[0], pubs[i]); + } + return pubs[0].serialize(); + } + + /* + * Aggregate message to be signed + */ + public byte[] aggregateMsg(byte[][] msg) { + G2[] msgs = new G2[msg.length]; + for (int i = 0; i < msg.length; i++) { + msgs[i] = new G2(); + Mcl.hashAndMapToG2(msgs[i], msg[i]); + } + for (int i = 1; i < msg.length; i++) { + Mcl.add(msgs[0], msgs[0], msgs[i]); + } + return msgs[0].serialize(); + } + + /* + * Verify aggregate signature + * Case: multiple messages, multiple private keys with multiple signatures + */ + public boolean verifyAggregate(byte[][] msg, byte[] sig, byte[][] pub) { + G2[] H = new G2[msg.length]; + for (int i = 0; i < msg.length; i++) { + H[i] = new G2(); + Mcl.hashAndMapToG2(H[i], msg[i]); + } + G1[] pubs = new G1[pub.length]; + for (int i = 0; i < pub.length; i++) { + pubs[i] = new G1(); + pubs[i].deserialize(pub[i]); + } + G1 Q = new G1(); + Q.setStr(Bls.BaseG1); + G2 g2 = new G2(); + g2.deserialize(sig); + GT[] e1 = new GT[msg.length]; + GT e2 = new GT(); + for (int i = 0; i < msg.length; i++) { + e1[i] = new GT(); + Mcl.pairing(e1[i], pubs[i], H[i]); // e1 = e(H, s Q) + } + for (int i = 1; i < msg.length; i++) { + Mcl.mul(e1[0], e1[0], e1[i]); + } + Mcl.pairing(e2, Q, g2); // e2 = e(s H, Q); + return e1[0].equals(e2); + } +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/bls/BlsConstants.java b/src/main/java/org/arkecosystem/crypto/signature/bls/BlsConstants.java new file mode 100644 index 00000000..5954a218 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/bls/BlsConstants.java @@ -0,0 +1,7 @@ +package org.arkecosystem.crypto.signature.bls; + +public interface BlsConstants { + public static final int BLS12_381 = 5; + public static final String BaseG1 = + "1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569"; +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/bls/JNIEnv.java b/src/main/java/org/arkecosystem/crypto/signature/bls/JNIEnv.java new file mode 100644 index 00000000..b0e13e12 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/bls/JNIEnv.java @@ -0,0 +1,83 @@ +package org.arkecosystem.crypto.signature.bls; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class JNIEnv { + byte[] cache; + List sources; + + public JNIEnv() { + cache = new byte[1024]; + sources = new LinkedList(); + String OS = System.getProperty("os.name").toLowerCase(); + String ARCH = System.getProperty(("os.arch")).toLowerCase(); + if (OS.contains("mac") && (ARCH.contains("x86_64") || ARCH.contains("aarch64"))) { + sources.add("libmcljava.dylib"); + } else if (OS.contains("linux") && ARCH.contains("amd64")) { + sources.add("libmcljava.so"); + } + } + + private Boolean sourceExist(String sourceName) { + System.out.println("[JNIDEV]:CHECKING JNI LIB:" + System.getProperty("java.library.path")); + String[] libraryPaths = System.getProperty("java.library.path").split(File.pathSeparator); + for (String path : libraryPaths) { + File f = new File(path, sourceName); + if (f.exists()) { + return true; + } + } + return false; + } + + public void prepare() { + for (String s : sources) { + copy(s); + } + } + + public Boolean copy(String sourceName) { + if (sourceExist(sourceName)) { + return true; + } else { + try { + String[] libraryPaths = + System.getProperty("java.library.path").split(File.pathSeparator); + File f = + new File( + libraryPaths[0], + sourceName); // Using the first path in java.library.path + if (!f.exists()) { + f.createNewFile(); + System.out.println("[JNIDEV]:DEFAULT JNI INITION:" + sourceName); + } + FileOutputStream os = new FileOutputStream(f); + + InputStream is = + getClass() + .getResourceAsStream( + "/" + sourceName); // Modified to add leading slash + if (is == null) { + os.close(); + return false; + } + Arrays.fill(cache, (byte) 0); + int realRead = is.read(cache); + while (realRead != -1) { + os.write(cache, 0, realRead); + realRead = is.read(cache); + } + os.close(); + } catch (Exception e) { + System.out.println("[JNIDEV]:ERROR IN COPY JNI LIB!"); + return false; + } + } + return true; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/bls/PrivateKey.java b/src/main/java/org/arkecosystem/crypto/signature/bls/PrivateKey.java new file mode 100644 index 00000000..1545cfa9 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/bls/PrivateKey.java @@ -0,0 +1,62 @@ +package org.arkecosystem.crypto.signature.bls; + +import com.herumi.mcl.Fr; +import com.herumi.mcl.G1; +import com.herumi.mcl.G2; +import com.herumi.mcl.Mcl; + +public class PrivateKey implements java.security.PrivateKey { + private int curveType; + private byte[] secKey; + + @Override + public String getAlgorithm() { + if (curveType == Bls.BLS12_381) { + return "BLS12-381"; + } else { + return "NOT SUPPORTED"; + } + } + + @Override + public String getFormat() { + return null; + } + + @Override + public byte[] getEncoded() { + return secKey; + } + + public PrivateKey(int curveType) { + this.curveType = curveType; + Fr fr = new Fr(); + fr.setByCSPRNG(); + secKey = fr.serialize(); + } + + public PublicKey getPublicKey() { + G1 Q = new G1(); + Q.setStr(Bls.BaseG1); + G1 pub = new G1(); + Fr fr = new Fr(); + fr.deserialize(secKey); + Mcl.mul(pub, Q, fr); + + PublicKey publicKey = new PublicKey(curveType, pub.serialize()); + return publicKey; + } + + /* + * Sign a message + */ + public byte[] sign(byte[] msg) { + G2 H = new G2(); + Mcl.hashAndMapToG2(H, msg); // H = Hash(m) + G2 sig = new G2(); + Fr fr = new Fr(); + fr.deserialize(secKey); + Mcl.mul(sig, H, fr); // signature of m = s H + return sig.serialize(); + } +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/bls/PublicKey.java b/src/main/java/org/arkecosystem/crypto/signature/bls/PublicKey.java new file mode 100644 index 00000000..8ee00c8a --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/bls/PublicKey.java @@ -0,0 +1,78 @@ +package org.arkecosystem.crypto.signature.bls; + +import com.herumi.mcl.G1; +import com.herumi.mcl.G2; +import com.herumi.mcl.GT; +import com.herumi.mcl.Mcl; + +public class PublicKey implements java.security.PublicKey { + private int curveType; + private byte[] pubKey; + + @Override + public String getAlgorithm() { + if (curveType == Bls.BLS12_381) { + return "BLS12-381"; + } else { + return "NOT SUPPORTED"; + } + } + + @Override + public String getFormat() { + return null; + } + + @Override + public byte[] getEncoded() { + return pubKey; + } + + public PublicKey(int curveType, byte[] pubKey) { + this.curveType = curveType; + this.pubKey = pubKey; + } + + /* + * Veryfi signature + * Case 1: single message and single signature + * Case 2: single message and multiple signatures + */ + public boolean verify(byte[] msg, byte[] sig) { + G2 H = new G2(); + Mcl.hashAndMapToG2(H, msg); // H = Hash(m) + G1 pub = new G1(); + pub.deserialize(pubKey); + G1 Q = new G1(); + Q.setStr(Bls.BaseG1); + G2 g2 = new G2(); + g2.deserialize(sig); + GT e1 = new GT(); + GT e2 = new GT(); + Mcl.pairing(e1, pub, H); // e1 = e(H, s Q) + Mcl.pairing(e2, Q, g2); // e2 = e(s H, Q); + return e1.equals(e2); + } + + /* + * Verify mutiple signatures + * Case: Single private key and multiple messages with multiple signatures + * h: Not the message itself, it's result of hashAndMapToG2 + */ + public boolean verifyAggregate(byte[] h, byte[] sig) { + G2 H = new G2(); + H.deserialize(h); // H = Hash(m) + G1 pub = new G1(); + pub.deserialize(pubKey); + G1 Q = new G1(); + Q.setStr(Bls.BaseG1); + + G2 g2 = new G2(); + g2.deserialize(sig); + GT e1 = new GT(); + GT e2 = new GT(); + Mcl.pairing(e1, pub, H); // e1 = e(H, s Q) + Mcl.pairing(e2, Q, g2); // e2 = e(s H, Q); + return e1.equals(e2); + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java index 37993eee..3cd62950 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java @@ -6,14 +6,15 @@ public class ValidatorRegistrationBuilder extends AbstractTransactionBuilder { + public ValidatorRegistrationBuilder() { super(); this.transaction.fee = Fees.VALIDATOR_REGISTRATION.getValue(); } public ValidatorRegistrationBuilder publicKeyAsset(String publicKey) { + validateBlsPublicKey(publicKey); this.transaction.asset.validatorPublicKey = publicKey; - return this; } @@ -26,4 +27,69 @@ public Transaction getTransactionInstance() { public ValidatorRegistrationBuilder instance() { return this; } + + private void validateBlsPublicKey(String publicKeyHex) { + if (publicKeyHex.length() != 96) { + throw new IllegalArgumentException("Invalid BLS public key length"); + } + + // byte[] publicKeyBytes = Schnorr.hexStringToByteArray(publicKeyHex); + + // // Log para verificar longitud de bytes + // System.out.println("publicKeyBytes length: " + publicKeyBytes.length); + + // // Usar la función de la clase BLS para verificar si la clave pública es válida + // ECP2 publicKeyPoint = ECP2.fromBytes(publicKeyBytes); + + // // Descomprimir la clave pública comprimida + // BIG xBig = BIG.fromBytes(publicKeyBytes); + // ECP2 publicKeyPoint = new ECP2(xBig, 0); // El segundo argumento es un bit de paridad + + // // Verificar que el punto no esté en el infinito + // if (publicKeyPoint.is_infinity()) { + // throw new IllegalArgumentException("Invalid BLS public key: point at infinity"); + // } + + // // Verificar que el punto realmente pertenezca a la curva utilizando la ecuación de la + // curva + // FP2 rhs = ECP2.RHS(publicKeyPoint.getX()); // Right-hand side: y^2 = x^3 + Ax + B + // FP2 lhs = new FP2(publicKeyPoint.getY()); + // lhs.sqr(); // Left-hand side: y^2 + + // if (!lhs.equals(rhs)) { + // throw new IllegalArgumentException( + // "Invalid BLS public key: does not satisfy curve equation"); + // } + + // System.out.println("BLS public key is valid."); + + // Verificación usando PAIR.G2member + // boolean isValid = PAIR.G2member(publicKeyPoint); + // System.out.println("Is publicKeyPoint valid using PAIR.G2member: " + isValid); + + // // Alternativa: Usar BLS.core_verify para verificar la clave pública + // // La clave pública W y un mensaje arbitrario se pueden usar aquí + // byte[] dummyMessage = "test message".getBytes(); + // byte[] dummySignature = new byte[publicKeyBytes.length]; // Firma ficticia para validar + // la clave + + // // Realizar la verificación + // int result = BLS.core_verify(dummySignature, dummyMessage, publicKeyBytes); + + // if (result != BLS.BLS_OK) { + // throw new IllegalArgumentException("Invalid BLS public key according to + // core_verify"); + // } + + // System.out.println("Public key is valid according to BLS.core_verify"); + + // // Validar que el punto pertenece al grupo G2 + // boolean isValid = PAIR.G2member(publicKeyPoint); + // // Depuración: Resultado de la validación + // System.out.println("Is publicKeyPoint valid: " + isValid); + + // if (!isValid) { + // throw new IllegalArgumentException("Invalid BLS public key"); + // } + } } diff --git a/src/main/java/org/arkecosystem/crypto/utils/Schnorr.java b/src/main/java/org/arkecosystem/crypto/utils/Schnorr.java index 23d13508..d5d2330d 100644 --- a/src/main/java/org/arkecosystem/crypto/utils/Schnorr.java +++ b/src/main/java/org/arkecosystem/crypto/utils/Schnorr.java @@ -1,4 +1,4 @@ -package org.arkecosystem.crypto; +package org.arkecosystem.crypto.utils; public class Schnorr { diff --git a/src/test/java/org/arkecosystem/crypto/SchnorrTest.java b/src/test/java/org/arkecosystem/crypto/SchnorrTest.java index 008fe682..db6cb7b3 100644 --- a/src/test/java/org/arkecosystem/crypto/SchnorrTest.java +++ b/src/test/java/org/arkecosystem/crypto/SchnorrTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.utils.Schnorr; import org.junit.jupiter.api.Test; class SchnorrTest { diff --git a/src/test/java/org/arkecosystem/crypto/identities/bls/KeyPairFactoryTest.java b/src/test/java/org/arkecosystem/crypto/identities/bls/KeyPairFactoryTest.java new file mode 100644 index 00000000..b95f031d --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/identities/bls/KeyPairFactoryTest.java @@ -0,0 +1,25 @@ +package org.arkecosystem.crypto.identities.bls; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class KeyPairFactoryTest { + + private static final String PASSPHRASE = + "question measure debris increase false feature journey height fun agent coach office only shell nation skill track upset distance behave easy devote floor shy"; + private static final String EXPECTED_PRIVATE_KEY = + "3e99d30b3816f60077b1fdb4535ce0e9f9c715e42d1647edc3361fc531fb618f"; + private static final String EXPECTED_PUBLIC_KEY = + "b4865127896c3c5286296a7b26e7c8002586a3ecf5832bfb59e689336f1f4c75e10491b9dfaed8dfb2c2fbe22d11fa93"; + + @Test + public void fromPassphrase() { + KeyPairFactory factory = new KeyPairFactory(); + + KeyPairFactory.KeyPair keyPair = factory.fromPassphrase(PASSPHRASE); + + assertEquals(EXPECTED_PRIVATE_KEY, keyPair.getPrivateKey()); + assertEquals(EXPECTED_PUBLIC_KEY, keyPair.getPublicKey()); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java b/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java index 858c5c5f..a5a01ce4 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java @@ -2,9 +2,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.arkecosystem.crypto.Schnorr; import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PrivateKey; +import org.arkecosystem.crypto.utils.Schnorr; import org.bitcoinj.core.ECKey; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java b/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java index 7f09c61c..5e6678a6 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java @@ -2,8 +2,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; -import org.arkecosystem.crypto.Schnorr; import org.arkecosystem.crypto.identities.PrivateKey; +import org.arkecosystem.crypto.utils.Schnorr; import org.bitcoinj.core.ECKey; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java index 65ffa8f8..06fa98dd 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java @@ -8,25 +8,69 @@ import org.junit.jupiter.api.Test; class ValidatorRegistrationBuilderTest { + @Test void build() { - Transaction actual = - new ValidatorRegistrationBuilder() - .publicKeyAsset( - "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118") - .nonce(3) - .sign("this is a top secret passphrase") - .transaction; + List publicKeys = + List.of( + "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb" + // "b4865127896c3c5286296a7b26e7c8002586a3ecf5832bfb59e689336f1f4c75e10491b9dfaed8dfb2c2fbe22d11fa93" + // From python + // "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118" + ); - HashMap actualHashMap = actual.toHashMap(); + for (String publicKey : publicKeys) { + Transaction actual = + new ValidatorRegistrationBuilder() + .publicKeyAsset(publicKey) + .nonce(3) + .sign("this is a top secret passphrase") + .transaction; - HashMap asset = (HashMap) actualHashMap.get("asset"); + HashMap actualHashMap = actual.toHashMap(); + HashMap asset = (HashMap) actualHashMap.get("asset"); - assertEquals( - asset.get("validatorPublicKey"), - "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118"); + assertEquals(asset.get("validatorPublicKey"), publicKey); + assertTrue(actual.verify()); + } + } - assertTrue(actual.verify()); + @Test + void testValidatorRegistrationTransactionWithInvalidBlsPublicKey() { + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> { + new ValidatorRegistrationBuilder() + .publicKeyAsset( + "b5fea88b9aab3f0b122e5a7e1b07917e62a63ea59103d0a0715ecded3c41685af88f0a9606309b148b3b50f51a2edddd") + .nonce(3) + .sign("this is a top secret passphrase"); + }); + + String expectedMessage = "Invalid BLS public key"; + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + void testValidatorRegistrationTransactionWithInvalidBlsPublicKeyByLength() { + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> { + new ValidatorRegistrationBuilder() + .publicKeyAsset( + "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3") + .nonce(3) + .sign("this is a top secret passphrase"); + }); + + String expectedMessage = "Invalid BLS public key"; + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); } @Test diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java index c8a44ac3..be8c5753 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java @@ -53,10 +53,6 @@ void passphraseVendorField() { assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); assertEquals(data.get("signature").toString(), actual.signature); assertEquals(data.get("id").toString(), actual.id); - - System.out.println("AAAA"); - System.out.println(data.get("vendorField").toString()); - assertEquals(data.get("recipientId").toString(), actual.recipientId); assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); assertEquals(((Double) data.get("expiration")).intValue(), actual.expiration);