p256k

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2025 License: Unlicense Imports: 11 Imported by: 0

README

p256k1

This is a library that uses the bitcoin-core optimized secp256k1 elliptic curve signatures library for nostr schnorr signatures.

If you need to build it without libsecp256k1 C library, you must disable cgo:

export CGO_ENABLED='0'

This enables the fallback btcec pure Go library to be used in its place. This CGO setting is not default for Go, so it must be set in order to disable this.

The standard libsecp256k1-0 and libsecp256k1-dev available through the ubuntu dpkg repositories do not include support for the BIP-340 schnorr signatures or the ECDH X-only shared secret generation algorithm, so you must follow the following instructions to get the benefits of using this library. It is 4x faster at signing and generating shared secrets so it is a must if your intention is to use it for high throughput systems like a network transport.

The easy way to install it, if you have ubuntu/debian, is the script ../ubuntu_install_libsecp256k1.sh, it handles the dependencies and runs the build all in one step for you. Note that it

For ubuntu, you need these:

sudo apt -y install build-essential autoconf libtool  

For other linux distributions, the process is the same but the dependencies are likely different. The main thing is it requires make, gcc/++, autoconf and libtool to run. The most important thing to point out is that you must enable the schnorr signatures feature, and ECDH.

The directory p256k/secp256k1 needs to be initialized, built and installed, like so:

cd secp256k1
git submodule init
git submodule update

Then to build, you can refer to the instructions or just use the default autotools:

./autogen.sh
./configure --enable-module-schnorrsig --enable-module-ecdh --prefix=/usr
make
sudo make install

On WSL2 you may have to attend to various things to make this work, setting up your basic locale (uncomment one or more in /etc/locale.gen, and run locale-gen), installing the basic build tools (build-essential or base-devel) and of course git, curl, wget, libtool and autoconf.

ECDH

TODO: Currently the use of the libsecp256k1 library for ECDH, used in nip-04 and nip-44 encryption is not enabled, because the default version uses the Y coordinate and this is incorrect for nostr. It will be enabled soon... for now it is done with the btcec fallback version. This is slower, however previous tests have shown that this ECDH library is fast enough to enable 8mb/s throughput per CPU thread when used to generate a distinct secret for TCP packets. The C library will likely raise this to 20mb/s or more.

Documentation

Overview

Package p256k is a signer interface that (by default) uses the bitcoin/libsecp256k1 library for fast signature creation and verification of the BIP-340 nostr X-only signatures and public keys, and ECDH.

Currently the ECDH is only implemented with the btcec library.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssertLen

func AssertLen(b []byte, length int, name string) (err error)

func FromSecretBytes

func FromSecretBytes(skb []byte) (
	pkb []byte,
	sec *Sec,
	pub *XPublicKey,

	err error,
)

FromSecretBytes parses and processes what should be a secret key. If it is a correct key within the curve order, but with a public key having an odd Y coordinate, it returns an error with the fixed key.

func Generate

func Generate() (
	skb, pkb []byte,
	sec *Sec,
	pub *XPublicKey,
	err error,
)

Generate gathers entropy to generate a full set of bytes and CGO values of it and derived from it to perform signature and ECDH operations.

func Negate

func Negate(uskb []byte)

Negate inverts a secret key so an odd prefix bit becomes even and vice versa.

func RandomizeContext

func RandomizeContext(ctx *C.secp256k1_context)

func Sign

func Sign(msg *Uchar, sk *SecKey) (sig []byte, err error)

Sign a message and return a schnorr BIP-340 64 byte signature.

func SignFromBytes

func SignFromBytes(msg, sk []byte) (sig []byte, err error)

SignFromBytes Signs a message using a provided secret key and message as raw bytes.

func Verify

func Verify(msg, sig *Uchar, pk *PubKey) (valid bool)

Verify a message signature matches the provided PubKey.

func VerifyFromBytes

func VerifyFromBytes(msg, sig, pk []byte) (err error)

VerifyFromBytes a signature from the raw bytes of the message hash, signature and public key

func Zero

func Zero(sk *SecKey)

Zero wipes the memory of a SecKey by overwriting it three times with random data and then zeroing it.

Types

type Cint

type Cint = C.int

type Context

type Context = C.secp256k1_context

func CreateContext

func CreateContext() *Context

func CreateRandomContext

func CreateRandomContext() (c *Context)

type ECPub

type ECPub struct {
	Key ECPubKey
}

func ECPubFromSchnorrBytes

