BTC(比特币)地址是一个由字母和数字组成的字符串,用于接收和发送比特币。每个地址代表着区块链上一个唯一的标识符,与一对公钥和私钥相关联。比特币地址的生成过程涉及复杂的加密算法,确保其安全性和唯一性。

BTC地址的特点:

  1. 结构与格式
    • 比特币地址通常以数字“1”或“3”开头,或者以“bc1”开头。根据格式的不同,地址可以分为三种类型:
      • P2PKH (Pay-to-PubKey-Hash):以“1”开头,是最早期的地址格式,例如1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
      • P2SH (Pay-to-Script-Hash):以“3”开头,通常用于多重签名地址或其他复杂脚本,例如3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
      • Bech32 (SegWit):以“bc1”开头,是最新的地址格式,支持隔离见证技术,例如bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080
  2. 生成方式
    • 地址的生成基于椭圆曲线加密算法(Elliptic Curve Cryptography, ECC),特别是椭圆曲线secp256k1
    • 公钥由私钥生成,再经过哈希函数(SHA-256和RIPEMD-160)处理后得到地址。
  3. 地址的安全性
    • 比特币地址本质上是公钥的哈希值,因此只要私钥不泄露,地址是非常安全的。
    • 由于哈希函数的不可逆性,通过地址反推出公钥或私钥几乎是不可能的。
  4. 地址的使用
    • 每个比特币地址可以无限次接收比特币,但最好每次交易使用不同的地址,以提高隐私性。
    • 地址并不存储比特币,它只是一个用来识别比特币所有权的标识符。比特币本身存在区块链上,地址则指向这些比特币的所属权。

常见问题:

  • 地址长度:BTC地址通常是26至35个字符之间。
  • 大小写敏感性:以“1”和“3”开头的地址大小写敏感,而以“bc1”开头的Bech32地址不区分大小写。
  • 验证与校验:比特币地址通常包含校验码,用于检测地址是否有效,从而避免输入错误。

Go实现示例

type BTCAddress struct {
	key *btcutil.WIF
}

func NewBTCAddressFromWIF(wif *btcutil.WIF) *BTCAddress {
	return &BTCAddress{
		key: wif,
	}
}
// GenP2PKAddress Generates the BTC Pay-to-Pubkey address
func (k *BTCAddress) GenP2PKAddress(param *chaincfg.Params) (string, error) {
	address, err := btcutil.NewAddressPubKey(k.key.SerializePubKey(), param)
	if err != nil {
		return "", errors.Wrap(err, "failed to generate P2PK address")
	}
	// AddressPubKey.EncodeAddress 将公钥的字符串编码返回为 pay-to-pubkey-hash
	// so we can get the same address string with GenP2PKHAddress
	return address.EncodeAddress(), nil
}

// GenP2PKHAddress Generates the BTC Pay-to-Pubkey-Hash
func (k *BTCAddress) GenP2PKHAddress(param *chaincfg.Params) (string, error) {
	address, err := btcutil.NewAddressPubKeyHash(btcutil.Hash160(k.key.SerializePubKey()), param)
	if err != nil {
		return "", errors.Wrap(err, "failed to generate P2PKH address")
	}
	return address.EncodeAddress(), nil
}

// GenBech32Address Generates the BTC SegWit address
func (k *BTCAddress) GenBech32Address(param *chaincfg.Params) (string, error) {
	address, err := btcutil.NewAddressWitnessPubKeyHash(btcutil.Hash160(k.key.SerializePubKey()), param)
	if err != nil {
		return "", errors.Wrap(err, "failed to generate P2PKH address")
	}
	return address.EncodeAddress(), nil
}

func (k *BTCAddress) ExportPrivateKey(pwd string) (string, error) {
	encryptData, err := utils.BIP38Encrypt(k.key.String(), pwd)
	if err != nil {
		return "", errors.Wrap(err, "failed to encrypt private key")
	}
	return encryptData, nil
}

func (k *BTCAddress) LoadPrivateKey(encryptStr, pwd string) error {
	decryptData, err := utils.BIP38Decrypt(encryptStr, pwd,"mainnet")
	if err != nil {
		return errors.Wrap(err, "failed to decrypt private key")
	}
	wif, err := btcutil.DecodeWIF(decryptData)
	if err != nil {
		return errors.Wrap(err, "failed to decode WIF")
	}
	k.key = wif
	return nil
}

孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意

腾讯云开发者社区:孟斯特