slip10

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2025 License: MIT Imports: 15 Imported by: 0

README

Go-SLIP10

🔐 Universal Hierarchical Deterministic Key Derivation for Go

Go Reference Go Report Card Test codecov

A robust, idiomatic Go library for SLIP-10 (Universal Hierarchical Deterministic Key Derivation) and BIP-39 (Mnemonic Codes).


go-slip10 provides a unified interface to generate and derive keys across multiple elliptic curves, making it the perfect foundation for multi-chain wallets and cryptographic tools.

⚡ Quick Start

import "github.com/meehow/go-slip10"

// Mnemonic → Seed → Master Key → Child Key in 3 lines
seed := slip10.MnemonicToSeed("abandon abandon abandon ... about", "")
master, _ := slip10.NewMasterNode(seed, slip10.NewSecp256k1())
child, _ := master.DerivePath("m/44'/0'/0'/0/0")

🚀 Key Features

  • Multi-Curve Support: Native support for secp256k1 (Bitcoin/Ethereum), NIST P-256, Ed25519 (Solana/Cardano), and Curve25519.
  • Standards Compliant: Strictly follows SLIP-10 and BIP-39 specifications.
  • Public Child Derivation (CKDpub): Full support for deriving public child keys from public parent keys for Weierstrass curves (secp256k1, NIST P-256), enabling secure watch-only architectures.
  • Verified Correctness: Rigorously tested against official test vectors and reference implementations. 97% Test Coverage.
  • High Performance: Includes a custom, optimized Base58 implementation and minimal external dependencies.

🌍 Use Cases

  • Multi-chain HD Wallets: Derive keys for Bitcoin, Ethereum, Solana, and more from a single mnemonic
  • Watch-Only Servers: Use CKDpub to generate receiving addresses without exposing private keys
  • Hardware Wallet Integration: Standard compliance ensures interoperability with Ledger/Trezor
  • Cold Storage Solutions: Generate addresses offline with full derivation path control
  • Key Management Systems: Programmatically manage hierarchical key structures

⚖️ Comparison

Why choose go-slip10 over other libraries?

Feature go-slip10 btcsuite/btcutil anyproto/go-slip10 Generic Crypto Libs
SLIP-10 Support ✅ Native ❌ BIP-32 only ✅ Ed25519 only
Multi-Curve ✅ 4 curves ❌ Secp256k1 only ❌ Ed25519 only ⚠️ Varies
BIP-39 ✅ Built-in ⚠️ Separate pkg
Public Derivation ✅ Weierstrass
Dependencies 🟢 Minimal 🔴 Heavy 🟢 Minimal 🟢 Minimal
Type Safety 🛡️ Strict ⚠️ Loose ⚠️ Loose ⚠️ Loose

📦 Installation

go get github.com/meehow/go-slip10

🛠️ Usage Examples

1. Mnemonic to Seed (BIP-39)

Convert a user-friendly mnemonic phrase into a binary seed for key derivation.

package main

import (
    "fmt"
    "github.com/meehow/go-slip10"
)

func main() {
    mnemonic := "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
    passphrase := "optional-passphrase"

    // Deterministically generate a 512-bit seed
    seed := slip10.MnemonicToSeed(mnemonic, passphrase)
    fmt.Printf("Seed: %x\n", seed)
}
2. Multi-Coin Derivation (SLIP-10)

Derive keys for different blockchains from the same master seed using different curves.

// Create a Master Node for Bitcoin (secp256k1)
btcMaster, _ := slip10.NewMasterNode(seed, slip10.NewSecp256k1())
// Derive BIP-44 path: m/44'/0'/0'/0/0
btcChild, _ := btcMaster.DerivePath("m/44'/0'/0'/0/0")
fmt.Printf("BTC Private Key: %x\n", btcChild.PrivKey)

// Create a Master Node for Solana (Ed25519)
solMaster, _ := slip10.NewMasterNode(seed, slip10.NewEd25519())
// Derive path: m/44'/501'/0'/0' (Hardened only for Ed25519)
solChild, _ := solMaster.DerivePath("m/44'/501'/0'/0'")
fmt.Printf("SOL Private Key: %x\n", solChild.PrivKey)
3. Public Child Derivation (Watch-Only Wallets)

Safely derive public keys on a server without ever exposing private keys.

// Assume we have an account-level extended public key (xpub)
accountXPub := "xpub6C..." 
node, _ := slip10.NewNodeFromExtendedKey(accountXPub, slip10.NewSecp256k1())

// Derive receive address index 0 (public derivation)
childPub, _ := node.Derive(0) 

fmt.Printf("Derived Public Key: %x\n", childPub.PublicKey())
// Note: childPub.PrivKey is nil, ensuring security.

📈 Performance

Benchmarked on Intel Core i7-10510U @ 1.80GHz:

Operation Time Memory Allocations
Base58 Encode 1.31 µs 96 B 2
Base58 Decode 776 ns 32 B 1
Mnemonic to Seed 1.13 ms 1.4 KB 12
Master Node (secp256k1) 30.8 µs 1.2 KB 10
Derive (secp256k1) 32.5 µs 1.4 KB 15
Derive (Ed25519) 21.4 µs 1.1 KB 10
Derive (NIST P-256) 15.8 µs 1.9 KB 22
DerivePath (5 levels) 242 µs 7.4 KB 82
XPriv/XPub Serialization 9.5 µs 224 B 2

