MultiBit HD / Technical library
INDEPENDENT KEYCHAINX RESOURCE
WalletId: identifiers and directory names
Builds and formats wallet identifiers and parses them from wallet paths. The formatted identifier is distinct from a Bitcoin address. The constructors distinguish seed-derived inputs and salts; do not treat the visible directory name as a reversible encoding of recovery words.
Source inspection only. Historical Java code; not executed or security-audited for this publication.
mbhd-core/src/main/java/org/multibit/hd/core/dto/WalletId.java
View the exact upstream file · Read raw source · License notices
SHA-256: 1c2ef08a66c5fb1a4a1d59feb3982bbbdb4c9095e09fbabd85d6a2ea7799583c
1package org.multibit.hd.core.dto;23import org.bitcoinj.core.Utils;4import com.google.common.base.Preconditions;5import org.multibit.commons.crypto.AESUtils;6import org.multibit.hd.core.managers.WalletManager;78import java.io.File;9import java.util.Arrays;1011/**12 * <p>Data object to provide the following to wallet seed related classes:</p>13 * <ul>14 * <li>Creation of wallet id from seed</li>15 * <li>Creation of wallet directory name from wallet id</li>16 * <li>Round-tripping of the above</li>17 * </ul>18 *19 * @since 0.0.120 */21public class WalletId {2223 public static final int SEPARATOR_REPEAT_PERIOD = 4;24 public static final String WALLET_ID_SEPARATOR = "-";2526 /**27 * The salt used in converting seed bytes to a wallet id for MBHD wallets28 */29 private static final byte[] WALLET_ID_SALT_USED_IN_SCRYPT_FOR_MBHD_WALLETS = new byte[]{(byte) 1};3031 /**32 * The salt used in converting seed bytes to a wallet id for Trezor wallets33 */34 private static final byte[] WALLET_ID_SALT_USED_IN_SCRYPT_FOR_TREZOR_SOFT_WALLETS = new byte[]{(byte) 2};3536 private static final int NUMBER_OF_BYTES_IN_WALLET_ID = 20;37 public static final int LENGTH_OF_FORMATTED_WALLET_ID = 2 * NUMBER_OF_BYTES_IN_WALLET_ID + (NUMBER_OF_BYTES_IN_WALLET_ID / SEPARATOR_REPEAT_PERIOD) - 1;3839 private final byte[] walletId;4041 /**42 * @return A copy of the wallet ID salt used in Scrypt for MBHD wallets43 */44 public static byte[] getWalletIdSaltUsedInScryptForMbhdWallets() {45 return Arrays.copyOf(WALLET_ID_SALT_USED_IN_SCRYPT_FOR_MBHD_WALLETS, WALLET_ID_SALT_USED_IN_SCRYPT_FOR_MBHD_WALLETS.length);46 }4748 /**49 * @return A copy of the wallet ID salt used in Scrypt for Trezor soft wallets50 */51 public static byte[] getWalletIdSaltUsedInScryptForTrezorSoftWallets() {52 return Arrays.copyOf(WALLET_ID_SALT_USED_IN_SCRYPT_FOR_TREZOR_SOFT_WALLETS, WALLET_ID_SALT_USED_IN_SCRYPT_FOR_TREZOR_SOFT_WALLETS.length);53 }5455 /**56 * Create a wallet id from a formatted wallet id57 *58 * @param formattedWalletId The formatted wallet id you want to use (e.g. "66666666-77777777-88888888-99999999-aaaaaaaa")59 */60 public WalletId(String formattedWalletId) {6162 Preconditions.checkState(formattedWalletId.length() == LENGTH_OF_FORMATTED_WALLET_ID);6364 // remove any embedded hyphens65 formattedWalletId = formattedWalletId.replaceAll("-", "");6667 walletId = Utils.parseAsHexOrBase58(formattedWalletId);68 }6970 /**71 * Create an MBHD wallet id from the given seed.72 * This produces a wallet id from the seed using various trapdoor functions.73 * The seed is typically generated from the SeedPhraseGenerator#convertToSeed method.74 *75 * @param seed The seed to use in deriving the wallet id76 */77 public WalletId(byte[] seed) {78 walletId = AESUtils.generate160BitsOfEntropy(seed, WALLET_ID_SALT_USED_IN_SCRYPT_FOR_MBHD_WALLETS);79 }808182 /**83 * Create an wallet id from the given seed and salt84 *85 * You can use this to generate a wallet id for a Trezor soft wallet passing in WALLET_ID_SALT_USED_IN_SCRYPT_FOR_TREZOR_SOFT_WALLETS86 * This produces a wallet id from the seed using various trapdoor functions.87 * The seed is typically generated from the SeedPhraseGenerator#convertToSeed method.88 *89 * @param seed The seed to use in deriving the wallet id90 */91 public WalletId(byte[] seed, byte[] salt) {92 walletId = AESUtils.generate160BitsOfEntropy(seed, salt);93 }9495 /**96 * Create a WalletId from a wallet filename - the filename is parsed into a walletId byte array97 * The wallet filename should be the whole file name e.g /herp/derp/mbhd-23bb865e-161bfefc-3020c418-66bf6f75-7fecdfcc/mbhd.wallet98 *99 * @return The wallet ID100 */101 public static WalletId parseWalletFilename(String walletFilename) {102103 File walletFile = new File(walletFilename);104105 // Get the parent directory, in which the wallet id is embedded106 File walletRoot = walletFile.getParentFile();107 String walletRootName = walletRoot.getName();108109 // Remove the prefix mbhd110 String prefix = WalletManager.WALLET_DIRECTORY_PREFIX + WALLET_ID_SEPARATOR;111 if (walletRootName.startsWith(prefix)) {112 walletRootName = walletRootName.replace(prefix, "");113114 return new WalletId(walletRootName);115116 } else {117 throw new IllegalStateException("Cannot parse '" + walletFilename + "' into a WalletId. Does not start with '" + prefix + "'");118 }119 }120121 /**122 * @return The raw wallet id as a byte[]123 */124 public byte[] getBytes() {125 return Arrays.copyOf(walletId, walletId.length);126 }127128 /**129 * @return The wallet id as a formatted string (e.g. "66666666-77777777-88888888-99999999-aaaaaaaa")130 */131 public String toFormattedString() {132133 StringBuilder buffer = new StringBuilder();134135 for (int i = 0; i < walletId.length; i++) {136 buffer.append(Utils.HEX.encode(new byte[]{walletId[i]}));137138 if (((i + 1) % SEPARATOR_REPEAT_PERIOD == 0) && !(i == walletId.length - 1)) {139 buffer.append(WALLET_ID_SEPARATOR);140 }141 }142 return buffer.toString();143 }144145 @Override146 public String toString() {147 return toFormattedString();148 }149150151 @Override152 public boolean equals(Object o) {153 if (this == o) return true;154 if (o == null || getClass() != o.getClass()) return false;155156 WalletId that = (WalletId) o;157158 return Arrays.equals(this.walletId, that.walletId);159160 }161162 @Override163 public int hashCode() {164 return Arrays.hashCode(walletId);165 }166167}Read in context
Builds and formats wallet identifiers and parses them from wallet paths. The formatted identifier is distinct from a Bitcoin address. The constructors distinguish seed-derived inputs and salts; do not treat the visible directory name as a reversible encoding of recovery words.
Compare the callers, dependency versions and corresponding tests. The pinned file is one part of a larger application. Do not execute write, prune or migration routines against your only copy of a wallet.