base58 base58check 编码

介绍

  • Base58 是 Bitcoin 中使用的一种独特的编码方式,主要用于产生 Bitcoin 的钱包地址。
  • Base58 采用数字、大写字母、小写字母,去除歧义字符 0(零)、O(大写字母 O)、I(大写字母i)、l(小写字母L),总计58个字符作为编码的字母表。
  • Base58Check 是一种 Base58 编码格式,可在前几个字符中明确编码的数据类型(版本号 Version),并在最后几个字符中包含一个错误检测代码(校验和 Checksum)。

引用:https://www.jianshu.com/p/d8af38e091be

Base58

const (
	// base58 编码基数表
	alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
)

func Encode(b []byte) []byte {
	var (
		x     *big.Int // b对应的大整数
		radix *big.Int // 除数
		zero  *big.Int // 大整数0
		mod   *big.Int // 模
		dst   []byte   // 编码结果
	)

	x = big.NewInt(0).SetBytes(b)
	radix = big.NewInt(58) // 58
	zero = big.NewInt(0)
	mod = &big.Int{}
	for x.Cmp(zero) != 0 {
		x.DivMod(x, radix, mod) // 除余法
		dst = append(dst, alphabet[mod.Int64()])
	}

	reverse(dst)
	return dst
}

func Decode(b []byte) []byte {
	r := big.NewInt(0)
	for _, c := range b {
		i := bytes.IndexByte([]byte(alphabet), c)
		r.Mul(r, big.NewInt(58))
		r.Add(r, big.NewInt(int64(i)))
	}
	return r.Bytes()
}

func reverse(b []byte) {
	i, j := 0, len(b)-1
	for i < j {
		b[i], b[j] = b[j], b[i]
		i++
		j--
	}
}

Base58check

const (
	version = byte(0x00)
)

func Encode(hash160 []byte) (base58checkEncoded []byte) {
	encoded := make([]byte, len(hash160)+1)
	encoded[0] = version
	copy(encoded[1:], hash160)

	// 执行两次 SHA-256
	hash := sha256.Sum256(encoded)
	hash2 := sha256.Sum256(hash[:])

	checksum := hash2[0:4]
	encodedChecksum := append(encoded, checksum...)
	base58EncodedChecksum := base58.Encode(encodedChecksum)

	// 由于base58会将0删除,比特币要求在0的位置补上1,即比特币地址由1开始的原因
	var buffer bytes.Buffer
	for _, v := range encodedChecksum {
		if v != byte(0x00) {
			break
		}
		buffer.WriteByte('1')
	}
	buffer.Write(base58EncodedChecksum)

	return buffer.Bytes()
}

func Decode(b []byte) (hash160 []byte, err error) {
	encodedChecksum := base58.Decode(b[1:])

	hash160 = encodedChecksum[:len(encodedChecksum)-4]
	checksum := encodedChecksum[len(encodedChecksum)-4:]

	var buffer bytes.Buffer
	for _, v := range b {
		if v != '1' {
			break
		}
		buffer.WriteByte(0)
	}
	buffer.Write(hash160)
	encoded := buffer.Bytes()

	// 执行两次 SHA-256,验证校验码是否正确
	hash := sha256.Sum256(encoded)
	hash2 := sha256.Sum256(hash[:])

	if !bytes.Equal(hash2[:4], checksum) {
		return nil, fmt.Errorf("checksum error")
	}

	return hash160, nil
}

Test

func TestBase58(t *testing.T) {
	src := []byte("this is the example")
	e := Encode(src)
	t.Log(string(e))
	d := Decode(e)
	require.Equal(t, src, d)
}
func TestBase58check(t *testing.T) {
	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	require.NoError(t, err)
	pub := elliptic.Marshal(elliptic.P256(), key.PublicKey.X, key.PublicKey.Y)

	hash := sha256.Sum256(pub)
	r := ripemd160.New()
	r.Write(hash[:])
	hash160 := r.Sum(nil)

	address := Encode(hash160)
	// t.Log(string(address))

	dexHash160, err := Decode(address)
	require.NoError(t, err)
	require.Equal(t, hash160, dexHash160)
}

完整代码:https://github.com/treeforest/easyblc/tree/main/pkg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值