bmt

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2024 License: MIT Imports: 23 Imported by: 0

README

The Bitcoin Message Tool

Installation

go get github.com/shadowy-pycoder/go-bitcoin-message-tool@latest

Usage

package main

import (
	"fmt"

	"github.com/shadowy-pycoder/go-bitcoin-message-tool/bmt"
)

func main() {
	wifStr := bmt.NewStr("Kx4XofogMJhEdvHGSMRdztgEg3BBHs9B18yv9uBe1VphNcpKyMnF")
	w, _ := bmt.CreateNewWallet(nil, wifStr)
	fmt.Println(w)
	fmt.Println()
	fmt.Println(w.PrivateKey().Hex())
	fmt.Println(w.PrivateKey().Wif())
	fmt.Println(w.PublicKey())
	fmt.Println(w.PublicKeyRaw())
	fmt.Println(w.LegacyAddress())
	fmt.Println(w.SegwitAddress())
	fmt.Println(w.NestedSegwitAddress())
	fmt.Println(w.TaprootAddress())

	var p bmt.JacobianPoint
	p.Mul(w.PrivateKey().Hex(), bmt.GenPoint)      // point multiplication
	fmt.Println(p.ToAffine().Eq(w.PublicKeyRaw())) // calculated point equals wallet public key
	// message verification
	message := `-----BEGIN BITCOIN SIGNED MESSAGE-----
ECDSA is the most fun I have ever experienced
-----BEGIN BITCOIN SIGNATURE-----
16wrm6zJek6REbxbJSLsBHehn3Lj1vo57t

H3x5bM2MpXK9MyLLbIGWQjZQNTP6lfuIjmPqMrU7YZ5CCm5bS9L+zCtrfIOJaloDb0mf9QBSEDIs4UCd/jou1VI=
-----END BITCOIN SIGNATURE-----`
	bm := bmt.BitcoinMessage{}
	bmt.ParseRFCMessage(message, &bm)
	result, err := bmt.VerifyMessage(&bm, false)
	if err != nil {
		panic(err)
	}
	fmt.Println(result.Verified)
	// message signing
	signedMessage, err := bmt.SignMessage(w.PrivateKey(), // private key
		"segwit", // address type
		"ECDSA is the most fun I have ever experienced", // message
		true,  // deterministic signature
		false, // electrum format
	)
	if err != nil {
		panic(err)
	}
	fmt.Println(signedMessage)
}
Private Key (HEX): 191d8aa8b3e52eaa12b9754bf56d118d754602a3b74701678b3d63a93a3b27a2
Private Key (WIF): Kx4XofogMJhEdvHGSMRdztgEg3BBHs9B18yv9uBe1VphNcpKyMnF
Public Key (Raw): (X=d4f0b6554af7e3108dda04c44bc5cd727b13ba9c8bc614ca61462fbca98b4807, Y=361359e859074eb33df657b6b37a6a80b1694657fcc84580b505bdd1497665ec)
Public Key (HEX Compressed): 02d4f0b6554af7e3108dda04c44bc5cd727b13ba9c8bc614ca61462fbca98b4807
Legacy Address: 1AvumVcXFP5hEJBAMkCeFegzhWAM1gvGeZ
Nested SegWit Address: 38CeDX7CWZ5PAUfMw3pgmF98R8X3U9ePpf
Native SegWit Address: bc1qdn4nnn59570wlkdn4tq23whw6y5e6c28p7chr5
Taproot Address: bc1pvm2y9rm950593kglq758620aew3n2gcfhdcrnt868l2nr3u4yetsduhsra


191d8aa8b3e52eaa12b9754bf56d118d754602a3b74701678b3d63a93a3b27a2
Kx4XofogMJhEdvHGSMRdztgEg3BBHs9B18yv9uBe1VphNcpKyMnF
02d4f0b6554af7e3108dda04c44bc5cd727b13ba9c8bc614ca61462fbca98b4807
(X=d4f0b6554af7e3108dda04c44bc5cd727b13ba9c8bc614ca61462fbca98b4807, Y=361359e859074eb33df657b6b37a6a80b1694657fcc84580b505bdd1497665ec)
1AvumVcXFP5hEJBAMkCeFegzhWAM1gvGeZ
bc1qdn4nnn59570wlkdn4tq23whw6y5e6c28p7chr5
38CeDX7CWZ5PAUfMw3pgmF98R8X3U9ePpf
bc1pvm2y9rm950593kglq758620aew3n2gcfhdcrnt868l2nr3u4yetsduhsra
true
true
-----BEGIN BITCOIN SIGNED MESSAGE-----
ECDSA is the most fun I have ever experienced
-----BEGIN BITCOIN SIGNATURE-----
bc1qdn4nnn59570wlkdn4tq23whw6y5e6c28p7chr5

