Java 以太坊 ETH离线创建地址

有遇到疑惑的可加QQ群交流:1057160243

以太坊地址生成过程如下

  1. 生成 256 位随机数作为私钥。
  2. 将私钥转化为 secp256k1 非压缩格式的公钥,即 512 位的公钥。
  3. 使用散列算法 Keccak256 计算公钥的哈希值,转化为十六进制字符串。
  4. 取十六进制字符串的后 40 个字母,开头加上 0x 作为地址。

直接上代码,代码里面有详细解释

    /**
     * 通用的以太坊基于bip44协议的助记词路径 (imtoken jaxx Metamask myetherwallet)
     */
    private static String ETH_TYPE = "m/44'/60'/0'/0/0";

public Object createAddress(String password, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (password.length() < 12) {
            return ResponseBuilder.custom().success("error", 500).data("password长度最少12位数").build();
        }
        // 生成助记词
        EthHDWallet generateMnemonic = generateMnemonic(ETH_TYPE, password);
        // 钱包地址
        String address = generateMnemonic.Address;
        // keystore
        String keystore = generateMnemonic.keystore;
        // 私要
        String privateKey = generateMnemonic.privateKey;
        // 公钥
        String publicKey = generateMnemonic.publicKey;
        // 助记词
        List<String> mnemonic = generateMnemonic.mnemonic;
        // 助记词字符串
        String memorizing = Arrays.toString(mnemonic.toArray());
        // 助记词路径
        String mnemonicPath = generateMnemonic.mnemonicPath;
        // 根私钥
        String seedBytes = generateMnemonic.seedBytes;
        // 助记词种子
        String mnemonicSeedBytes = generateMnemonic.mnemonicSeedBytes;

        Map<String,Object> map = new HashMap<>();
        map.put("address",address.toString());
        map.put("keystore", keystore);
        map.put("memorizing",memorizing);
        map.put("mnemonicPath",mnemonicPath);
        map.put("mnemonicSeedBytes",mnemonicSeedBytes);
        map.put("privateKey",privateKey);
        map.put("publicKey",publicKey);
        map.put("seedBytes",seedBytes);
        return ResponseBuilder.custom().success("success", 0).data(map).build();
    }
public static EthHDWallet generateMnemonic(String path, String password) {
        if (!path.startsWith("m") && !path.startsWith("M")) {
            //            //参数非法
            return null;
        }
        String[] pathArray = path.split("/");
        if (pathArray.length <= 1) {
            //内容不对
            return null;
        }

        if (password.length() < 8) {
            //密码过短
            return null;
        }

        String passphrase = "";
        long creationTimeSeconds = System.currentTimeMillis() / 1000;
        DeterministicSeed ds = new DeterministicSeed(secureRandom, 128, passphrase);
        return createEthWallet(ds, pathArray, password);
    }
private static EthHDWallet createEthWallet(DeterministicSeed ds, String[] pathArray, String password) {
        //根私钥
        byte[] seedBytes = ds.getSeedBytes();
        String seedBytesa = Arrays.toString(seedBytes);

        //助记词
        List<String> mnemonic = ds.getMnemonicCode();
        String mnemonicSeedBytesa = null;
        try {
            //助记词种子
            byte[] mnemonicSeedBytes = MnemonicCode.INSTANCE.toEntropy(mnemonic);
            mnemonicSeedBytesa = Arrays.toString(mnemonicSeedBytes);
            ECKeyPair mnemonicKeyPair = ECKeyPair.create(mnemonicSeedBytes);
            WalletFile walletFile = Wallet.createLight(password, mnemonicKeyPair);
            ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
            //存这个keystore 用完后删除
            String jsonStr = objectMapper.writeValueAsString(walletFile);
            //验证
            WalletFile checkWalletFile = objectMapper.readValue(jsonStr, WalletFile.class);
            ECKeyPair ecKeyPair = Wallet.decrypt(password, checkWalletFile);
            byte[] checkMnemonicSeedBytes = Numeric.hexStringToByteArray(ecKeyPair.getPrivateKey().toString(16));
            List<String> checkMnemonic = MnemonicCode.INSTANCE.toMnemonic(checkMnemonicSeedBytes);

        } catch (MnemonicException.MnemonicLengthException | MnemonicException.MnemonicWordException | MnemonicException.MnemonicChecksumException | CipherException | IOException e) {
            e.printStackTrace();
        }

        if (seedBytes == null) {
            return null;
        }

        DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
        for (int i = 1; i < pathArray.length; i++) {
            ChildNumber childNumber;
            if (pathArray[i].endsWith("'")) {
                int number = Integer.parseInt(pathArray[i].substring(0,
                        pathArray[i].length() - 1));
                childNumber = new ChildNumber(number, true);
            } else {
                int number = Integer.parseInt(pathArray[i]);
                childNumber = new ChildNumber(number, false);
            }
            dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
        }

        ECKeyPair keyPair = ECKeyPair.create(dkKey.getPrivKeyBytes());

        EthHDWallet ethHDWallet = null;
        try {
            WalletFile walletFile = Wallet.createLight(password, keyPair);
            ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
            //存
            String keystore = objectMapper.writeValueAsString(walletFile);

            ethHDWallet = new EthHDWallet(keyPair.getPrivateKey().toString(16),
                    keyPair.getPublicKey().toString(16),
                    mnemonic, dkKey.getPathAsString(),
                    "0x" + walletFile.getAddress(), keystore, seedBytesa, mnemonicSeedBytesa);
        } catch (CipherException | JsonProcessingException e) {
            e.printStackTrace();
        }

        return ethHDWallet;
    }
public static class EthHDWallet {
        String privateKey;
        String publicKey;
        List<String> mnemonic;
        String mnemonicPath;
        String Address;
        String keystore;
        String seedBytes;
        String mnemonicSeedBytes;

        public EthHDWallet(String privateKey, String publicKey, List<String> mnemonic, String mnemonicPath, String address, String keystore, String seedBytes, String mnemonicSeedBytes) {
            this.privateKey = privateKey;
            this.publicKey = publicKey;
            this.mnemonic = mnemonic;
            this.mnemonicPath = mnemonicPath;
            this.Address = address;
            this.keystore = keystore;
            this.seedBytes = seedBytes;
            this.mnemonicSeedBytes = mnemonicSeedBytes;
        }
    }

依赖包

<dependency>
            <groupId>org.web3j</groupId>
            <artifactId>core</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.bitcoinj</groupId>
            <artifactId>bitcoinj-core</artifactId>
            <version>0.14.6</version>
            <scope>compile</scope>
        </dependency>

相关知识:

BIP32

定义 Hierarchical Deterministic wallet (简称 “HD Wallet”中文为分层确定性钱包),是一个系统可以从单一个 seed 产生一树状结构储存多组 keypairs(私钥和公钥)。好处是可以方便的备份、转移到其他相容装置(因为都只需要 seed),以及分层的权限控制等。

BIP39

将 seed 用方便记忆和书写的单字表示。业界一般使用 12 、15、18、21个单字组成的单词,,中文称为助记词或助记码。

BIP44

基于 BIP32 的系统,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。

可以通过特定的路径解析不同币种钱包,

btc一般是 m/44'/0'/0'/0eth一般是 m/44'/60'/0'/0

有遇到疑惑的可加QQ群交流:1057160243

猜你喜欢

转载自blog.csdn.net/u010138906/article/details/115245366