func ECPubFromSchnorrBytes(xkb []byte) (pub *ECPub, err error)

ECPubFromSchnorrBytes converts a BIP-340 public key to its even standard 33 byte encoding.

This function is for the purpose of getting a key to do ECDH from an x-only key.

type ECPubKey

type ECPubKey = C.secp256k1_pubkey

type Keygen

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

Keygen is an implementation of a key miner designed to be used for vanity key generation with X-only BIP-340 keys.

func NewKeygen

func NewKeygen() (k *Keygen)

NewKeygen allocates the required buffers for deriving a key. This should only be done once to avoid garbage and make the key mining as fast as possible.

This allocates everything and creates proper CGO variables needed for the generate function so they only need to be allocated once per thread.

func (*Keygen) Generate

func (k *Keygen) Generate() (
	sec *Sec,
	pub *XPublicKey,
	pubBytes []byte,
	err error,
)

Generate takes a pair of buffers for the secret and ec pubkey bytes and gathers new entropy and returns a valid secret key and the compressed pubkey bytes for the partial collision search.

The first byte of pubBytes must be sliced off before deriving the hex/Bech32 forms of the nostr public key.

type Pub

type Pub struct {
	Key PubKey
}

Pub is a schnorr BIP-340 public key.

func PubFromBytes

func PubFromBytes(pk []byte) (pub *Pub, err error)

PubFromBytes creates a public key from raw bytes.

func (*Pub) Pub

func (p *Pub) Pub() *PubKey

Pub returns the public key as a PubKey.

func (*Pub) PubB

func (p *Pub) PubB() (b []byte)

PubB returns the contained public key as bytes.

func (*Pub) ToBytes

func (p *Pub) ToBytes() (b []byte, err error)

ToBytes returns the contained public key as bytes.

type PubKey

type PubKey = C.secp256k1_xonly_pubkey

type Sec

type Sec struct {
	Key SecKey
}

func GenSec

func GenSec() (sec *Sec, err error)

func SecFromBytes

func SecFromBytes(sk []byte) (sec *Sec, err error)

func (*Sec) Pub

func (s *Sec) Pub() (p *Pub, err error)

func (*Sec) Sec

func (s *Sec) Sec() *SecKey

type SecKey

type SecKey = C.secp256k1_keypair

type Signer

type Signer struct {
	// SecretKey is the secret key.
	SecretKey *SecKey
	// PublicKey is the public key.
	PublicKey *PubKey
	// BTCECSec is needed for ECDH as currently the CGO bindings don't include it
	BTCECSec *btcec.SecretKey
	// contains filtered or unexported fields
}

Signer implements the signer.I interface.

Either the Sec or Pub must be populated, the former is for generating signatures, the latter is for verifying them.

When using this library only for verification, a constructor that converts from bytes to PubKey is needed prior to calling Verify.

func (*Signer) ECDH

func (s *Signer) ECDH(pubkeyBytes []byte) (secret []byte, err error)

func (*Signer) Generate

func (s *Signer) Generate() (err error)

Generate a new Signer key pair using the CGO bindings to libsecp256k1

func (*Signer) InitPub

func (s *Signer) InitPub(pub []byte) (err error)

func (*Signer) InitSec

func (s *Signer) InitSec(skb []byte) (err error)

func (*Signer) Pub

func (s *Signer) Pub() (b []byte)

func (*Signer) Sec

func (s *Signer) Sec() (b []byte)

func (*Signer) Sign

func (s *Signer) Sign(msg []byte) (sig []byte, err error)

func (*Signer) Verify

func (s *Signer) Verify(msg, sig []byte) (valid bool, err error)

func (*Signer) Zero

func (s *Signer) Zero()

type Uchar

type Uchar = C.uchar

func GetRandom

func GetRandom() (u *Uchar)

func Msg

func Msg(b []byte) (id *Uchar, err error)

Msg checks that a message hash is correct, and converts it for use with a Signer.

func Sig

func Sig(b []byte) (sig *Uchar, err error)

Sig checks that a signature bytes is correct, and converts it for use with a Signer.

func ToUchar

func ToUchar(b []byte) (u *Uchar)

type XPublicKey

type XPublicKey struct {
	Key *C.secp256k1_xonly_pubkey
}

func NewXPublicKey

func NewXPublicKey() *XPublicKey

Directories

Path Synopsis
Package btcec implements the signer.I interface for signatures and ECDH with nostr.
Package btcec implements the signer.I interface for signatures and ECDH with nostr.

Jump to

Keyboard shortcuts

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