Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ repositories {
}

dependencies {
implementation 'org.web3j:core:4.8.7'
implementation 'org.bitcoinj:bitcoinj-core:0.16.3'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.google.guava:guava:30.2.0-jre'
Expand Down
62 changes: 27 additions & 35 deletions src/main/java/org/arkecosystem/crypto/identities/Address.java
Original file line number Diff line number Diff line change
@@ -1,58 +1,50 @@
package org.arkecosystem.crypto.identities;

import com.google.common.primitives.Bytes;
import org.arkecosystem.crypto.configuration.Network;
import org.arkecosystem.crypto.encoding.Base58;
import org.arkecosystem.crypto.encoding.Hex;
import org.bitcoinj.core.ECKey;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.web3j.crypto.Hash;
import org.web3j.crypto.Keys;

public class Address {
public static String fromPassphrase(String passphrase, Integer networkVersion) {
return fromPrivateKey(PrivateKey.fromPassphrase(passphrase), networkVersion);
}

public static String fromPassphrase(String passphrase) {
return Address.fromPassphrase(passphrase, null);
ECKey privateKey = PrivateKey.fromPassphrase(passphrase);
return fromPrivateKey(privateKey);
}

public static String fromPublicKey(String publicKey, Integer networkVersion) {
public static String fromPublicKey(String publicKey) {
byte[] publicKeyBytes = Hex.decode(publicKey);

RIPEMD160Digest digest = new RIPEMD160Digest();
digest.update(publicKeyBytes, 0, publicKeyBytes.length);
byte[] out = new byte[20];
digest.doFinal(out, 0);
// Ensure the public key is uncompressed
ECKey ecKey = ECKey.fromPublicOnly(publicKeyBytes);
byte[] uncompressedPublicKeyBytes = ecKey.getPubKeyPoint().getEncoded(false);

if (networkVersion == null) {
networkVersion = Network.get().version();
}
// Remove the prefix (0x04)
byte[] rawPublicKey = new byte[uncompressedPublicKeyBytes.length - 1];
System.arraycopy(uncompressedPublicKeyBytes, 1, rawPublicKey, 0, rawPublicKey.length);

byte[] bytes = Bytes.concat(new byte[] {networkVersion.byteValue()}, out);
return Base58.encodeChecked(bytes);
}
// Hash the public key using Keccak-256
byte[] keccakHash = Hash.sha3(rawPublicKey);

public static String fromPublicKey(String publicKey) {
return Address.fromPublicKey(publicKey, null);
}
// Take the last 20 bytes of the Keccak-256 hash
byte[] addressBytes = new byte[20];

public static String fromPrivateKey(ECKey privateKey, Integer networkVersion) {
return fromPublicKey(privateKey.getPublicKeyAsHex(), networkVersion);
}
System.arraycopy(keccakHash, keccakHash.length - 20, addressBytes, 0, 20);

public static String fromPrivateKey(ECKey privateKey) {
return Address.fromPrivateKey(privateKey, null);
}
// Convert to checksum address
String address = "0x" + Hex.encode(addressBytes);

public static Boolean validate(String address, Integer networkVersion) {
if (networkVersion == null) {
networkVersion = Network.get().version();
}
return Keys.toChecksumAddress(address);
}

return Base58.decodeChecked(address)[0] == networkVersion;
public static String fromPrivateKey(ECKey privateKey) {
byte[] publicKeyBytes = privateKey.getPubKey();
return fromPublicKey(Hex.encode(publicKeyBytes));
}

public static Boolean validate(String address) {
return Address.validate(address, null);
if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) {
return false;
}
return address.equals(Keys.toChecksumAddress(address));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public VoteBuilder addVote(String vote) {
}

public VoteBuilder sign(String passphrase) {
this.transaction.recipientId = Address.fromPassphrase(passphrase, this.transaction.network);
this.transaction.recipientId = Address.fromPassphrase(passphrase);

super.sign(passphrase);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,34 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.arkecosystem.crypto.configuration.Network;
import org.arkecosystem.crypto.networks.Devnet;
import org.bitcoinj.core.ECKey;
import org.junit.jupiter.api.Test;

public class AddressTest {

@Test
public void fromPassphrase() {
Network.set(new Devnet());
String actual = Address.fromPassphrase("this is a top secret passphrase");
assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual);
assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual);
}

@Test
public void fromPublicKey() {
String actual =
Address.fromPublicKey(
"034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192");
assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual);
assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual);
}

@Test
public void fromPrivateKey() {
ECKey privateKey = PrivateKey.fromPassphrase("this is a top secret passphrase");
String actual = Address.fromPrivateKey(privateKey);
assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual);
assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual);
}

@Test
public void validate() {
Network.set(new Devnet());
assertTrue(Address.validate("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib"));
assertTrue(Address.validate("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01"));
}
}
2 changes: 1 addition & 1 deletion src/test/resources/identity.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"data": {
"privateKey": "d8839c2432bfd0a67ef10a804ba991eabba19f154a3d707917681d45822a5712",
"publicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
"address": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"address": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"wif": "SGq4xLgZKCGxs7bjmwnBrWcT4C1ADFEermj846KC97FSv1WFD1dA"
},
"passphrase": "this is a top secret passphrase"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 0,
"amount": 200000000,
"fee": 10000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"timestamp": 41443847,
"asset": {},
"vendorFieldHex": "48656c6c6f20576f726c64",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 0,
"amount": 200000000,
"fee": 10000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"timestamp": 41443847,
"asset": {},
"vendorField": "Hello World",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 0,
"amount": 200000000,
"fee": 10000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"timestamp": 41268326,
"asset": {},
"senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 0,
"amount": 200000000,
"fee": 10000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"timestamp": 41443865,
"asset": {},
"vendorFieldHex": "48656c6c6f20576f726c64",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 0,
"amount": 200000000,
"fee": 10000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"timestamp": 41443865,
"asset": {},
"vendorField": "Hello World",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 0,
"amount": 200000000,
"fee": 10000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"timestamp": 41268430,
"asset": {},
"senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
Expand Down
2 changes: 1 addition & 1 deletion src/test/resources/transactions/V1/vote/passphrase.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 3,
"amount": 0,
"fee": 100000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
"timestamp": 41269349,
"asset": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": 3,
"amount": 0,
"fee": 100000000,
"recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib",
"recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01",
"senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
"timestamp": 41269366,
"asset": {
Expand Down