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..c609a2f2 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,6 @@ test { useJUnitPlatform() testLogging { events 'PASSED', 'FAILED', 'SKIPPED' - showStandardStreams = true } } diff --git a/libmcljava.dylib b/libmcljava.dylib new file mode 100644 index 00000000..355362e3 Binary files /dev/null and b/libmcljava.dylib 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/enums/CoreTransactionTypes.java b/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java index 5ee7d0de..a977cb48 100644 --- a/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java +++ b/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java @@ -6,12 +6,10 @@ public enum CoreTransactionTypes { VALIDATOR_REGISTRATION(2), VOTE(3), MULTI_SIGNATURE_REGISTRATION(4), - IPFS(5), MULTI_PAYMENT(6), VALIDATOR_RESIGNATION(7), - HTLC_LOCK(8), - HTLC_CLAIM(9), - HTLC_REFUND(10); + USERNAME_REGISTRATION(8), + USERNAME_RESIGNATION(9); private final int value; diff --git a/src/main/java/org/arkecosystem/crypto/enums/Fees.java b/src/main/java/org/arkecosystem/crypto/enums/Fees.java index e5e1321b..8a5cf991 100644 --- a/src/main/java/org/arkecosystem/crypto/enums/Fees.java +++ b/src/main/java/org/arkecosystem/crypto/enums/Fees.java @@ -6,12 +6,10 @@ public enum Fees { VALIDATOR_REGISTRATION(2_500_000_000L), VOTE(100_000_000L), MULTI_SIGNATURE_REGISTRATION(500_000_000L), - IPFS(500_000_000L), MULTI_PAYMENT(10_000_000L), VALIDATOR_RESIGNATION(2_500_000_000L), - HTLC_LOCK(10_000_000L), - HTLC_CLAIM(0L), - HTLC_REFUND(0L); + USERNAME_REGISTRATION(2_500_000_000L), + USERNAME_RESIGNATION(2_500_000_000L); private final Long value; 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..e550cf70 --- /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.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..8a37b471 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/bls/JNIEnv.java @@ -0,0 +1,82 @@ +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) { + 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/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index 32730ef9..66c45891 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -15,6 +15,8 @@ import org.arkecosystem.crypto.transactions.types.SecondSignatureRegistration; import org.arkecosystem.crypto.transactions.types.Transaction; import org.arkecosystem.crypto.transactions.types.Transfer; +import org.arkecosystem.crypto.transactions.types.UsernameRegistration; +import org.arkecosystem.crypto.transactions.types.UsernameResignation; import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; import org.arkecosystem.crypto.transactions.types.ValidatorResignation; import org.arkecosystem.crypto.transactions.types.Vote; @@ -42,6 +44,10 @@ public Deserializer(String serialized) { coreTransactionTypes.put(CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); coreTransactionTypes.put( CoreTransactionTypes.VALIDATOR_RESIGNATION.getValue(), new ValidatorResignation()); + coreTransactionTypes.put( + CoreTransactionTypes.USERNAME_RESIGNATION.getValue(), new UsernameResignation()); + coreTransactionTypes.put( + CoreTransactionTypes.USERNAME_REGISTRATION.getValue(), new UsernameRegistration()); transactionGroups.put(TransactionTypeGroup.CORE.getValue(), coreTransactionTypes); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java index b69e19bc..5d0fef1d 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java @@ -13,6 +13,7 @@ public class TransactionAsset { public HashMap customAsset = new HashMap<>(); public long amount = 0L; public String validatorPublicKey; + public String username; public static class Signature { public String publicKey; diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java new file mode 100644 index 00000000..19592102 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java @@ -0,0 +1,29 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.arkecosystem.crypto.transactions.types.UsernameRegistration; + +public class UsernameRegistrationBuilder + extends AbstractTransactionBuilder { + public UsernameRegistrationBuilder() { + super(); + this.transaction.fee = Fees.VALIDATOR_REGISTRATION.getValue(); + } + + public UsernameRegistrationBuilder usernameAsset(String username) { + this.transaction.asset.username = username; + + return this; + } + + @Override + public Transaction getTransactionInstance() { + return new UsernameRegistration(); + } + + @Override + public UsernameRegistrationBuilder instance() { + return this; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java new file mode 100644 index 00000000..7fee046d --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java @@ -0,0 +1,24 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.arkecosystem.crypto.transactions.types.UsernameResignation; + +public class UsernameResignationBuilder + extends AbstractTransactionBuilder { + + public UsernameResignationBuilder() { + super(); + this.transaction.fee = Fees.USERNAME_RESIGNATION.getValue(); + } + + @Override + public Transaction getTransactionInstance() { + return new UsernameResignation(); + } + + @Override + public UsernameResignationBuilder instance() { + return this; + } +} 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..b2b3c98c 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java @@ -1,19 +1,23 @@ package org.arkecosystem.crypto.transactions.builder; import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.signature.bls.Bls; +import org.arkecosystem.crypto.signature.bls.BlsConstants; import org.arkecosystem.crypto.transactions.types.Transaction; import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; public class ValidatorRegistrationBuilder extends AbstractTransactionBuilder { + public ValidatorRegistrationBuilder() { super(); this.transaction.fee = Fees.VALIDATOR_REGISTRATION.getValue(); } public ValidatorRegistrationBuilder publicKeyAsset(String publicKey) { - this.transaction.asset.validatorPublicKey = publicKey; + validateBlsPublicKey(publicKey); + this.transaction.asset.validatorPublicKey = publicKey; return this; } @@ -26,4 +30,14 @@ 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"); + } + + Bls bls = new Bls(BlsConstants.BLS12_381); + + bls.validateBlsPublicKey(publicKeyHex); + } } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java index 0530eca3..0e61dfe0 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java @@ -4,9 +4,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PrivateKey; import org.arkecosystem.crypto.signature.SchnorrSigner; @@ -93,7 +91,7 @@ public boolean verify() { byte[] signature = Hex.decode(this.signature); byte[] hash = Sha256Hash.hash(Serializer.serialize(this, true, true, false)); - return verifier(this.signature).verify(hash, keys, signature); + return verifier().verify(hash, keys, signature); } public boolean secondVerify(String secondPublicKey) { @@ -102,48 +100,7 @@ public boolean secondVerify(String secondPublicKey) { byte[] signature = Hex.decode(this.secondSignature); byte[] hash = Sha256Hash.hash(Serializer.serialize(this, false, true, false)); - return verifier(this.secondSignature).verify(hash, keys, signature); - } - - public boolean multiVerify(int min, List publicKeys) { - if (publicKeys.isEmpty()) { - throw new RuntimeException("The multi signature asset is invalid."); - } - - byte[] hash = Sha256Hash.hash(Serializer.serialize(this, true, true, true)); - - Set publicKeyIndexes = new HashSet<>(); - int verifiedSignatures = 0; - boolean verified = false; - for (int i = 0; i < this.signatures.size(); i++) { - String signature = this.signatures.get(i); - int publicKeyIndex = Integer.parseInt(signature.substring(0, 2), 16); - - if (!publicKeyIndexes.contains(publicKeyIndex)) { - publicKeyIndexes.add(publicKeyIndex); - } else { - throw new RuntimeException("Duplicate participant in multi signature"); - } - - String partialSignature = signature.substring(2); - String publicKey = publicKeys.get(publicKeyIndex); - - if (verifier(partialSignature) - .verify( - hash, - ECKey.fromPublicOnly(Hex.decode(publicKey)), - Hex.decode(partialSignature))) { - verifiedSignatures++; - } - - if (verifiedSignatures == min) { - verified = true; - break; - } else if (signatures.size() - (i + 1 - verifiedSignatures) < min) { - break; - } - } - return verified; + return verifier().verify(hash, keys, signature); } public String toJson() { @@ -206,7 +163,7 @@ private Signer signer() { return new SchnorrSigner(); } - private Verifier verifier(String signature) { + private Verifier verifier() { return new SchnorrVerifier(); } } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java new file mode 100644 index 00000000..f4bbe80d --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java @@ -0,0 +1,53 @@ +package org.arkecosystem.crypto.transactions.types; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.HashMap; +import org.arkecosystem.crypto.enums.CoreTransactionTypes; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; + +public class UsernameRegistration extends Transaction { + @Override + public int getTransactionType() { + return CoreTransactionTypes.USERNAME_REGISTRATION.getValue(); + } + + @Override + public int getTransactionTypeGroup() { + return TransactionTypeGroup.CORE.getValue(); + } + + @Override + public HashMap assetToHashMap() { + HashMap asset = new HashMap<>(); + + asset.put("username", this.asset.username); + + return asset; + } + + @Override + public byte[] serialize() { + byte[] username = this.asset.username.getBytes(); + + ByteBuffer buffer = ByteBuffer.allocate(username.length + 1); + + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.put((byte) username.length); + buffer.put(username); + + return buffer.array(); + } + + @Override + public void deserialize(ByteBuffer buffer) { + int usernameLength = buffer.get() & 0xff; + + byte[] username = new byte[usernameLength]; + buffer.get(username); + + String utf8Username = new String(username); + this.asset.username = utf8Username; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java new file mode 100644 index 00000000..8f1b70b2 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java @@ -0,0 +1,31 @@ +package org.arkecosystem.crypto.transactions.types; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import org.arkecosystem.crypto.enums.CoreTransactionTypes; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; + +public class UsernameResignation extends Transaction { + @Override + public int getTransactionType() { + return CoreTransactionTypes.USERNAME_RESIGNATION.getValue(); + } + + @Override + public int getTransactionTypeGroup() { + return TransactionTypeGroup.CORE.getValue(); + } + + @Override + public HashMap assetToHashMap() { + return null; + } + + @Override + public byte[] serialize() { + return new byte[0]; + } + + @Override + public void deserialize(ByteBuffer buffer) {} +} diff --git a/src/main/java/org/arkecosystem/crypto/Schnorr.java b/src/main/java/org/arkecosystem/crypto/utils/Schnorr.java similarity index 100% rename from src/main/java/org/arkecosystem/crypto/Schnorr.java rename to src/main/java/org/arkecosystem/crypto/utils/Schnorr.java diff --git a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java index 73294eda..c338e6ec 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java @@ -1,60 +1,31 @@ package org.arkecosystem.crypto.signature; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.gson.internal.LinkedTreeMap; -import java.util.Arrays; -import java.util.List; -import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PublicKey; import org.arkecosystem.crypto.transactions.Deserializer; import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; public class FixtureSignVerificationTest { - private final String passphrase = "my super secret passphrase"; private final String secondPassphrase = "this is a top secret second passphrase"; - private final String musigPassphrase1 = - "album pony urban cheap small blade cannon silent run reveal luxury glad predict excess fire beauty hollow reward solar egg exclude leaf sight degree"; - private final String musigPassphrase2 = - "hen slogan retire boss upset blame rocket slender area arch broom bring elder few milk bounce execute page evoke once inmate pear marine deliver"; - private final String musigPassphrase3 = - "top visa use bacon sun infant shrimp eye bridge fantasy chair sadness stable simple salad canoe raw hill target connect avoid promote spider category"; @ParameterizedTest @ValueSource( strings = { "transactions/transfer/transfer-sign", - "transactions/transfer/transfer-with-vendor-field-sign", - // "transactions/transfer/transfer-multi-sign", - "transactions/vote/vote-sign", "transactions/vote/unvote-sign", - // "transactions/vote/vote-multi-sign", - "transactions/validator_registration/validator-registration-sign", - // "transactions/validator_registration/validator-registration-multi-sign", - "transactions/validator_resignation/validator-resignation-sign", - // "transactions/validator_resignation/validator-resignation-multi-sign", - "transactions/multi_payment/multi-payment-sign", "transactions/multi_payment/multi-payment-with-vendor-field-sign", - // "transactions/multi_payment/multi-payment-multi-sign", - - // "transactions/username_resignation/username-resignation-sign", - // "transactions/username_resignation/username-resignation-multi-sign", - - // "transactions/username_registration/username-registration-multi-sign", - // "transactions/username_registration/username-registration-sign", - + "transactions/username_resignation/username-resignation-sign", + "transactions/username_registration/username-registration-sign", "transactions/multi_signature_registration/multi-signature-registration-sign", }) void checkSchnorrSignature(String file) { @@ -67,117 +38,10 @@ void checkSchnorrSignature(String file) { if (actual.secondSignature != null) { checkSecondSignature(actual); } - - if (actual.signatures != null) { - checkMultiSignature(actual); - } - } - - @ParameterizedTest - @ValueSource( - strings = { - "transactions/transfer/transfer-sign", - "transactions/transfer/transfer-with-vendor-field-sign", - // "transactions/transfer/transfer-multi-sign", - - "transactions/vote/vote-sign", - "transactions/vote/unvote-sign", - // "transactions/vote/vote-multi-sign", - - "transactions/validator_registration/validator-registration-sign", - // "transactions/validator_registration/validator-registration-multi-sign", - - "transactions/validator_resignation/validator-resignation-sign", - // "transactions/validator_resignation/validator-resignation-multi-sign", - - "transactions/multi_payment/multi-payment-sign", - "transactions/multi_payment/multi-payment-with-vendor-field-sign", - // "transactions/multi_payment/multi-payment-multi-sign", - - // "transactions/username_resignation/username-resignation-sign", - // "transactions/username_resignation/username-resignation-multi-sign", - - // "transactions/username_registration/username-registration-multi-sign", - // "transactions/username_registration/username-registration-sign", - - // "transactions/multi_signature_registration/multi-signature-registration-sign", - }) - void checkSigningAgainProducesSameSignature(String file) { - LinkedTreeMap fixture = FixtureLoader.load(file); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - // Remove the signatures from original transaction - Transaction withoutSignatures = - new Deserializer(Hex.encode(Serializer.serialize(actual, true, true, true))) - .deserialize(); - - // Ensure only the signatures were removed - assertThat( - fixture.get("serialized").toString(), - startsWith(Hex.encode(Serializer.serialize(withoutSignatures)))); - - reSignUnsigned(actual, withoutSignatures); - - if (withoutSignatures.signature != null) { - assertTrue(withoutSignatures.verify()); - } - - if (withoutSignatures.secondSignature != null) { - checkSecondSignature(withoutSignatures); - } - - int signatureLength = 128; - - if (withoutSignatures.signatures != null) { - checkMultiSignature(withoutSignatures); - - signatureLength = 128 + (withoutSignatures.signatures.size() * 130); - } - - String serializedWithoutSignatures = Hex.encode(Serializer.serialize(withoutSignatures)); - String serializedFixture = fixture.get("serialized").toString(); - - // Exclude the last 128 characters (signature) for final comparison - assertThat( - serializedWithoutSignatures.substring( - 0, serializedWithoutSignatures.length() - signatureLength), - is(serializedFixture.substring(0, serializedFixture.length() - signatureLength))); - } - - private void reSignUnsigned(Transaction actual, Transaction withoutSignatures) { - if (actual.signatures != null) { - int i = 0; - for (String passphrase : - Arrays.asList(musigPassphrase1, musigPassphrase2, musigPassphrase3)) { - withoutSignatures.multiSign(passphrase, i++); - } - if (actual.signature != null) { - withoutSignatures.sign(musigPassphrase1); - } - if (actual.secondSignature != null) { - withoutSignatures.secondSign(secondPassphrase); - } - } else if (actual.secondSignature != null) { - withoutSignatures.sign(passphrase); - withoutSignatures.secondSign(secondPassphrase); - } else if (actual.signature != null) { - withoutSignatures.sign(passphrase); - } } private void checkSecondSignature(Transaction actual) { String secondPublicKey = PublicKey.fromPassphrase(secondPassphrase); assertTrue(actual.secondVerify(secondPublicKey)); } - - private void checkMultiSignature(Transaction actual) { - String key1 = PublicKey.fromPassphrase(musigPassphrase1); - String key2 = PublicKey.fromPassphrase(musigPassphrase2); - String key3 = PublicKey.fromPassphrase(musigPassphrase3); - - List publicKeys = Arrays.asList(key1, key2, key3); - - assertTrue(actual.multiVerify(2, publicKeys)); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java index 4427b45e..ab66bd60 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -59,4 +60,29 @@ void testMaxPayments() { () -> actual.addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1)); assertEquals("Expected a maximum of 64 payments", exception.getMessage()); } + + @Test + void buildMultiSignature() { + Transaction actual = + new MultiPaymentBuilder() + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 2) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 3) + .vendorField("This is a transaction from Java") + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java index 894ab34c..3751034f 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java @@ -3,14 +3,11 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import org.arkecosystem.crypto.enums.Fees; import org.arkecosystem.crypto.identities.PublicKey; -import org.arkecosystem.crypto.transactions.Deserializer; import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class MultiSignatureRegistrationBuilderTest { @@ -38,7 +35,6 @@ void build() { .transaction; assertTrue(actual.verify()); - assertTrue(actual.multiVerify(3, publicKeys)); HashMap actualHashMap = actual.toHashMap(); @@ -54,32 +50,4 @@ void build() { assertEquals(publicKeys, actualPublicKeys); assertEquals(3, actualMin); } - - @Test - void checkMultiSignaturePassingInvalidMultiSignatureAsset() { - Exception thrown = - Assertions.assertThrows( - RuntimeException.class, - () -> { - Deserializer deserializer = - new Deserializer( - "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632"); - Transaction actual = deserializer.deserialize(); - assertTrue(actual.multiVerify(3, Collections.emptyList())); - }); - assertEquals("The multi signature asset is invalid.", thrown.getMessage()); - } - - @Test - void checkMultiSignaturePassingInvalidMultiSignatureAssets() { - String key1 = PublicKey.fromPassphrase("this is a top secret passphrase 1"); - String key2 = PublicKey.fromPassphrase("this is a top secret passphrase 2"); - String key3 = PublicKey.fromPassphrase("this is a top secret passphrase 3"); - - Deserializer deserializer = - new Deserializer( - "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632"); - Transaction actual = deserializer.deserialize(); - assertFalse(actual.multiVerify(3, Arrays.asList(key1, key2, key3))); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java index 22634cd2..00e061af 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java @@ -1,9 +1,11 @@ package org.arkecosystem.crypto.transactions.builder; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.enums.Fees; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -62,4 +64,31 @@ void buildSecondSignature() { HashMap actualHashMap = actual.toHashMap(); assertEquals(actualHashMap.get("secondSignature"), actual.secondSignature); } + + @Test + void buildMultiSignature() { + Transaction actual = + new TransferBuilder() + .recipient("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") + .amount(133380000000L) + .expiration(100000) + .vendorField("This is a transaction from Java") + .nonce(3) + .fee(Fees.TRANSFER.getValue()) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("secret 1") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java new file mode 100644 index 00000000..d373b3f5 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java @@ -0,0 +1,51 @@ +package org.arkecosystem.crypto.transactions.builder; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import java.util.List; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameRegistrationBuilderTest { + @Test + void build() { + Transaction actual = + new UsernameRegistrationBuilder() + .usernameAsset("alfonsobries") + .nonce(3) + .sign("this is a top secret passphrase") + .transaction; + + HashMap actualHashMap = actual.toHashMap(); + + HashMap asset = (HashMap) actualHashMap.get("asset"); + + assertEquals(asset.get("username"), "alfonsobries"); + + assertTrue(actual.verify()); + } + + @Test + void buildMultiSignature() { + Transaction actual = + new UsernameRegistrationBuilder() + .usernameAsset("alfonsobries") + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java new file mode 100644 index 00000000..e96e39ed --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java @@ -0,0 +1,62 @@ +package org.arkecosystem.crypto.transactions.builder; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import java.util.List; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +public class UsernameResignationBuilderTest { + @Test + void build() { + Transaction actual = + new UsernameResignationBuilder() + .nonce(3) + .sign("this is a top secret passphrase") + .transaction; + + HashMap actualHashMap = actual.toHashMap(); + HashMap actualAsset = (HashMap) actualHashMap.get("asset"); + assertNull(actualAsset); + + assertTrue(actual.verify()); + } + + @Test + void buildSecondSignature() { + Transaction actual = + new UsernameResignationBuilder() + .nonce(3) + .sign("this is a top secret passphrase") + .secondSign("this is a top secret second passphrase") + .transaction; + + assertTrue(actual.verify()); + assertTrue( + actual.secondVerify( + "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); + } + + @Test + void buildMultiSignature() { + Transaction actual = + new UsernameResignationBuilder() + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } +} 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 1a28a767..63fb3e89 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -27,4 +28,66 @@ void build() { 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 + void buildMultiSignature() { + Transaction actual = + new ValidatorRegistrationBuilder() + .publicKeyAsset( + "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118") + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java index b42b367f..960a93fa 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -36,4 +37,26 @@ void buildSecondSignature() { actual.secondVerify( "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); } + + @Test + void buildMultiSignature() { + Transaction actual = + new ValidatorResignationBuilder() + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java index 971773df..8aca1456 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java @@ -1,6 +1,7 @@ package org.arkecosystem.crypto.transactions.builder; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; @@ -128,4 +129,29 @@ void buildVoteSecondSignature() { actual.secondVerify( "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); } + + @Test + void buildMultiSignature() { + Transaction actual = + new VoteBuilder() + .addVote( + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192") + .version(2) + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } 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); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java new file mode 100644 index 00000000..0853ed71 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java @@ -0,0 +1,37 @@ +package org.arkecosystem.crypto.transactions.deserializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +public class UsernameRegistrationTest { + + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load("transactions/username_registration/username-registration-sign"); + + LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); + + Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); + + assertEquals(((Double) data.get("version")).intValue(), actual.version); + assertEquals(((Double) data.get("network")).intValue(), actual.network); + assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); + assertEquals(((Double) data.get("type")).intValue(), actual.type); + assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); + assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); + assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); + assertEquals(data.get("signature").toString(), actual.signature); + assertEquals(data.get("id").toString(), actual.id); + + LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); + + assertEquals((asset.get("username")), actual.asset.username); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java new file mode 100644 index 00000000..6dfa1ff7 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java @@ -0,0 +1,36 @@ +package org.arkecosystem.crypto.transactions.deserializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameResignationTest { + + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load("transactions/username_resignation/username-resignation-sign"); + + LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); + + Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); + + assertEquals(((Double) data.get("version")).intValue(), actual.version); + assertEquals(((Double) data.get("network")).intValue(), actual.network); + assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); + assertEquals(((Double) data.get("type")).intValue(), actual.type); + assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); + assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); + assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); + assertEquals(data.get("signature").toString(), actual.signature); + assertEquals(data.get("id").toString(), actual.id); + + assertNull(data.get("asset")); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java new file mode 100644 index 00000000..c07191d6 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java @@ -0,0 +1,25 @@ +package org.arkecosystem.crypto.transactions.serializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.Serializer; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameRegistrationTest { + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load("transactions/username_registration/username-registration-sign"); + Transaction transaction = + new Deserializer(fixture.get("serialized").toString()).deserialize(); + + String actual = Hex.encode(Serializer.serialize(transaction)); + + assertEquals(fixture.get("serialized").toString(), actual); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java new file mode 100644 index 00000000..ec77bef7 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java @@ -0,0 +1,26 @@ +package org.arkecosystem.crypto.transactions.serializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.Serializer; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameResignationTest { + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load("transactions/username_resignation/username-resignation-sign"); + + Transaction transaction = + new Deserializer(fixture.get("serialized").toString()).deserialize(); + + String actual = Hex.encode(Serializer.serialize(transaction)); + + assertEquals(fixture.get("serialized").toString(), actual); + } +}