MultiBit HDTHE TECHNICAL RECOVERY LIBRARYmail@keychainx.io ↗

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.

By KeychainX · 20 September 2026 · Source revision 24a12b199a01

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.

Sources at the reviewed revision