|
1 | 1 | package org.arkecosystem.crypto.identities; |
2 | 2 |
|
3 | | -import com.google.common.primitives.Bytes; |
4 | | -import org.arkecosystem.crypto.configuration.Network; |
5 | | -import org.arkecosystem.crypto.encoding.Base58; |
6 | 3 | import org.arkecosystem.crypto.encoding.Hex; |
7 | 4 | import org.bitcoinj.core.ECKey; |
8 | | -import org.bouncycastle.crypto.digests.RIPEMD160Digest; |
| 5 | +import org.web3j.crypto.Hash; |
| 6 | +import org.web3j.crypto.Keys; |
9 | 7 |
|
10 | 8 | public class Address { |
11 | | - public static String fromPassphrase(String passphrase, Integer networkVersion) { |
12 | | - return fromPrivateKey(PrivateKey.fromPassphrase(passphrase), networkVersion); |
13 | | - } |
14 | | - |
15 | 9 | public static String fromPassphrase(String passphrase) { |
16 | | - return Address.fromPassphrase(passphrase, null); |
| 10 | + ECKey privateKey = PrivateKey.fromPassphrase(passphrase); |
| 11 | + return fromPrivateKey(privateKey); |
17 | 12 | } |
18 | 13 |
|
19 | | - public static String fromPublicKey(String publicKey, Integer networkVersion) { |
| 14 | + public static String fromPublicKey(String publicKey) { |
20 | 15 | byte[] publicKeyBytes = Hex.decode(publicKey); |
21 | 16 |
|
22 | | - RIPEMD160Digest digest = new RIPEMD160Digest(); |
23 | | - digest.update(publicKeyBytes, 0, publicKeyBytes.length); |
24 | | - byte[] out = new byte[20]; |
25 | | - digest.doFinal(out, 0); |
| 17 | + // Ensure the public key is uncompressed |
| 18 | + ECKey ecKey = ECKey.fromPublicOnly(publicKeyBytes); |
| 19 | + byte[] uncompressedPublicKeyBytes = ecKey.getPubKeyPoint().getEncoded(false); |
26 | 20 |
|
27 | | - if (networkVersion == null) { |
28 | | - networkVersion = Network.get().version(); |
29 | | - } |
| 21 | + // Remove the prefix (0x04) |
| 22 | + byte[] rawPublicKey = new byte[uncompressedPublicKeyBytes.length - 1]; |
| 23 | + System.arraycopy(uncompressedPublicKeyBytes, 1, rawPublicKey, 0, rawPublicKey.length); |
30 | 24 |
|
31 | | - byte[] bytes = Bytes.concat(new byte[] {networkVersion.byteValue()}, out); |
32 | | - return Base58.encodeChecked(bytes); |
33 | | - } |
| 25 | + // Hash the public key using Keccak-256 |
| 26 | + byte[] keccakHash = Hash.sha3(rawPublicKey); |
34 | 27 |
|
35 | | - public static String fromPublicKey(String publicKey) { |
36 | | - return Address.fromPublicKey(publicKey, null); |
37 | | - } |
| 28 | + // Take the last 20 bytes of the Keccak-256 hash |
| 29 | + byte[] addressBytes = new byte[20]; |
38 | 30 |
|
39 | | - public static String fromPrivateKey(ECKey privateKey, Integer networkVersion) { |
40 | | - return fromPublicKey(privateKey.getPublicKeyAsHex(), networkVersion); |
41 | | - } |
| 31 | + System.arraycopy(keccakHash, keccakHash.length - 20, addressBytes, 0, 20); |
42 | 32 |
|
43 | | - public static String fromPrivateKey(ECKey privateKey) { |
44 | | - return Address.fromPrivateKey(privateKey, null); |
45 | | - } |
| 33 | + // Convert to checksum address |
| 34 | + String address = "0x" + Hex.encode(addressBytes); |
46 | 35 |
|
47 | | - public static Boolean validate(String address, Integer networkVersion) { |
48 | | - if (networkVersion == null) { |
49 | | - networkVersion = Network.get().version(); |
50 | | - } |
| 36 | + return Keys.toChecksumAddress(address); |
| 37 | + } |
51 | 38 |
|
52 | | - return Base58.decodeChecked(address)[0] == networkVersion; |
| 39 | + public static String fromPrivateKey(ECKey privateKey) { |
| 40 | + byte[] publicKeyBytes = privateKey.getPubKey(); |
| 41 | + return fromPublicKey(Hex.encode(publicKeyBytes)); |
53 | 42 | } |
54 | 43 |
|
55 | 44 | public static Boolean validate(String address) { |
56 | | - return Address.validate(address, null); |
| 45 | + if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) { |
| 46 | + return false; |
| 47 | + } |
| 48 | + return address.equals(Keys.toChecksumAddress(address)); |
57 | 49 | } |
58 | 50 | } |
0 commit comments