Run benchmarks yourself:

go test -bench=. -benchmem ./...

🔒 Security & Design

  • Type Safety: The API is designed to prevent common mistakes, such as attempting public derivation on curves that don't support it (like Ed25519).
  • Minimal Dependencies: Only uses golang.org/x/crypto for core cryptographic operations.
  • Audit Friendly: Clean, readable code structure with clear separation of curve logic.
  • Constant-Time Operations: Uses Go's standard library bignum operations for sensitive calculations.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

# Run tests
go test -race -v ./...

# Run benchmarks
go test -bench=. -benchmem ./...

# Run fuzzing
go test -fuzz=FuzzBase58 -fuzztime=30s ./...

For major changes, please open an issue first to discuss what you would like to change.

🙏 Acknowledgments

📄 License

MIT License - see LICENSE for details.


If you find this library useful, please consider giving it a ⭐

Documentation

Index

Constants

View Source
const (
	// HardenedOffset is added to child index to indicate hardened derivation (BIP-32).
	// Indices >= HardenedOffset are hardened; indices < HardenedOffset are normal.
	HardenedOffset = 0x80000000
)

Variables

View Source
var (
	// VersionMainPublic is the BIP-32 version bytes for mainnet extended public keys (xpub).
	VersionMainPublic = []byte{0x04, 0x88, 0xB2, 0x1E}
	// VersionMainPrivate is the BIP-32 version bytes for mainnet extended private keys (xpriv).
	VersionMainPrivate = []byte{0x04, 0x88, 0xAD, 0xE4}
	// VersionTestPublic is the BIP-32 version bytes for testnet extended public keys (tpub).
	VersionTestPublic = []byte{0x04, 0x35, 0x87, 0xCF}
	// VersionTestPrivate is the BIP-32 version bytes for testnet extended private keys (tpriv).
	VersionTestPrivate = []byte{0x04, 0x35, 0x83, 0x94}
)

Functions

func MnemonicToSeed

func MnemonicToSeed(mnemonic, passphrase string) []byte

MnemonicToSeed converts a BIP-39 mnemonic and an optional passphrase into a 512-bit binary seed.

func ParsePath

func ParsePath(path string) ([]uint32, error)

ParsePath parses a BIP-32 path string into a slice of uint32 indices. The path must start with "m". Use "/" as separator. Example: "m/44'/0'/0'" -> [2147483692, 2147483648, 2147483648]

Types

type Curve

type Curve interface {
	Name() string
	MasterKey(seed []byte) (privKey, chainCode []byte, err error)
	DerivePrivateChild(privKey, chainCode []byte, index uint32) (childPrivKey, childChainCode []byte, err error)
	DerivePublicChild(pubKey, chainCode []byte, index uint32) (childPubKey, childChainCode []byte, err error)
	PublicKey(privKey []byte) []byte
}

Curve represents an elliptic curve supported by SLIP-10.

func NewCurve25519

func NewCurve25519() Curve

func NewEd25519

func NewEd25519() Curve

func NewNist256p1

func NewNist256p1() Curve

func NewSecp256k1

func NewSecp256k1() Curve

type Node

type Node struct {
	Curve     Curve
	IsPrivate bool
	PrivKey   []byte
	PubKey    []byte
	ChainCode []byte
	Depth     byte
	ParentFP  []byte
	Index     uint32
	Version   []byte
}

Node represents an extended key in the SLIP-10 hierarchy.

func NewMasterNode

func NewMasterNode(seed []byte, curve Curve) (*Node, error)

NewMasterNode creates a new master node from a seed for the specified curve.

func NewNodeFromExtendedKey

func NewNodeFromExtendedKey(extendedKey string, curve Curve) (*Node, error)

NewNodeFromExtendedKey creates a node from serialized extended key (xpub/xpriv).

func (*Node) Derive

func (n *Node) Derive(index uint32) (*Node, error)

Derive derives a child node at the given index.

func (*Node) DerivePath

func (n *Node) DerivePath(path string) (*Node, error)

DerivePath derives a child node following the given path (e.g., "m/44'/0'/0'/0/0").

func (*Node) Fingerprint

func (n *Node) Fingerprint() []byte

Fingerprint returns the fingerprint of the node's public key.

func (*Node) PublicKey

func (n *Node) PublicKey() []byte

PublicKey returns the public key associated with this node.

func (*Node) String

func (n *Node) String() string

String returns a safe string representation of the node (does not expose private key).

func (*Node) Wipe

func (n *Node) Wipe()

Wipe overwrites the private key and chain code with zeros to protect sensitive data in memory. It is recommended to call this method when the Node is no longer needed.

func (*Node) XPriv

func (n *Node) XPriv() string

XPriv returns the extended private key (xpriv) string.

func (*Node) XPub

func (n *Node) XPub() string

XPub returns the extended public key (xpub) string.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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