ETH钱包生成ECKeyPair的正确姿势

前段时间做了一下eth钱包开发的事情,现在项目基本结束了。空下来就去梳理一下之前遇到的一些关键问题,以及踩过的一些坑。

下面就和大家分享一下我遇到过的一个问题。

创建钱包


在钱包开发中,创建钱包大致分为以下几个步骤。

1、随机生成一组助记词
2、根据助记词生成种子 seed
3、根据种子seed生成ECKeyPair
4、根据ECKeyPair和密码创建钱包

我发现网上很多博客在生成ECKeyPair的时候,姿势不对。

网上很多教程的生成方式

ECKeyPair ecKeyPair= ECKeyPair.create(sha256(seed));

这种方式是Web3j提供的API,看上去是很简洁,用起来很方便,但实际上坑很大,根本不能在项目中使用,只能作为Demo。

在创建ETH钱包的过程,需要使用BIP32,BIP39,BIP44,3个协议。它们的作用如下:
BIP32:
定义了目前被广泛使用的 HD Wallet,生成种子seed 和公钥、私钥的。

BIP39:用于生成助记词

BIP44:
基于 BIP32 的系统,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。简单一点说,它就是指定币种规范的一个协议。它的格式如下:

m / purpose' / coin_type' / account' / change / address_index

其中的 purporse' 固定是 44',代表使用 BIP44。而coin_type'用来表示不同币种,例如 Bitcoin 就是 0',Ethereum 是 60'

目前市面上的Ethereum 钱包均采用以上 Bitcoin HD Wallet 的架构,用的都是BIP44:,具体是这样的m/44'/60'/0'/0/0

而Web3j那种创建方式,并没有采用BIP44,在项目中是不能采用这种方式的,但是依然被很多人采用,并且在网上传播。

下面是我验证这种方式的一个例子。

 private void test(String password, String mnemonics) {
        String path = mContext.getCacheDir() + "/MyWallet";
        //2种方式生成seed是一样的
//        byte[] seed = MnemonicUtils.generateSeed(mnemonics, "");
//        ECKeyPair ecKeyPair = ECKeyPair.create(sha256(seed));
        byte[] seed2 = new SeedCalculator().calculateSeed(mnemonics, "");
        ECKeyPair ecKeyPair2 = ECKeyPair.create(sha256(seed2));

        Log.i(TAG, "test2 pubk : " + ecKeyPair2.getPublicKey());
        Log.i(TAG, "test2 prek : " + ecKeyPair2.getPrivateKey());
        Log.i(TAG, "test2 address : " + Keys.getAddress(ecKeyPair2));
}

通过seed获取ECKeyPair,然后通过ECKeyPair获取公钥、私钥、地址。
结果是这样的,可以明显看出是有问题的。

PublicKey:
7244922113023370429973158797216818288186973573283250245018732882291753635193658294263389808990758395488598426777669619093953194711324283066023497720888144
privateKey:
51826596792659989115758568077400059679039347198031504935670220417030436567903
address : 
f81f6c5eb74f1b726e4bce7f4528c966e46dc2e3

注意:明文私钥是64位的。

正确的姿势


1、生成 seed
2、生成 master key
3、生成 child key
4、我们取第一组child key即m/44'/60'/0'/0/0 得到私钥,keystore及地址

完整代码如下,这段代码用到了BIP32,BIP39,BIP44

/**
     * generate key pair to create eth wallet_normal
     * 生成KeyPair , 用于创建钱包(助记词生成私钥)
     */
    public ECKeyPair generateKeyPair(String mnemonics) {
        // 1. we just need eth wallet_normal for now
        AddressIndex addressIndex = BIP44
                .m()
                .purpose44()
                .coinType(60)
                .account(0)
                .external()
                .address(0);
        // 2. calculate seed from mnemonics , then get master/root key ; Note that the bip39 passphrase we set "" for common
        byte[] seed = new SeedCalculator().calculateSeed(mnemonics, "");
        ExtendedPrivateKey rootKey = ExtendedPrivateKey.fromSeed(seed, Bitcoin.MAIN_NET);
        Log.i(TAG, "mnemonics:" + mnemonics);
        String extendedBase58 = rootKey.extendedBase58();
        Log.i(TAG, "extendedBase58:" + extendedBase58);

        // 3. get child private key deriving from master/root key
        ExtendedPrivateKey childPrivateKey = rootKey.derive(addressIndex, AddressIndex.DERIVATION);
        String childExtendedBase58 = childPrivateKey.extendedBase58();
        Log.i(TAG, "childExtendedBase58:" + childExtendedBase58);

        // 4. get key pair
        byte[] privateKeyBytes = childPrivateKey.getKey();
        ECKeyPair keyPair = ECKeyPair.create(privateKeyBytes);

        // we 've gotten what we need
        String privateKey = childPrivateKey.getPrivateKey();
        String publicKey = childPrivateKey.neuter().getPublicKey();
        String address = Keys.getAddress(keyPair);


        Log.i(TAG, "privateKey:" + privateKey);
        Log.i(TAG, "publicKey:" + publicKey);
        Log.i(TAG, "address:" + Constant.PREFIX_16 + address);

        return keyPair;
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容