可以查看github源代码:https://github.com/wangjinggithub/wallet
原博文:https://blog.csdn.net/u012846783/article/details/82775643
个人使用处理:
-
导入包:
implementation ‘org.web3j:core:3.3.1-android’
implementation ‘org.bitcoinj:bitcoinj-core:0.14.7’ -
网上找到bip44文件,在电脑磁盘中,将其放到app同级文件路径下;
- 在Android studio中,导入“model”,将bip44导入到工程中,再打开projectstructuer,将这个model设置为依赖
public class MyWalletBIP44 {
private static final String TAG = "MyWalletBIP44";
private static WordList wordList = CN.INSTANCE;
private static CoinTypes coinTypes = CoinTypes.Bitcoin;
private static List<String> strings = new ArrayList<>();
/**
* 默认为中文、bitcon(m/44'/0'/0'/0),也可以进行设置成中文英文;
*/
public static ECKeyPair createKey() {
//1.通过bip44生成助记词
byte[] random = RandomSeed.random(WordCount.TWELVE);
strings = new MnemonicGenerator(wordList).createMnemonic(random);
// StringBuilder sb = new StringBuilder();
// byte[] entropy = new byte[Words.TWELVE.byteLength()];
// new SecureRandom().nextBytes(entropy);
// new MnemonicGenerator(io.github.novacrypto.bip39.wordlists.English.INSTANCE).createMnemonic(entropy, sb::append);
String mnemonic = strings.toString();
// String mnemonics = sb.toString();
mnemonic=mnemonic.replace(",","");
mnemonic=mnemonic.replace("[","");
mnemonic=mnemonic.replace("]","");
Log.e("+++", "生成的助记词:" + mnemonic);
//2.生成种子
byte[] seed = generateSeed(mnemonic, null);
//3. 生成根私钥 root private key 树顶点的master key ;bip32
DeterministicKey rootPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
// 4. 由根私钥生成 第一个HD 钱包
DeterministicHierarchy dh = new DeterministicHierarchy(rootPrivateKey);
// 5. 定义父路径 H则是加强 imtoken中的eth钱包进过测试发现使用的是此方式生成 bip44
List<ChildNumber> parentPath = HDUtils.parsePath("M/44H/60H/0H/0");
// 6. 由父路径,派生出第一个子私钥 "new ChildNumber(0)" 表示第一个 (m/44'/60'/0'/0/0)
DeterministicKey child = dh.deriveChild(parentPath, true, true, new ChildNumber(0));
byte[] privateKeyByte = child.getPrivKeyBytes();
ECKeyPair keyPair = ECKeyPair.create(privateKeyByte);
Log.i(TAG, "generateBip44Wallet: 钥匙对 私钥 = " + Numeric.toHexStringNoPrefix(keyPair.getPrivateKey()));
Log.i(TAG, "generateBip44Wallet: 钥匙对 公钥 = " + Numeric.toHexStringNoPrefix(keyPair.getPublicKey()));
Log.i(TAG, "generateBip44Wallet: 钥匙对 公钥 = " + (keyPair.getPublicKey()));
Log.i(TAG, "generateBip44Wallet: 钥匙对 私钥 = " + (keyPair.getPrivateKey()));
return keyPair;
}
/**
* 设置创建账号类型的助记词为:中文
*/
public static void setChineseLanguage() {
wordList = CN.INSTANCE;
}
/**
* 设置创建账号类型的助记词为:英文
*/
public static void setEnglishLanguage() {
wordList = English.INSTANCE;
}
/**
* 设置创建账号类型的币种为:btcoin
* 路径为:0,拼接为:m/44'/0'/0'/0
* 生成的私钥为64位或+0x为66位
*/
public static void setBitcoiTypes() {
coinTypes = CoinTypes.Bitcoin;
}
/**
* 设置创建账号类型的币种为:Ethcoin
* 路径为:0,拼接为:m/44'/60'/0'/0
* 生成的私钥为64位或+0x为66位
*/
public static void setEthereumTypes() {
coinTypes = CoinTypes.Ethereum;
}
public static CoinTypes getCoinTypes() {
return coinTypes;
}
public static WordList getWordList() {
return wordList;
}
public static List<String> getStrings() {
return strings;
}
public static void setStrings(List<String> strings) {
MyWalletBIP44.strings = strings;
}
}
外部类调用时:
public class WalletUtils3 {
中文/英文助记词
public static boolean ChineseZhuJiCi=true;//一般放在Const类中,方便管理
private static final String TAG = "WalletUtils3";
private static String address;
// private static final SecureRandom secureRandom = new SecureRandom();
public static Bip39Wallet generateBip39Wallet(String password, File destinationDirectory)
throws CipherException, IOException {
MyWalletBIP44 myWalletBIP44 = new MyWalletBIP44();
if (ChineseZhuJiCi) {
myWalletBIP44.setChineseLanguage();
} else {
myWalletBIP44.setEnglishLanguage();
}
myWalletBIP44.setEthereumTypes();
ECKeyPair ecKeyPair = myWalletBIP44.createKey();
Wallet.createLight(password, ecKeyPair);
String mnemonic = myWalletBIP44.getStrings().toString();
mnemonic = mnemonic.replace(",", "");
mnemonic = mnemonic.replace("[", "");
mnemonic = mnemonic.replace("]", "");
Log.e(TAG, "generateBip39Wallet: " + mnemonic);
// ECKeyPair privateKey = ECKeyPair.create(sha256(seed));
String walletFile = generateWalletFile(password, ecKeyPair, destinationDirectory, false);
return new Bip39Wallet(walletFile, mnemonic);
}
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public static String generateWalletFile(
String password, ECKeyPair ecKeyPair, File destinationDirectory, boolean useFullScrypt)
throws CipherException, IOException {
WalletFile walletFile;
if (useFullScrypt) {
walletFile = Wallet.createStandard(password, ecKeyPair);
} else {
walletFile = Wallet.createLight(password, ecKeyPair);
}
address = Keys.toChecksumAddress(walletFile.getAddress());
Log.e(TAG, "generateWalletFile address: " + address);
String fileName = getWalletFileName();
File destination = new File(destinationDirectory, fileName);
objectMapper.writeValue(destination, walletFile);
return fileName;
}
private static final int CURRENT_VERSION = 3;
private static final String CIPHER = "aes-128-ctr";
static final String AES_128_CTR = "pbkdf2";
static final String SCRYPT = "scrypt";
private static byte[] generateDerivedScryptKey(
byte[] password, byte[] salt, int n, int r, int p, int dkLen) {
try {
return SCrypt.scrypt(password, salt, n, r, p, dkLen);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return null;
}
private static String getWalletFileName() {
return System.currentTimeMillis() + ".json";
}
public static String getAddress() {
return address;
}
public static void setAddress(String address) {
WalletUtils3.address = address;
}
}
场景生成助记词:
Bip39Wallet wallet = null;
File ff = new File(MyConst.ETH_KEYSTORE_PATH);
if (!ff.exists()) {
ff.mkdirs();
}
try {
// wallet = WalletUtils.generateBip39Wallet(passwordtwo.getText().toString(), new File(MyConst.ETH_KEYSTORE_PATH));
wallet = walletUtils3.generateBip39Wallet(passwordtwo.getText().toString(), new File(MyConst.ETH_KEYSTORE_PATH));
} catch (CipherException e) {
e.printStackTrace();
Log.e("wallet", "CipherException=" + e.getMessage());
} catch (NoClassDefFoundError e) {
e.printStackTrace();
Log.e("wallet", "NoClassDefFoundError=" + e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.e("wallet", "IOException=" + e.getMessage());
}
//keyStore文件名
Log.e("wallet", "getFilename=" + wallet.getFilename());
//12个单词的助记词
Log.e("wallet", "getMnemonic=" + wallet.getMnemonic());
Credentials credentials = WalletUtils.loadBip39Credentials(passwordtwo.getText().toString(), wallet.getMnemonic());
String keyStore = null;
try {
InputStream inputStream = new FileInputStream(MyConst.ETH_KEYSTORE_PATH + "/" + wallet.getFilename());
keyStore = myGetString(inputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String other= WalletSPUtils.getPrivateKey(keyStore,passwordone.getText().toString());
Log.e(TAG, "load other: "+other );
String address = walletUtils3.getAddress();
Log.e(TAG, "address=" + address);
if (other.length() == 64|| other.length() !=66) {
handler.sendEmptyMessage(ShowCreateToast);
List<WalletInfoBean> mList = WalletSPUtils.mList;
if (mList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
WalletInfoBean walletInfoBean = mList.get(i);
walletInfoBean.setClick(false);
}
WalletSPUtils.saveList(mList);
}
WalletInfoBean walletInfoBean = new WalletInfoBean();
walletInfoBean.setKeyStorePath(wallet.getFilename());
walletInfoBean.setMemoryCharacter(wallet.getMnemonic());
walletInfoBean.setWalletName(et_name.getText().toString());
walletInfoBean.setAddress(address);
walletInfoBean.setkeyStore(keyStore);
walletInfoBean.setClick(true);
WalletSPUtils.saveWalletInfo(walletInfoBean);
startActivity(new Intent(context, WalletKeystoreActivity.class)
.putExtra("password", passwordone.getText().toString())
.putExtra("file", walletInfoBean)
.putExtra("type", "create")
);
finish();
导入账号时:
//keystore导入时:
private void importKeyStore(String password, String keystore) {
try {
// 判断大小store
JSONObject jsonObject=new JSONObject(keystore);
if (jsonObject!=null){
String n=jsonObject.getJSONObject("crypto").getJSONObject("kdfparams").getString("n");
Log.e(TAG, "importKeyStore: "+n );
if (n.length()>5) {
handlerSuccess.sendEmptyMessage(ShowLoad);
BigToSmall(keystore, password);
return;
}
}
ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
WalletFile walletFile = objectMapper.readValue(keystore, WalletFile.class);
ECKeyPair ecKeyPair = Wallet.decrypt(password, walletFile);
String publicKey = ecKeyPair.getPublicKey().toString(16);
String address = "0x" + Keys.getAddress(publicKey);
File ff = new File(MyConst.ETH_KEYSTORE_PATH);
if (!ff.exists()) {
ff.mkdirs();
}
String generateWalletFile = walletUtils3.generateWalletFile(password, ecKeyPair,
new File(MyConst.ETH_KEYSTORE_PATH), false);
setNumState();//退出当前用户
WalletInfoBean walletInfoBean = new WalletInfoBean();
walletInfoBean.setKeyStorePath(generateWalletFile);
walletInfoBean.setWalletName(import_name.getText().toString());
walletInfoBean.setkeyStore(keystore);
walletInfoBean.setAddress(address);
walletInfoBean.setClick(true);
WalletSPUtils.saveWalletInfo(walletInfoBean);
show("导入成功");
getActivity().finish();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
showToast("导入失败");
e.printStackTrace();
} catch (CipherException e) {
show("KEYSTORE或节点密码密码不正确");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void BigToSmall(String keystore,String password) {
Flowable
.just(keystore)
.filter(s -> validateInput(s,password))
.flatMap(s -> InitWalletManager.shared().importKeystore(context,s,password))
.compose(ScheduleCompat.apply()).subscribe();//必填
// .subscribe((FlowableSubscriber<? super HLWallet>) this);
}
private boolean validateInput(String privateKey, String password) {
// validate empty
TextView textView=null;
if (TextUtils.isEmpty(privateKey) || TextUtils.isEmpty(password)){
ScheduleCompat.snackInMain(textView,"please input data");
return false;
}
return true;
}
// 私钥导入
private void importPrivateKey(String passwd, String privateKey) {
Log.e("tag", "importPrivateKey: " + privateKey);
BigInteger pk = Numeric.toBigInt(privateKey);
byte[] privateKeyByte = pk.toByteArray();
ECKeyPair keyPair = ECKeyPair.create(privateKeyByte);
WalletFile walletFile = null;
try {
walletFile = Wallet.createLight(passwd, keyPair);
} catch (CipherException e) {
show("密码错误");
e.printStackTrace();
}
String address = Keys.toChecksumAddress(walletFile.getAddress());
Log.e(TAG, "importPrivateKey address: " + address);
try {
File ff = new File(MyConst.ETH_KEYSTORE_PATH);
if (!ff.exists()) {
ff.mkdirs();
}
//
String generateWalletFile = walletUtils3.generateWalletFile(passwd, keyPair,
new File(MyConst.ETH_KEYSTORE_PATH), false);
WalletInfoBean walletInfoBean = new WalletInfoBean();
try {
InputStream inputStream = new FileInputStream(MyConst.ETH_KEYSTORE_PATH + "/" + generateWalletFile);
String keyStore = myGetString(inputStream);
Log.e("tag", "load: " + keyStore);
walletInfoBean.setkeyStore(keyStore);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 助记词
private void importAuxiliaries(String passwd, String menmory) {
byte[] seed = generateSeed(menmory, null);
DeterministicKey rootPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
// 4. 由根私钥生成 第一个HD 钱包
DeterministicHierarchy dh = new DeterministicHierarchy(rootPrivateKey);
// 5. 定义父路径 H则是加强 imtoken中的eth钱包进过测试发现使用的是此方式生成 bip44
List<ChildNumber> parentPath = HDUtils.parsePath("M/44H/60H/0H/0");
// 6. 由父路径,派生出第一个子私钥 "new ChildNumber(0)" 表示第一个 (m/44'/60'/0'/0/0)
DeterministicKey child = dh.deriveChild(parentPath, true, true, new ChildNumber(0));
byte[] privateKeyByte = child.getPrivKeyBytes();
ECKeyPair keyPair = ECKeyPair.create(privateKeyByte);
Log.i(TAG, "generateBip44Wallet: 钥匙对 私钥 = " + Numeric.toHexStringNoPrefix(keyPair.getPrivateKey()));
Log.i(TAG, "generateBip44Wallet: 钥匙对 公钥 = " + Numeric.toHexStringNoPrefix(keyPair.getPublicKey()));
WalletFile walletFile = null;
try {
walletFile = Wallet.createLight(passwd, keyPair);
} catch (CipherException e) {
e.printStackTrace();
}
String address = Keys.toChecksumAddress(walletFile.getAddress());
Log.e(TAG, "importAuxiliaries: " + address);
try {
File ff = new File(MyConst.ETH_KEYSTORE_PATH);
if (!ff.exists()) {
ff.mkdirs();
}
String generateWalletFile = WalletUtils.generateWalletFile(passwd, keyPair,
new File(MyConst.ETH_KEYSTORE_PATH), false);
setNumState();//退出当前用户
WalletInfoBean walletInfoBean = new WalletInfoBean();
walletInfoBean.setKeyStorePath(generateWalletFile);
walletInfoBean.setMemoryCharacter("");
walletInfoBean.setWalletName(import_name.getText().toString());
walletInfoBean.setAddress(address);
walletInfoBean.setClick(true);
WalletSPUtils.saveWalletInfo(walletInfoBean);
show("导入成功");
getActivity().finish();