diff --git a/autobahn/build.gradle b/autobahn/build.gradle index f84ace65..729bd8c8 100644 --- a/autobahn/build.gradle +++ b/autobahn/build.gradle @@ -24,13 +24,17 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.1' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.16.1' implementation 'org.msgpack:jackson-dataformat-msgpack:0.9.8' - implementation 'org.web3j:core:5.0.0' - implementation 'org.web3j:abi:5.0.0' - implementation 'org.web3j:utils:5.0.0' + implementation('io.xconn:cryptology:1.0.1') { + exclude group: "org.bouncycastle", module: "bcprov-jdk18on" + } if (IS_ANDROID) { - implementation 'com.github.joshjdevl.libsodiumjni:libsodium-jni-aar:2.0.2' - } else { - implementation 'com.github.joshjdevl.libsodiumjni:libsodium-jni:2.0.2' + implementation 'org.web3j:core:4.8.8-android' + implementation 'org.web3j:abi:4.8.8-android' + implementation 'org.web3j:utils:4.8.8-android' + } else{ + implementation 'org.web3j:core:4.11.0' + implementation 'org.web3j:abi:4.11.0' + implementation 'org.web3j:utils:4.11.0' implementation 'org.json:json:20240205' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.5' } @@ -38,6 +42,7 @@ dependencies { implementation 'io.netty:netty-codec-http:4.1.106.Final' implementation 'io.netty:netty-handler:4.1.106.Final' } + testImplementation 'junit:junit:4.13.2' } // Create the pom configuration: @@ -174,8 +179,8 @@ if (IS_ANDROID) { jar { version = relVersion } - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } afterEvaluate { @@ -187,7 +192,7 @@ afterEvaluate { artifactId ARTIFACT_ANDROID } else { from components.java - artifactId IS_NEXT ? ARTIFACT_NEXT: ARTIFACT_JAVA + artifactId IS_NEXT ? ARTIFACT_NEXT : ARTIFACT_JAVA } artifact sourcesJar diff --git a/autobahn/src/main/java/io/crossbar/autobahn/wamp/auth/CryptosignAuth.java b/autobahn/src/main/java/io/crossbar/autobahn/wamp/auth/CryptosignAuth.java index 9b471cac..48f87001 100644 --- a/autobahn/src/main/java/io/crossbar/autobahn/wamp/auth/CryptosignAuth.java +++ b/autobahn/src/main/java/io/crossbar/autobahn/wamp/auth/CryptosignAuth.java @@ -1,14 +1,15 @@ package io.crossbar.autobahn.wamp.auth; -import org.libsodium.jni.crypto.Random; -import org.libsodium.jni.keys.SigningKey; -import org.libsodium.jni.keys.VerifyKey; - import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; +import org.bouncycastle.util.encoders.Hex; + +import io.xconn.cryptology.CryptoSign; +import io.xconn.cryptology.KeyPair; + import io.crossbar.autobahn.utils.AuthUtil; import io.crossbar.autobahn.utils.Pair; import io.crossbar.autobahn.wamp.Session; @@ -16,7 +17,6 @@ import io.crossbar.autobahn.wamp.types.Challenge; import io.crossbar.autobahn.wamp.types.ChallengeResponse; -import static org.libsodium.jni.SodiumConstants.SECRETKEY_BYTES; public class CryptosignAuth implements IAuthenticator { public static final String authmethod = "cryptosign"; @@ -28,13 +28,12 @@ public class CryptosignAuth implements IAuthenticator { private final byte[] privateKeyRaw; public static Pair generateSigningKeyPair() { - VerifyKey key = new VerifyKey(new Random().randomBytes(SECRETKEY_BYTES)); - SigningKey signingKey = new SigningKey(key.toBytes()); + KeyPair keyPair = CryptoSign.generateKeyPair(); - String privateKey = AuthUtil.toHexString(key.toBytes()); - String publicKey = AuthUtil.toHexString(signingKey.getVerifyKey().toBytes()); + String publicKeyHex = Hex.toHexString(keyPair.getPublicKey()); + String privateKeyHex = Hex.toHexString(keyPair.getPrivateKey()); - return new Pair<>(publicKey, privateKey); + return new Pair<>(publicKeyHex, privateKeyHex); } public CryptosignAuth(String authid, String privateKey) { @@ -42,8 +41,8 @@ public CryptosignAuth(String authid, String privateKey) { } public static String getPublicKey(byte[] privateKeyRaw) { - SigningKey signingKey = new SigningKey(privateKeyRaw); - return AuthUtil.toHexString(signingKey.getVerifyKey().toBytes()); + byte[] publicKeyBytes = CryptoSign.getPublicKey(privateKeyRaw); + return AuthUtil.toHexString(publicKeyBytes); } public CryptosignAuth(String authid, String privkey, Map authextra) { @@ -68,8 +67,7 @@ public CryptosignAuth(String authid, File privateKeyFile) { } } - public CryptosignAuth(String authid, String authrole, String privkey, - Map authextra) { + public CryptosignAuth(String authid, String authrole, String privkey, Map authextra) { this.authid = authid; this.authrole = authrole; this.authextra = authextra; @@ -85,8 +83,7 @@ public CompletableFuture onChallenge(Session session, Challen String hexChallenge = (String) challenge.extra.get("challenge"); byte[] rawChallenge = AuthUtil.toBinary(hexChallenge); - SigningKey key = new SigningKey(privateKeyRaw); - byte[] signed = key.sign(rawChallenge); + byte[] signed = CryptoSign.sign(privateKeyRaw, rawChallenge); String signatureHex = AuthUtil.toHexString(signed); String res = signatureHex + hexChallenge; diff --git a/autobahn/src/main/java/xbr/network/KeySeries.java b/autobahn/src/main/java/xbr/network/KeySeries.java index d48d0cc1..1df16ef3 100644 --- a/autobahn/src/main/java/xbr/network/KeySeries.java +++ b/autobahn/src/main/java/xbr/network/KeySeries.java @@ -11,14 +11,6 @@ package xbr.network; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.cbor.CBORFactory; - -import org.libsodium.jni.SodiumConstants; -import org.libsodium.jni.crypto.Random; -import org.web3j.utils.Numeric; - import java.math.BigInteger; import java.util.HashMap; import java.util.Map; @@ -26,6 +18,14 @@ import java.util.TimerTask; import java.util.function.Consumer; +import static io.xconn.cryptology.Util.generateRandomBytesArray; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; + +import org.web3j.utils.Numeric; + import xbr.network.crypto.SealedBox; import xbr.network.crypto.SecretBox; @@ -94,8 +94,7 @@ byte[] getPrice() { } Map encrypt(Object payload) throws JsonProcessingException { - byte[] nonce = new Random().randomBytes( - SodiumConstants.XSALSA20_POLY1305_SECRETBOX_NONCEBYTES); + byte[] nonce = generateRandomBytesArray(Util.NONCE_SIZE); Map data = new HashMap<>(); data.put("id", mID); @@ -112,8 +111,8 @@ byte[] encryptKey(byte[] keyID, byte[] buyerPubKey) { } private void onRotate() { - mID = new Random().randomBytes(16); - mKey = new Random().randomBytes(SodiumConstants.XSALSA20_POLY1305_SECRETBOX_KEYBYTES); + mID = generateRandomBytesArray(16); + mKey = generateRandomBytesArray(Util.SECRET_KEY_LEN); mBox = new SecretBox(mKey); Map data = new HashMap<>(); diff --git a/autobahn/src/main/java/xbr/network/SimpleBuyer.java b/autobahn/src/main/java/xbr/network/SimpleBuyer.java index 4b22695e..8ed30353 100644 --- a/autobahn/src/main/java/xbr/network/SimpleBuyer.java +++ b/autobahn/src/main/java/xbr/network/SimpleBuyer.java @@ -15,7 +15,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.cbor.CBORFactory; -import org.libsodium.jni.SodiumConstants; import org.web3j.crypto.Credentials; import org.web3j.crypto.ECKeyPair; import org.web3j.utils.Numeric; @@ -27,6 +26,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; +import io.xconn.cryptology.KeyPair; + import io.crossbar.autobahn.utils.ABLogger; import io.crossbar.autobahn.utils.IABLogger; import io.crossbar.autobahn.wamp.Session; @@ -36,8 +37,6 @@ import xbr.network.pojo.Quote; import xbr.network.pojo.Receipt; -import static org.libsodium.jni.NaCl.sodium; - public class SimpleBuyer { private static final IABLogger LOGGER = ABLogger.getLogger(SimpleBuyer.class.getName()); @@ -69,9 +68,9 @@ public SimpleBuyer(String marketMakerAddr, String buyerKey, BigInteger maxPrice) mEthPublicKey = mECKey.getPublicKey().toByteArray(); mEthAddr = Numeric.hexStringToByteArray(Credentials.create(mECKey).getAddress()); - mPrivateKey = new byte[SodiumConstants.SECRETKEY_BYTES]; - mPublicKey = new byte[SodiumConstants.PUBLICKEY_BYTES]; - sodium().crypto_box_keypair(mPublicKey, mPrivateKey); + KeyPair pubPriKeyPair = io.xconn.cryptology.SealedBox.generateKeyPair(); + mPublicKey = pubPriKeyPair.getPublicKey(); + mPrivateKey = pubPriKeyPair.getPrivateKey(); mMaxPrice = maxPrice; mKeys = new HashMap<>(); diff --git a/autobahn/src/main/java/xbr/network/SimpleSeller.java b/autobahn/src/main/java/xbr/network/SimpleSeller.java index 2bac117a..3f3b5471 100644 --- a/autobahn/src/main/java/xbr/network/SimpleSeller.java +++ b/autobahn/src/main/java/xbr/network/SimpleSeller.java @@ -11,10 +11,11 @@ package xbr.network; +import static io.xconn.cryptology.Util.generateRandomBytesArray; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; -import org.libsodium.jni.crypto.Random; import org.web3j.crypto.ECKeyPair; import org.web3j.crypto.Keys; import org.web3j.utils.Numeric; @@ -93,7 +94,7 @@ public byte[] getPublicKey() { private void onRotate(KeySeries series) { mKeysMap.put(Numeric.toHexString(series.getID()), series); long validFrom = Math.round(System.nanoTime() - 10 * Math.pow(10, 9)); - byte[] signature = new Random().randomBytes(65); + byte[] signature = generateRandomBytesArray(65); List args = new ArrayList<>(); args.add(series.getID()); diff --git a/autobahn/src/main/java/xbr/network/Util.java b/autobahn/src/main/java/xbr/network/Util.java index b99f98fb..956becd2 100644 --- a/autobahn/src/main/java/xbr/network/Util.java +++ b/autobahn/src/main/java/xbr/network/Util.java @@ -27,6 +27,9 @@ public class Util { + public static final int NONCE_SIZE = 24; + public static final int SECRET_KEY_LEN = 32; + public static BigInteger toXBR(int xbr) { return BigInteger.valueOf(xbr).multiply(BigInteger.valueOf(10).pow(18)); } diff --git a/autobahn/src/main/java/xbr/network/crypto/SealedBox.java b/autobahn/src/main/java/xbr/network/crypto/SealedBox.java index 18728663..1969dcfd 100644 --- a/autobahn/src/main/java/xbr/network/crypto/SealedBox.java +++ b/autobahn/src/main/java/xbr/network/crypto/SealedBox.java @@ -1,16 +1,15 @@ package xbr.network.crypto; -import org.libsodium.jni.encoders.Encoder; - -import static org.libsodium.jni.NaCl.sodium; -import static org.libsodium.jni.SodiumConstants.PUBLICKEY_BYTES; -import static org.libsodium.jni.crypto.Util.isValid; +import static io.xconn.cryptology.SealedBox.seal; +import static io.xconn.cryptology.SealedBox.sealOpen; public class SealedBox { private static final int MAC_BYTES = 16; + private static int PUBLICKEY_BYTES = 32; private static final int SEAL_BYTES = PUBLICKEY_BYTES + MAC_BYTES; + private static final byte[] HSALSA20_SEED = new byte[16]; private byte[] publicKey; private byte[] privateKey; @@ -22,9 +21,6 @@ public SealedBox(byte[] publicKey) { this.privateKey = null; } - public SealedBox(String publicKey, Encoder encoder) { - this(encoder.decode(publicKey)); - } public SealedBox(byte[] publicKey, byte[] privateKey) { if (publicKey == null) { @@ -37,23 +33,11 @@ public SealedBox(byte[] publicKey, byte[] privateKey) { this.privateKey = privateKey; } - public SealedBox(String publicKey, String privateKey, Encoder encoder) { - this(encoder.decode(publicKey), encoder.decode(privateKey)); - } - public byte[] encrypt(byte[] message) { - byte[] ct = new byte[message.length + SEAL_BYTES]; - isValid(sodium().crypto_box_seal( - ct, message, message.length, publicKey), - "Encryption failed"); - return ct; + return seal(message, publicKey); } - public byte[] decrypt(byte[] ciphertext) { - byte[] message = new byte[ciphertext.length - SEAL_BYTES]; - isValid(sodium().crypto_box_seal_open( - message, ciphertext, ciphertext.length, publicKey, privateKey), - "Decryption failed. Ciphertext failed verification"); - return message; + public byte[] decrypt(byte[] message) { + return sealOpen(message, privateKey); } } diff --git a/autobahn/src/main/java/xbr/network/crypto/SecretBox.java b/autobahn/src/main/java/xbr/network/crypto/SecretBox.java index acdb3045..74f4688b 100644 --- a/autobahn/src/main/java/xbr/network/crypto/SecretBox.java +++ b/autobahn/src/main/java/xbr/network/crypto/SecretBox.java @@ -1,65 +1,39 @@ package xbr.network.crypto; -import org.libsodium.jni.crypto.Random; -import org.libsodium.jni.crypto.Util; -import org.libsodium.jni.encoders.Encoder; - import java.util.Arrays; -import static org.libsodium.jni.NaCl.sodium; -import static org.libsodium.jni.SodiumConstants.BOXZERO_BYTES; -import static org.libsodium.jni.SodiumConstants.XSALSA20_POLY1305_SECRETBOX_KEYBYTES; -import static org.libsodium.jni.SodiumConstants.XSALSA20_POLY1305_SECRETBOX_NONCEBYTES; -import static org.libsodium.jni.SodiumConstants.ZERO_BYTES; -import static org.libsodium.jni.crypto.Util.checkLength; -import static org.libsodium.jni.crypto.Util.isValid; -import static org.libsodium.jni.crypto.Util.removeZeros; +import static io.xconn.cryptology.SecretBox.box; +import static io.xconn.cryptology.SecretBox.boxOpen; +import static io.xconn.cryptology.Util.checkLength; +import static io.xconn.cryptology.Util.generateRandomBytesArray; +import static xbr.network.Util.NONCE_SIZE; +import static xbr.network.Util.SECRET_KEY_LEN; public class SecretBox { - - private byte[] mKey; - private Encoder mEncoder; + private final byte[] mKey; public SecretBox(byte[] key) { - checkLength(key, XSALSA20_POLY1305_SECRETBOX_KEYBYTES); - mEncoder = Encoder.RAW; - mKey = key; + checkLength(key, SECRET_KEY_LEN); + mKey = Arrays.copyOf(key, key.length); } public byte[] encrypt(byte[] message) { - byte[] nonce = new Random().randomBytes(XSALSA20_POLY1305_SECRETBOX_NONCEBYTES); + byte[] nonce = generateRandomBytesArray(NONCE_SIZE); return encrypt(nonce, message); } - public byte[] encrypt(byte[] nonce, byte[] message) { - checkLength(nonce, XSALSA20_POLY1305_SECRETBOX_NONCEBYTES); - byte[] msg = org.libsodium.jni.crypto.Util.prependZeros(ZERO_BYTES, message); - byte[] ct = org.libsodium.jni.crypto.Util.zeros(msg.length); - isValid(sodium().crypto_secretbox_xsalsa20poly1305(ct, msg, msg.length, - nonce, mKey), "Encryption failed"); - byte[] cipherWithoutNonce = removeZeros(BOXZERO_BYTES, ct); - byte[] ciphertext = new byte[cipherWithoutNonce.length + - XSALSA20_POLY1305_SECRETBOX_NONCEBYTES]; + public byte[] encrypt(byte[] nonce, byte[] plaintext) { + byte[] cipherWithoutNonce = box(nonce, plaintext, mKey); + byte[] ciphertext = new byte[cipherWithoutNonce.length + NONCE_SIZE]; System.arraycopy(nonce, 0, ciphertext, 0, nonce.length); - System.arraycopy(cipherWithoutNonce, 0, ciphertext, nonce.length, - cipherWithoutNonce.length); + System.arraycopy(cipherWithoutNonce, 0, ciphertext, nonce.length, cipherWithoutNonce.length); return ciphertext; } public byte[] decrypt(byte[] ciphertext) { - byte[] nonce = Arrays.copyOfRange(ciphertext, 0, XSALSA20_POLY1305_SECRETBOX_NONCEBYTES); - byte[] message = Arrays.copyOfRange(ciphertext, XSALSA20_POLY1305_SECRETBOX_NONCEBYTES, - ciphertext.length); - return decrypt(nonce, message); - } - - public byte[] decrypt(byte[] nonce, byte[] ciphertext) { - checkLength(nonce, XSALSA20_POLY1305_SECRETBOX_NONCEBYTES); - byte[] ct = org.libsodium.jni.crypto.Util.prependZeros(BOXZERO_BYTES, ciphertext); - byte[] message = Util.zeros(ct.length); - isValid(sodium().crypto_secretbox_xsalsa20poly1305_open(message, ct, - ct.length, nonce, mKey), "Decryption failed. Ciphertext failed verification"); - return removeZeros(ZERO_BYTES, message); + byte[] nonce = Arrays.copyOfRange(ciphertext, 0, NONCE_SIZE); + byte[] message = Arrays.copyOfRange(ciphertext, NONCE_SIZE, ciphertext.length); + return boxOpen(nonce, message, mKey); } } diff --git a/autobahn/src/test/java/io/crossbar/autobahn/wamp/auth/CryptosignAuthTests.java b/autobahn/src/test/java/io/crossbar/autobahn/wamp/auth/CryptosignAuthTests.java new file mode 100644 index 00000000..e047d397 --- /dev/null +++ b/autobahn/src/test/java/io/crossbar/autobahn/wamp/auth/CryptosignAuthTests.java @@ -0,0 +1,112 @@ +package io.crossbar.autobahn.wamp.auth; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import io.crossbar.autobahn.utils.AuthUtil; +import io.crossbar.autobahn.utils.Pair; +import io.crossbar.autobahn.wamp.types.Challenge; +import io.crossbar.autobahn.wamp.types.ChallengeResponse; + +public class CryptosignAuthTests { + + private static final String TestAuthID = "testAuthId"; + private static final String TestPrivateKey = "61b297d1573d0a2a6ac58d7fd39369adbd365c5b3276bd69edf661c92b7ad9ff"; + private static final String TestPublicKey = "ea971c008ee99021eaf48342791442dd742259a4bf14004fa3500d1fa6995211"; + + @Test + public void testGenerateSigningKeyPair() { + Pair keyPair = CryptosignAuth.generateSigningKeyPair(); + assertNotNull(keyPair.first); + assertNotNull(keyPair.second); + assertEquals(64, keyPair.first.length()); + assertEquals(64, keyPair.second.length()); + } + + @Test + public void testGetPublicKey() { + byte[] privateKeyRaw = AuthUtil.toBinary(TestPrivateKey); + String publicKeyHex = CryptosignAuth.getPublicKey(privateKeyRaw); + assertNotNull(publicKeyHex); + assertEquals(TestPublicKey, publicKeyHex); + } + + @Test + public void testConstructorWithPrivateKey() { + CryptosignAuth auth = new CryptosignAuth(TestAuthID, TestPrivateKey); + assertNotNull(auth); + assertEquals(TestAuthID, auth.authid); + } + + @Test + public void testConstructorWithPrivateKeyAndPubKey() { + CryptosignAuth auth = new CryptosignAuth(TestAuthID, TestPrivateKey, TestPublicKey); + assertNotNull(auth); + assertEquals(TestAuthID, auth.authid); + } + + @Test + public void testConstructorWithPrivateKeyFile() throws IOException { + File privateKeyFile = createPrivateKeyFile(); + CryptosignAuth auth = new CryptosignAuth(TestAuthID, privateKeyFile); + assertNotNull(auth); + assertEquals(TestAuthID, auth.authid); + } + + private File createPrivateKeyFile() throws IOException { + String privateKey = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + + "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAgwAAAAtzc2gtZW\n" + + "QyNTUxOQAAACCxFVfOJU6fDhJmG1Hh8qW2nEdqeDbXLkCOoeepu5VxcAAACBAMP3yQT9Mk\n" + + "/YAAAAAtzc2gtZWQyNTUxOQAAACCxFVfOJU6fDhJmG1Hh8qW2nEdqeDbXLkCOoeepu5Vxc\n" + + "AAAEA6Ay3awSTmEnMS7QZi4ofEiChSju2bN8wFFS4tmFrG3sVV84lTp8OEmYbUeHypbacR\n" + + "2p4NtcuQI6h56m7lXFwAAAECf4qghufu/GJScYXWHjVPfX+znr0NQ1p2YVNTZi7mC0rLQ6\n" + + "qSsWfNYu4mSvA1Q6Jv6Xu8HAB/TIllo5bqV9acxSbA5GEE0S8T6rMq0BtZk+jHxUlFMjrr\n" + + "QwEW18H/mFjtsitG8K5XWfBgMb3dF8XsoGYJyKlY4e4p0D7BBjqSKnB7wlUGwkCdTeeUDw==\n" + + "-----END OPENSSH PRIVATE KEY-----\n"; + byte[] privateKeyBytes = privateKey.getBytes(StandardCharsets.UTF_8); + Path tempFilePath = Files.createTempFile("private_key", ".txt"); + Files.write(tempFilePath, privateKeyBytes); + return tempFilePath.toFile(); + } + + @Test + public void testConstructorWithAuthIdPrivateKeyAuthExtra() { + Map authextra = new HashMap<>(); + authextra.put("pubkey", TestPublicKey); + CryptosignAuth auth = new CryptosignAuth(TestAuthID, TestPrivateKey, authextra); + assertNotNull(auth); + assertEquals(TestAuthID, auth.authid); + assertEquals(authextra, auth.authextra); + } + + @Test + public void testOnChallenge() { + String challengeString = "f9d17535fb925e9f674d648cbfc41399"; + String signedString = "539707667d93bb9eb01e72be9ca5e00006bb6b1b786d697b3f189ebf5a0f60c70" + + "b8054f3735e19b77df31dc990864fb21259cfe3021f9a7e8ec0427c2077840a"; + Challenge challenge = new Challenge("cryptosign", new HashMap() {{ + put("challenge", challengeString); + }}); + + CryptosignAuth auth = new CryptosignAuth(TestAuthID, TestPrivateKey); + ChallengeResponse response = auth.onChallenge(null, challenge).join(); + assertNotNull(response.signature); + assertEquals(signedString + challengeString, response.signature); + } + + @Test + public void testGetAuthMethod() { + CryptosignAuth auth = new CryptosignAuth(TestAuthID, TestPrivateKey); + assertEquals("cryptosign", auth.getAuthMethod()); + } +} diff --git a/autobahn/src/test/java/xbr/network/crypto/SealedBoxTest.java b/autobahn/src/test/java/xbr/network/crypto/SealedBoxTest.java new file mode 100644 index 00000000..97d5c632 --- /dev/null +++ b/autobahn/src/test/java/xbr/network/crypto/SealedBoxTest.java @@ -0,0 +1,43 @@ +package xbr.network.crypto; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertThrows; + +import org.bouncycastle.util.encoders.Hex; +import org.junit.Before; +import org.junit.Test; + +public class SealedBoxTest { + + private static byte[] publicKey; + private static byte[] privateKey; + + @Before + public void setUp() { + publicKey = Hex.decode("e146721761cf7378cb2e007adc1a51b70fa40abfb87652c645d8e86be19c2b1e"); + privateKey = Hex.decode("3817e2630237d569188a02a06354d9e9f61ee9cdd0cc8b5388c56013b7b5654a"); + } + @Test + public void testEncryptDecrypt() { + SealedBox sealedBox = new SealedBox(publicKey, privateKey); + + String message = "Hello, world!"; + byte[] encrypted = sealedBox.encrypt(message.getBytes()); + byte[] decrypted = sealedBox.decrypt(encrypted); + + assertArrayEquals(message.getBytes(), decrypted); + } + + @Test + public void testNullPublicKey() { + assertThrows(IllegalArgumentException.class, () -> new SealedBox(null)); + } + + @Test + public void testNullPrivateKey() { + byte[] publicKey = Hex.decode("1eb32ea638c250f7b781b7a0d29d0c1b3456d7a3428ff9c7a4a64d75db709709"); + + assertThrows(IllegalArgumentException.class, () -> new SealedBox(publicKey, null)); + } + +} diff --git a/autobahn/src/test/java/xbr/network/crypto/SecretBoxTest.java b/autobahn/src/test/java/xbr/network/crypto/SecretBoxTest.java new file mode 100644 index 00000000..3927dac5 --- /dev/null +++ b/autobahn/src/test/java/xbr/network/crypto/SecretBoxTest.java @@ -0,0 +1,72 @@ +package xbr.network.crypto; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertThrows; +import static io.xconn.cryptology.Util.generateRandomBytesArray; + +import static xbr.network.Util.NONCE_SIZE; + +import org.junit.Test; + +public class SecretBoxTest { + + @Test + public void testConstructor() { + // test with valid key + new SecretBox(new byte[32]); + + // test with invalid key + assertThrows(IllegalArgumentException.class, () -> new SecretBox(new byte[16])); + + // test with null key + assertThrows(NullPointerException.class, () -> new SecretBox(null)); + } + + @Test + public void testEncryptAndDecrypt() { + SecretBox secretBox = new SecretBox(new byte[32]); + byte[] message = "Hello, World!".getBytes(); + byte[] encrypted = secretBox.encrypt(message); + byte[] decrypted = secretBox.decrypt(encrypted); + assertArrayEquals(message, decrypted); + } + + @Test + public void testEncryptAndDecryptWithNonce() { + SecretBox secretBox = new SecretBox(new byte[32]); + byte[] nonce = generateRandomBytesArray(NONCE_SIZE); + byte[] message = "Hello, World!".getBytes(); + byte[] encrypted = secretBox.encrypt(nonce, message); + byte[] decrypted = secretBox.decrypt(encrypted); + assertArrayEquals(message, decrypted); + } + + @Test + public void testEncryptAndDecryptWithInvalidMAC() { + SecretBox secretBox = new SecretBox(new byte[32]); + byte[] message = "Hello, World!".getBytes(); + byte[] encrypted = secretBox.encrypt(message); + encrypted[encrypted.length - 1] ^= 0xFF; // Modify last byte + assertThrows(IllegalArgumentException.class, () -> secretBox.decrypt(encrypted)); + } + + @Test + public void testEncryptAndDecryptWithInvalidNonce() { + SecretBox secretBox = new SecretBox(new byte[32]); + byte[] message = "Hello, World!".getBytes(); + byte[] encrypted = secretBox.encrypt(message); + encrypted[0] ^= 0xFF; // Modify first byte + assertThrows(IllegalArgumentException.class, () -> secretBox.decrypt(encrypted)); + } + + @Test + public void testEncryptAndDecryptWithModifiedCiphertext() { + byte[] key = new byte[32]; + SecretBox secretBox = new SecretBox(key); + byte[] message = "Hello, World!".getBytes(); + byte[] encrypted = secretBox.encrypt(message); + encrypted[NONCE_SIZE + 1] ^= 0xFF; // Modify the byte next to nonce + assertThrows(IllegalArgumentException.class, () -> secretBox.decrypt(encrypted)); + } + +} diff --git a/build.gradle b/build.gradle index cd36d419..f64b0493 100644 --- a/build.gradle +++ b/build.gradle @@ -38,5 +38,6 @@ allprojects { google() mavenCentral() maven { url "https://dl.bintray.com/ethereum/maven/" } + maven { url "https://artifacts.consensys.net/public/maven/maven/" } } } diff --git a/demo-gallery/build.gradle b/demo-gallery/build.gradle index c4ea851b..ac4d47f5 100644 --- a/demo-gallery/build.gradle +++ b/demo-gallery/build.gradle @@ -47,7 +47,7 @@ if (plugins.hasPlugin(project.PLUGIN_ANDROID_APP)) { implementation "com.google.android.material:material:1.11.0" implementation 'com.basgeekball:awesome-validation:4.2' - implementation 'org.web3j:crypto:5.0.0' + implementation 'org.web3j:crypto:4.8.8-android' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' } } else if (project.IS_NEXT) { @@ -79,4 +79,7 @@ if (plugins.hasPlugin(project.PLUGIN_ANDROID_APP)) { jar { version = project.properties.get("buildVersion", "") } + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 }