Filecoin地址生成

算法简介
blake2
BLAKE2的定位是目前安全系数最高的哈希函数。BLAKE2是基于BLAKE实现的,BLAKE是2008年被提交至SHA-3竞赛的一种哈希函数。
BLAKE2不仅仅只是一个简单的哈希函数而已!首先,BLAKE2有两大主要版本:BLAKE2b和BLAKE2s。BLAKE2b是BLAKE的64位版本,它可以生成最高512位的任意长度哈希。BLAKE2s是BLAKE的32位版本,它可以生成最高256位的任意长度哈希。
BLAKE2x是对BLAKE2的简单扩展,它可以生成任意长度的哈希值(长度不受限制)。

ECC  
椭圆曲线加密算法,即:Elliptic Curve Cryptography,简称ECC,是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全。据研究,160位ECC加密安全性相当于1024位RSA加密,210位ECC加密安全性相当于2048位RSA加密。

Base32编码
Base32编码是使用32个可打印字符(字母A-Z和数字2-7)对任意字节数据进行编码的方案,编码后的字符串不用区分大小写并排除了容易混淆的字符,可以方便地由人类使用并由计算机处理。Base32将任意字符串按照字节进行切分,并将每个字节对应的二进制值(不足8比特高位补0)串联起来,按照5比特一组进行切分,并将每组二进制值转换成十进制来对应32个可打印字符中的一个。

RFC
Request For Comments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。目前RFC文件是由Internet Society(ISOC)赞助发行。基本的互联网通信协议都有在RFC文件内详细说明。RFC文件还额外加入许多在标准内的论题,例如对于互联网新开发的协议及发展中所有的记录。因此几乎所有的互联网标准都有收录在RFC文件之中。

地址生成步骤:

  1. 随机生成256位私钥(BIP44协议,)
    privateKey = generatePrivateKey()
    "0x81232f16fa8f8bc2d31096d2407d9e392c25f048861a0e0f640f4febb4f22996"

  2. 利用椭圆曲线加密算法生成公钥
    publicKey=ECC.getPublicKeyFromPrivateKey(privateKey)
    "0xeb15c814543f9c1e62f1e4e13e2b5fd2a4d224b58f8cfeb1e587378d46a96c06dfaf876bc176911e7613c3e8ffe1e928025e266918a935fc6bd921606fcca5b3"

  3. 将公钥前加入0x04值后,进行20位的blake2b计算
    blake2Hash = blake2b("0x04eb15c814543f9c1e62f1e4e13e2b5fd2a4d224b58f8cfeb1e587378d46a96c06dfaf876bc176911e7613c3e8ffe1e928025e266918a935fc6bd921606fcca5b3", 20)
    "0x50cedfe81c8cdcf03fede2d075db9025d7f09463"

  4. 将得到的blake2哈希值前添加0x01后,继续用blake2b算法计算4位校验和。
    checksum = blake2b("0x0150cedfe81c8cdcf03fede2d075db9025d7f09463", 4)
    "0x62c27772"(4位转16进制就是8个字符)

  5. 将20位公钥哈希值和4位校验和连接起来,并用遵照RFC4648标准的Base32编码格式进行编码。
    sourceAddress = Base32Encode(blake2Hash ,checksum, 'RFC4648')
    "6j5iu4elnajlrrs4ugk5tjnd365b42csgh7b3hq"

  6. 将编码后的字符串根据地址属性,
    属于测试网(t),
    还是正式网(f),
    是钱包地址(1)
    是合约地址(2)
    加上相应的前缀。
    得到最终地址:
    t16j5iu4elnajlrrs4ugk5tjnd365b42csgh7b3hq

下面是kt的代码:

//通过助记词得到种子
        val seed = DeterministicSeed(
            mnemonicCodes,
            NumericUtil.toSeed(mnemonicCodes, ""),
            "",
            creationTimeSeconds
        )

        //通过biP44得到path
        val path: String? = getPath(0)

        //主密钥
        val keyChain = DeterministicKeyChain.builder().seed(seed).build()
        var rootPublicKey = keyChain.rootKey?.publicKeyAsHex
        Log.d(TAG, "主公钥:$rootPublicKey")
        val parent =
            keyChain.getKeyByPath(BIP44Util.generatePath(path), true)
        var p = Blake2b.Param()
        p.digestLength = 20

        //子私钥
        var xprv = parent.privateKeyAsHex


        Log.d(TAG, "子私钥:$xprv")
        Log.d(TAG, "子私钥(Base58):" + Base58.encode(parent.privKeyBytes))

        //
        val ecKey: ECKey =
            ECKey.fromPrivate(NumericUtil.hexToBytes(xprv))

        /**
         * 什么是压缩公钥?
         *
         * 什么是未压缩公钥?
         */

        //未压缩公钥16进制
        var pulStr =
            "0x04" + ecKey.pubKeyPoint.affineXCoord.toString() + ecKey.pubKeyPoint.affineYCoord.toString()
        Log.d(TAG, "未压缩公钥:$pulStr")

        //未压缩公钥字节
        val encryptionKey =
            NumericUtil.hexToBytes(pulStr)

        //将公钥前加入0x04值后,进行20位的blake2b计算
        p.digestLength = 20
        var blake2Hash = Blake2b.Digest.newInstance(p)
        var blake2HashHexByte = blake2Hash.digest(encryptionKey)
        var blake2HashHexStr = NumericUtil.bytesToHex(blake2HashHexByte)

        Log.d(TAG, blake2HashHexStr)

        //将得到的blake2哈希值前添加0x01后,继续用blake2b算法计算4位校验和
        var blake2HashSecond = "0x01$blake2HashHexStr"

        //用blake2b算法计算4位校验和
        p.digestLength = 4
        var blake2b3 = Blake2b.Digest.newInstance(p)
        var checksumBytes = blake2b3.digest(NumericUtil.hexToBytes(blake2HashSecond))
        var checksum =
            NumericUtil.bytesToHex(checksumBytes)
        Log.d(TAG, "校检和:$checksum")

        //将20位公钥哈希值和4位校验和连接起来
        val addressBytes = ByteArray(blake2HashHexByte.size + checksumBytes.size)
        System.arraycopy(blake2HashHexByte, 0, addressBytes, 0, blake2HashHexByte.size)
        System.arraycopy(checksumBytes, 0, addressBytes, blake2HashHexByte.size, checksumBytes.size)
        var address = "t1" + Base32New.encode(addressBytes)
        Log.d(TAG, "地址:$address")
    }

    //m/44'/461'/0/0/0
    private fun getPath(index: Int): String? {
        //146或1
        return "m/44'/461'/$index/0/0"
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章