1. 程式人生 > >通過P2PKH 反推比特幣地址

通過P2PKH 反推比特幣地址

這要從比特幣地址的結構說起:

比特幣地址結構: 【版本 + 公鑰雜湊 + 驗證碼】

版本:預設0x00, 即可空白的一位元組。
公鑰:由非對稱加密演算法得出。
公鑰雜湊:就是給公鑰做雜湊演算法得出的結果。
驗證碼:給 [版本 + 公鑰雜湊],sha256兩次,取頭4個字元作為驗證碼。

常見非對稱加密:rsa,ecdsa
常見hash演算法:MD5、sha1、sha256

比特幣由ecdsa算出私鑰、公鑰,再通過公鑰算出比特幣地址。
上面的公鑰雜湊做了 兩次雜湊:首先是sha256,再在此結果再做ripemd160。才變成上面所稱的公鑰雜湊。

以上基本的說完了

那麼 通過P2PKH(pay to public key hash) 反推比特幣地址,要怎樣操作呢?

public key hash 就是上面的 公鑰雜湊
反推地址 不就是 在 公鑰雜湊前面加上版本號,後面加上驗證碼就可以了嗎?

我們可以先看看比特幣轉賬的賬單。

https://www.blockchain.com/zh-cn/btc/tx/b6f6b339b546a13822192b06ccbdd817afea5311845f769702ae2912f7d94ab5?show_adv=true

在這裡插入圖片描述

收款方地址對應下圖的紅框中的PublicKeyHash。
在這裡插入圖片描述

即:
DUP HASH160 PUSHDATA(20)[5410d53b33362bc4f5bf5255767e5ce607415457] EQUALVERIFY CHECKSIG


中的 5410d53b33362bc4f5bf5255767e5ce607415457

將下列go語言程式碼編譯,並且執行。可以由5410d53b33362bc4f5bf5255767e5ce607415457推回比特幣地址。

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"log"

	"github.com/btcsuite/btcutil/base58"
)

const version = byte(0x00)

func P2PKHToAddress(pkscript string) (string, error) {
	hash, err := hex.DecodeString(pkscript)
	if err != nil {
		log.Fatal(err)
	}

	pf := append([]byte{version}, hash...)
	b := append(pf, checkSum(pf)...)

	address := base58.Encode(b)
	return address, nil
}

func checkSum(publicKeyHash []byte) []byte {
	first := sha256.Sum256(publicKeyHash)
	second := sha256.Sum256(first[:])
	return second[0:4]
}

func main() {
	address, err := P2PKHToAddress("5410d53b33362bc4f5bf5255767e5ce607415457")
	if err != nil {
		panic(err)
	}

	fmt.Println("BITCOIN ADDRESS: ", address)
}
	go get -u github.com/btcsuite/btcutil
	go build

跑起

呃…剛開始我在想為什麼收款地址不能直接寫成比特幣地址,非要寫個公鑰雜湊上去。
現在想想中本聰應該是為了省空間吧,直接寫公鑰雜湊比特幣地址省5個位元組。

比特幣地址多數給使用者使用,所以在校驗方面就比較重要。