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"
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章