J8xT/nFS2YpzmW6kDCoH4hjjLKjR2k7o9fHq2je/natNdMmYzQ7Gik5EHV1gVbkVOl7M74d7g2fEBl+csGqyqJ8=
-----END BITCOIN SIGNATURE-----

Benchmarks

make bench10k
go test -o ./bmt ./bmt -bench=. -benchmem -run=^$ -benchtime 10000x -cpuprofile='./bmt/cpu.prof' -memprofile='./bmt/mem.prof'
goos: linux
goarch: amd64
pkg: github.com/shadowy-pycoder/go-bitcoin-message-tool/bmt
cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
BenchmarkCreateWallets-8                           10000             79132 ns/op            5028 B/op         70 allocs/op
BenchmarkCreateNewWalletFromHex-8                  10000            277714 ns/op            2249 B/op         49 allocs/op
BenchmarkCreateNewWalletFromWif-8                  10000            278893 ns/op            2196 B/op         47 allocs/op
BenchmarkDblPoint-8                                10000               383.8 ns/op             0 B/op          0 allocs/op
BenchmarkAddPoints-8                               10000              1149 ns/op               0 B/op          0 allocs/op
BenchmarkMulGenPoint-8                             10000            130584 ns/op               1 B/op          0 allocs/op
BenchmarkMulPoint-8                                10000            229323 ns/op               3 B/op          0 allocs/op
BenchmarkSignMessageDeterministic-8                10000           1078618 ns/op            7553 B/op        131 allocs/op
BenchmarkSignMessageNonDeterministic-8             10000            895601 ns/op            3951 B/op         81 allocs/op
BenchmarkVerifyMessage-8                           10000            417738 ns/op            2013 B/op         34 allocs/op
BenchmarkConvertToBits-8                           10000               342.4 ns/op             0 B/op          0 allocs/op
BenchmarkValidateKey-8                             10000                36.67 ns/op            0 B/op          0 allocs/op
BenchmarkParseRFCMessage-8                         10000               433.4 ns/op             0 B/op          0 allocs/op
PASS
ok      github.com/shadowy-pycoder/go-bitcoin-message-tool/bmt  34.127s

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	GenPoint = NewJacobianPoint(genPointX, genPointY, one)

	IdentityPoint = NewJacobianPoint(zero, zero, zero)
)

Functions

func ConvertToBits added in v0.1.4

func ConvertToBits(scalar []byte, buf *[]int)

ConvertToBits converts scalar bytes into a LSB first bit array.

Parameters:

  • scalar: bytes slice representing the scalar value to convert.
  • buf: a pointer to a slice of integers representing the bit array.

Returns:

  • The function does not return anything. The bit array is stored in the slice pointed to by the buf parameter.

If the bit length of scalar doesn't fit in buf, ConvertToBits will panic.

func CreateNewWallet

func CreateNewWallet(raw *[]byte, wif *string) (*wallet, error)

CreateNewWallet generates a new wallet with private key, public key, and various address types.

Parameters:

  • raw: a pointer to a byte slice object representing the raw value of the private key.
  • wif: a pointer to a string representing the WIF (Wallet Import Format) of the private key.

Returns:

  • A pointer to a wallet struct representing the new wallet.
  • An error if any occurred during the generation process.

If both parameters are nil generates a random wallet

func CreateWallets

func CreateWallets(n int, path string)

CreateWallets generates a specified number of wallets and either prints them to stdout or writes them to a file.

Parameters:

  • n: the number of wallets to generate.
  • path: the path to the file where the wallets should be written. If empty, the wallets will be printed to stdout.

func DoubleSHA256

func DoubleSHA256(b []byte) []byte

DoubleSHA256 calculates the SHA256 hash of the input byte slice twice.

Parameter:

  • b: input byte slice to be hashed.

Returns: The double SHA256 hashed byte slice.

func NewByteStr added in v0.1.4

func NewByteStr(s string) *[]byte

NewByteStr decodes a hexadecimal string into a byte slice and returns a pointer to it.

Parameters:

  • s: a string representing the hexadecimal value.

Returns:

  • *[]byte: a pointer to the decoded byte slice.

func NewPrivateKey

func NewPrivateKey(raw *[]byte, wif *string) (*privatekey, error)

NewPrivateKey generates a new privatekey object.

It takes in two parameters:

  • raw: a pointer to a byte slice object representing the raw value of the private key.
  • wif: a pointer to a string representing the WIF (Wallet Import Format) of the private key.

The function returns a pointer to a privatekey object and an error.

  • If both raw and wif are provided, it returns an error.
  • If neither raw nor wif is provided, it generates a random private key and returns a new privatekey object.
  • If only wif is provided, it creates a new privatekey object with the provided WIF.
  • If only raw is provided, it creates a new privatekey object with the provided raw value.

