Loading

使用web3j core 将私钥创建助记词遇到的异常

事件还原:

在使用 MnemonicUtils.generateMnemonic 方法生成助记词的代码写完了以后,本地测试很多次发现正常就吧代码推到库上去了。后面测试同事反馈某些私钥生成助记词的时候失败了。
排查了日志后发现失败的情况抛出了如下的异常

java.lang.IllegalArgumentException: The allowed size of ENT is 128-256 bits of multiples of 32

分析步骤:

拿到异常后,首先去搜一下。没有任何发现 😦
吧关键代码提取出来,开始打断点调试。

在第80行打上断点,进去MnemonicUtils.generateMnemonic 方法发现,它会先对传入的byte数组进行校验。

进入这个validateEntropy校验看看

Good 找到了抛出异常的地方了。同时也发现我们传递进去的私钥字节数组的长度为33位?

此时问题变成了为什么这个私钥转换成的字节数组由33位而不是32位?

由第一个图我们可以得到私钥的16进制字符串:
9d38135d9eb270e29ed4fd055a23c1c55486af3bd946f984b1d45d5b5810a249

由debug得出字节数组为:[0, -99, 56, 19, 93, -98, -78, 112, -30, -98, -44, -3, 5, 90, 35, -63, -59, 84, -122, -81, 59, -39, 70, -7, -124, -79, -44, 93, 91, 88, 16, -94, 73]

由上图可知,-99的16进制就是9d ,所以字节数组是多了前面的这个0

解决方案:

在转换数组之后对其长度进行校验,如果是33位的字节数组,就判断首位是否位0,如果是,则将第一位舍弃。

测试OK

点击查看代码
import org.web3j.crypto.MnemonicUtils;

        String intPrivateKey="71112194320368789998803347305328030081773433265531236127646905100644415218249";

        BigInteger bigPriv=new BigInteger(intPrivateKey);
        String hex16Priv=bigPriv.toString(16);
        System.out.println("====| "+hex16Priv);

        byte[] privArray=bigPriv.toByteArray();

        if (privArray.length==33 && privArray[0]==(byte) 0){
            byte[] tmpArray=new byte[privArray.length-1];
            System.arraycopy(privArray,1,tmpArray,0,tmpArray.length);
            privArray=tmpArray;
        }

        String actualMnemonic= MnemonicUtils.generateMnemonic(privArray);
        System.out.println(actualMnemonic);

        byte[] privBytes=MnemonicUtils.generateEntropy(actualMnemonic);
        String sourceStr=new String(Hex.encode(privBytes));
        System.out.println(sourceStr);
        Assertions.assertEquals(hex16Priv,sourceStr);
posted @ 2021-11-17 16:37  Changing_now  阅读(361)  评论(0编辑  收藏  举报