The function checks if the generated or provided private key is valid. If the private key is invalid, it returns an error.

The function also encodes the generated or provided private key using the ToWif() method. If the encoding fails, it returns an error.

The function returns a pointer to the newly created privatekey object.

func NewStr added in v0.1.4

func NewStr(s string) *string

NewStr returns a pointer to the input string.

Parameters:

  • s: a string.

Returns:

  • *string: a pointer to the input string.

func ParseRFCMessage added in v0.1.3

func ParseRFCMessage(m string, bm *BitcoinMessage)

ParseRFCMessage parses a given message (RFC2440-like format) string into a BitcoinMessage struct.

Parameters:

  • m: a string representing the message to be parsed.
  • bm: a pointer to a BitcoinMessage struct where the parsed message data will be stored.

Returns: None.

func Ripemd160SHA256

func Ripemd160SHA256(b []byte) []byte

Ripemd160SHA256 computes the RIPEMD160 hash of the SHA-256 hash of the input byte slice.

Parameter:

  • b: input byte slice to be hashed.

Returns: The Ripemd160 hashed byte slice.

func Root

func Root(args []string) error

Root is an entrypoint to bmt CLI application

func ValidateKey added in v0.1.4

func ValidateKey(b *[]byte, scalar *ModNScalar) bool

ValidateKey converts byte slice into ModNScalar and checks if it is a valid key.

Types

type BitcoinMessage

type BitcoinMessage struct {
	// contains filtered or unexported fields
}

func NewBitcoinMessage added in v0.1.5

func NewBitcoinMessage(address, payload, signature string) *BitcoinMessage

NewBitcoinMessage creates a new BitcoinMessage struct with the given address, payload, and signature.

Parameters:

  • address: the address associated with the message.
  • payload: the content of the message.
  • signature: the signature of the message.

Returns:

  • A pointer to a BitcoinMessage struct with the given address, payload, and signature.

func SignMessage

func SignMessage(pk *privatekey, addrType, message string, deterministic, electrum bool) (*BitcoinMessage, error)

SignMessage generates a Bitcoin message signature using the provided private key, address type, message, deterministic flag, and electrum flag.

Parameters:

  • pk: A pointer to a privatekey struct representing the private key. Compressed private key will produce compressed public key and address. Uncompressed private key will only produce one address type - uncompressed legacy address
  • addrType: A string representing the address type. It can be either p2pkh (compressed and uncompressed), p2wpkh-p2sh or p2wpkh (only compressed).
  • message: A string representing the message.
  • deterministic: A boolean indicating whether the signature should be deterministic. If set to true, each unique combination of private key and message will yield only one signature
  • electrum: A boolean indicating whether the signature should be in Electrum format.

Returns:

  • A pointer to a BitcoinMessage struct representing the signed message.
  • An error if there was a problem signing the message.

https://github.com/bitcoin/bips/blob/master/bip-0137.mediawiki

func (*BitcoinMessage) String added in v0.1.5

func (bm *BitcoinMessage) String() string

String returns a string representation of message in RFC2440-like format

https://datatracker.ietf.org/doc/html/rfc2440

type FieldVal added in v0.1.4

type FieldVal = secp256k1.FieldVal

func NewFieldVal added in v0.1.4

func NewFieldVal(s string) *FieldVal

NewFieldVal creates a new FieldVal object from a hexadecimal string.

Parameters:

  • s: a string representing the hexadecimal value.

Returns:

  • A pointer to a FieldVal object.

type JacobianPoint

type JacobianPoint struct {
	X FieldVal
	Y FieldVal
	Z FieldVal
}

func NewJacobianPoint

func NewJacobianPoint(x, y, z *FieldVal) *JacobianPoint

NewJacobianPoint creates a new JacobianPoint with the given x, y, and z coordinates.

func (*JacobianPoint) Add

func (pt *JacobianPoint) Add(p, q *JacobianPoint) *JacobianPoint

Add performs elliptic curve point addition in Jacobian coordinates for the secp256k1 curve.

It takes two JacobianPoint points p and q as input parameters and returns a JacobianPoint point.

Parameters:

  • p: a pointer to a JacobianPoint representing the first point.
  • q: a pointer to a JacobianPoint representing the second point.

Returns:

  • a pointer to a JacobianPoint representing the sum of p and q.

https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl

func (*JacobianPoint) Dbl

Dbl performs a point doubling operation in the elliptic curve cryptography with 256 Bit Primes.

Parameter:

  • p: a pointer to a JacobianPoint struct representing the point to be doubled.

Returns: A pointer to a JacobianPoint struct representing the result of the point doubling operation.

https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l

func (*JacobianPoint) Eq

func (pt *JacobianPoint) Eq(q *JacobianPoint) bool

Eq compares the current JacobianPoint with another JacobianPoint.

Parameters:

  • q: the JacobianPoint to compare with.

Returns:

  • bool: true if the points are equal, false otherwise.

func (*JacobianPoint) Mul

func (pt *JacobianPoint) Mul(scalar *ModNScalar, p *JacobianPoint) *JacobianPoint

Mul performs elliptic curve multiplication.

It takes two parameters:

  • scalar: a pointer to a ModNScalar representing the scalar value.
  • p: a pointer to a JacobianPoint representing the point to be multiplied.

It returns a pointer to a JacobianPoint representing the result of the multiplication.

https://paulmillr.com/posts/noble-secp256k1-fast-ecc/#fighting-timing-attacks

func (*JacobianPoint) Set added in v0.1.4

Set sets the Jacobian point to the provided point.

func (*JacobianPoint) String

func (pt *JacobianPoint) String() string

String returns a string representation of the JacobianPoint struct.

It returns a string in the format "(x=X=<X>, Y=<Y>, Z=<Z>)", where <X>, <Y> and <Z> are the hexadeciaml representations of the X, Y and Z coordinates of the JacobianPoint.

func (*JacobianPoint) ToAffine

func (p *JacobianPoint) ToAffine() *Point

ToAffine converts a point from Jacobian coordinates to affine coordinates.

Parameter:

  • p: the point in Jacobian coordinates.

Returns: A pointer to a Point representing the point in affine coordinates.

type ModNScalar added in v0.1.4

type ModNScalar = secp256k1.ModNScalar

func NewModNScalar added in v0.1.4

func NewModNScalar(s string) *ModNScalar

NewModNScalar creates a new ModNScalar object from a hexadecimal string.

Parameters:

  • s: a string representing the hexadecimal value.

Returns:

  • A pointer to a ModNScalar object.

type Point

type Point struct {
	X FieldVal
	Y FieldVal
}

func (*Point) Eq added in v0.1.3

func (pt *Point) Eq(q *Point) bool

Eq compares the current Point with another Point.

Parameters:

  • q: the Point to compare with.

Returns:

  • bool: true if the points are equal, false otherwise.

func (*Point) String

func (pt *Point) String() string

String returns a string representation of the Point struct.

It returns a string in the format "(X=<X>, Y=<Y>)", where <X> and <Y> are the hexadecimal representations of the X and Y coordinates of the Point.

func (*Point) ToJacobian

func (pt *Point) ToJacobian() *JacobianPoint

ToJacobian converts a point from affine coordinates to Jacobian coordinates.

Parameter:

  • p: a pointer to a Point representing the point in affine coordinates.

Returns: A pointer to a JacobianPoint representing the point in Jacobian coordinates.

func (*Point) Valid

func (pt *Point) Valid() bool

Valid checks if a given point is on the elliptic curve.

type PointError

type PointError struct {
	Message string
	Err     error
}

func (*PointError) Error

func (e *PointError) Error() string

func (*PointError) Unwrap

func (e *PointError) Unwrap() error

type PrivateKeyError

type PrivateKeyError struct {
	Message string
	Err     error
}

func (*PrivateKeyError) Error

func (e *PrivateKeyError) Error() string

func (*PrivateKeyError) Unwrap

func (e *PrivateKeyError) Unwrap() error

type Runner

type Runner interface {
	Init([]string) error
	Run() error
	Name() string
}

type Signature

type Signature struct {
	// contains filtered or unexported fields
}

func NewSignature added in v0.1.4

func NewSignature(r, s *ModNScalar) *Signature

NewSignature creates a new signature given some r and s values.

func (*Signature) R

func (sig *Signature) R() ModNScalar

R returns the r value of the signature.

func (*Signature) S

func (sig *Signature) S() ModNScalar

S returns the s value of the signature.

type SignatureError

type SignatureError struct {
	Message string
	Err     error
}

func (*SignatureError) Error

func (e *SignatureError) Error() string

func (*SignatureError) Unwrap

func (e *SignatureError) Unwrap() error

type VerifyMessageResult added in v0.1.3

type VerifyMessageResult struct {
	Verified bool
	PubKey   string
	Message  string
}

func VerifyMessage

func VerifyMessage(message *BitcoinMessage, electrum bool) (*VerifyMessageResult, error)

VerifyMessage verifies a signed message.

Parameters:

  • message (*BitcoinMessage): The signed message to verify.
  • electrum: a flag indicating whether to use the electrum signature format.

Returns:

  • a pointer to a VerifyMessageResult struct containing the verification result and the hex-encoded public key.
  • error: an error if any occurred during the verification process.

https://github.com/bitcoin/bips/blob/master/bip-0137.mediawiki

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL