ppad-csecp256k1-0.2.0: bitcoin-core/secp256k1 bindings
Copyright(c) 2024 Jared Tobin
LicenseMIT
MaintainerJared Tobin <jared@ppad.tech>
Safe HaskellSafe-Inferred
LanguageHaskell2010

Crypto.Curve.Secp256k1

Description

Bindings to bitcoin-core/secp256k1, a C library supporting digital signatures and other cryptographic primitives on the secp256k1 elliptic curve.

This library exposes a minimal subset of functionality, primarily supporting ECDSA/Schnorr signatures and ECDH secret computation.

We're interacting with a C library here, and we don't pretend that we aren't. IO is prevalent and unhidden, and asynchronous exceptions (in the form of Secp256k1Exception) are the error-handling method of choice.

Synopsis

Documentation

newtype Context Source #

A bitcoin-core/secp256k1 context.

bitcoin-core/secp256k1 computations typically require a context, the primary purpose of which is to store randomization data as increased protection against side-channel attacks (and the second of which is boring pointer storage to various library callbacks).

You should create and use values of this type via wrcontext or wcontext.

The data constructor is exported only to make the implementation easier to benchmark. You should not pattern match on or manipulate context values.

Constructors

Context (Ptr Context) 

Instances

Instances details
Generic Context Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Associated Types

type Rep Context 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Context = D1 ('MetaData "Context" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "Context" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Ptr Context))))

Methods

from :: Context -> Rep Context x #

to :: Rep Context x -> Context #

Show Context Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Context Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Context = D1 ('MetaData "Context" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "Context" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Ptr Context))))

wcontext Source #

Arguments

:: (Context -> IO ())

continuation to run in the context

-> IO () 

Execute the supplied continuation within a fresh bitcoin-core/secp256k1 context. The context will be destroyed afterwards.

This function executes the supplied continuation in a context that has not been randomized, and so doesn't offer additional side-channel attack protection. For that, use wrcontext.

>>> wcontext $ \tex -> parse_pub tex bytestring
"<bitcoin-core/secp256k1 public key>"

wrcontext Source #

Arguments

:: ByteString

32 bytes of fresh entropy

-> (Context -> IO ())

continuation to run in the context

-> IO () 

Same as wcontext, but randomize the bitcoin-core/secp256k1 context with the provided 32 bytes of entropy before executing the supplied continuation.

Use this function to execute computations that may benefit from additional side-channel attack protection.

>>> wrcontext entropy $ \tex -> sign tex sec msg
"<bitcoin-core/secp256k1 signature>"

data Sig Source #

A bitcoin-core/secp256k1-internal ECDSA signature.

Create a value of this type via sign, or parse a DER-encoded signature via parse_der.

Instances

Instances details
Generic Sig Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Associated Types

type Rep Sig 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Sig = D1 ('MetaData "Sig" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "Sig" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

Methods

from :: Sig -> Rep Sig x #

to :: Rep Sig x -> Sig #

Show Sig Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Methods

showsPrec :: Int -> Sig -> ShowS #

show :: Sig -> String #

showList :: [Sig] -> ShowS #

type Rep Sig Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Sig = D1 ('MetaData "Sig" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "Sig" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

sign_ecdsa Source #

Arguments

:: Context 
-> ByteString

32-byte secret key

-> ByteString

32-byte message hash

-> IO Sig 

Sign a 32-byte message hash with the provided secret key.

>>> wrcontext entropy $ \tex -> sign tex sec msg
"<bitcoin-core/secp256k1 signature>"

verify_ecdsa Source #

Arguments

:: Context 
-> Pub 
-> ByteString

32-byte message hash

-> Sig 
-> IO Bool 

Verify an ECDSA signature for the provided message hash with the supplied public key.

Returns True for a verifying signature, False otherwise.

>>> wcontext $ \tex -> verify tex pub msg good_sig
True
>>> wcontext $ \tex -> verify tex pub msg bad_sig
False

sign_schnorr Source #

Arguments

:: Context 
-> ByteString

32-byte message hash

-> ByteString

32-byte secret key

-> ByteString

32 bytes of fresh entropy

-> IO ByteString

64-byte signature

Sign a 32-byte message hash with the provided secret key, using the provided 32 bytes of fresh auxiliary entropy.

BIP340 recommends that 32 bytes of fresh auxiliary entropy be generated and added at signing time as additional protection against side-channel attacks (namely, to thwart so-called "fault injection" attacks). This entropy is supplemental to security, and the cryptographic security of the signature scheme itself does not rely on it, so it is not strictly required; 32 zero bytes can be used in its stead.

The resulting 64-byte Schnorr signature is portable, and so is not wrapped in a newtype.

>>> import qualified System.Entropy as E  -- example entropy source
>>> enn <- E.getEntropy 32
>>> aux <- E.getEntropy 32
>>> wrcontext enn $ \tex -> sign_schnorr tex msg sec aux

verify_schnorr Source #

Arguments

:: Context 
-> Pub 
-> ByteString

32-byte message hash

-> ByteString

64-byte signature

-> IO Bool 

Verify a 64-byte Schnorr signature for the provided 32-byte message hash with the supplied public key.

>>> wrcontext entropy $ \tex -> verify_schnorr tex pub msg sig

ecdh Source #

Arguments

:: Context 
-> Pub 
-> ByteString

32-byte secret key

-> IO ByteString

32-byte secret key

Compute an ECDH secret key from the provided public key and (32-byte) secret key.

>>> wrcontext entropy $ \tex -> ecdh tex pub sec

parse_der Source #

Arguments

:: Context 
-> ByteString

DER-encoded signature

-> IO Sig 

Parse a DER-encoded bytestring into a signature.

>>> wcontext $ \tex -> parse_der tex bytestring
"<bitcoin-core/secp256k1 signature>"
>>> wcontext $ \tex -> parse_der tex bad_bytestring
*** Exception: Secp256k1Error

serialize_der Source #

Arguments

:: Context 
-> Sig 
-> IO ByteString

DER-encoded signature

Serialize a signature into a DER-encoded bytestring.

>>> wcontext $ \tex -> serialize_der tex sig

parse_compact Source #

Arguments

:: Context 
-> ByteString

bytestring encoding a 64-byte compact signature

-> IO Sig 

Parse a bytestring encoding a compact (64-byte) signature.

>>> wcontext $ \tex -> parse_compact tex bytestring

serialize_compact :: Context -> Sig -> IO ByteString Source #

Serialize a signature into a compact (64-byte) bytestring.

>>> wcontext $ \tex -> serialize_compact tex sig

newtype Pub Source #

A bitcoin-core/secp256k1-internal public key.

Create a value of this type by parsing a compressed or uncompressed public key via parse_pub, deriving one from a secret key via create_pub, or extracting one from a keypair via keypair_pub.

Constructors

Pub ByteString 

Instances

Instances details
Generic Pub Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Associated Types

type Rep Pub 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Pub = D1 ('MetaData "Pub" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "Pub" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

Methods

from :: Pub -> Rep Pub x #

to :: Rep Pub x -> Pub #

Show Pub Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Methods

showsPrec :: Int -> Pub -> ShowS #

show :: Pub -> String #

showList :: [Pub] -> ShowS #

type Rep Pub Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep Pub = D1 ('MetaData "Pub" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "Pub" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

derive_pub Source #

Arguments

:: Context 
-> ByteString

32-byte secret key

-> IO Pub 

Derive a public key from a 32-byte secret key.

>>> wrcontext entropy $ \tex -> derive_pub tex sec
"<bitcoin-core/secp256k1 public key>"

parse_pub Source #

Arguments

:: Context 
-> ByteString

compressed or uncompressed public key

-> IO Pub 

Parse a compressed (33-byte) or uncompressed (65-byte) public key.

>>> wcontext $ \tex -> parse_pub tex bs
"<bitcoin-core/secp256k1 public key>"

tweak_pub_add Source #

Arguments

:: Context 
-> Pub 
-> ByteString

32-byte tweak value

-> IO Pub 

Additively tweak a public key with the supplied 32-byte tweak.

>>> wrcontext $ \tex -> tweak_pub_add pub tweak

tweak_pub_mul Source #

Arguments

:: Context 
-> Pub 
-> ByteString

32-byte tweak value

-> IO Pub 

Multiplicatively tweak a public key with the supplied 32-byte tweak.

>>> wrcontext $ \tex -> tweak_pub_mul pub tweak

tweak_sec_add Source #

Arguments

:: Context 
-> ByteString

32-byte secret key

-> ByteString

32-byte tweak value

-> IO ByteString

32-byte secret key

Additively tweak a secret key with the supplied 32-byte tweak.

>>> wrcontext $ \tex -> tweak_sec_add sec tweak

tweak_sec_mul Source #

Arguments

:: Context 
-> ByteString

32-byte secret key

-> ByteString

32-byte tweak value

-> IO ByteString

32-byte secret key

Multiplicatively tweak a secret key with the supplied 32-byte tweak.

>>> wrcontext $ \tex -> tweak_sec_mul sec tweak

serialize_pub Source #

Arguments

:: Context 
-> Pub 
-> IO ByteString

serialized compressed public key

Serialize a public key into a compressed (33-byte) bytestring representation.

>>> wcontext $ \tex -> serialize_pub tex pub

serialize_pub_u Source #

Arguments

:: Context 
-> Pub 
-> IO ByteString

serialized uncompressed public key

Serialize a public key into an uncompressed (65-byte) bytestring represention.

>>> wcontext $ \tex -> serialize_pub_u tex pub

newtype XOnlyPub Source #

A bitcoin-core/secp256k1-internal x-only public key.

An "x-only" public key corresponds to a public key with even y-coordinate.

Create a value of this type from a Pub via xonly, or parse one directly via parse_xonly.

Constructors

XOnlyPub ByteString 

Instances

Instances details
Generic XOnlyPub Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Associated Types

type Rep XOnlyPub 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep XOnlyPub = D1 ('MetaData "XOnlyPub" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "XOnlyPub" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

Methods

from :: XOnlyPub -> Rep XOnlyPub x #

to :: Rep XOnlyPub x -> XOnlyPub #

Show XOnlyPub Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep XOnlyPub Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep XOnlyPub = D1 ('MetaData "XOnlyPub" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "XOnlyPub" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

xonly :: Context -> Pub -> IO XOnlyPub Source #

Convert a public key into an x-only public key (i.e. one with even y coordinate).

>>> wcontext $ \tex -> xonly tex pub
"<bitcoin-core/secp256k1 x-only public key>"

parse_xonly Source #

Arguments

:: Context 
-> ByteString

compressed or uncompressed public key

-> IO XOnlyPub 

Parse a compressed (33-byte) or uncompressed (65-byte) public key into an x-only public key.

>>> wcontext $ \tex -> parse_xonly tex bytestring
"<bitcoin-core/secp256k1 x-only public key>"

serialize_xonly Source #

Arguments

:: Context 
-> XOnlyPub 
-> IO ByteString

serialized x-only public key

Serialize an x-only public key into a 32-byte bytestring representation.

>>> wcontext $ \tex -> serialize_xonly tex xonly

data KeyPair Source #

A bitcoin-core/secp256k1-internal keypair.

Create a value of this type by passing a secret key to keypair.

Instances

Instances details
Generic KeyPair Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

Associated Types

type Rep KeyPair 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep KeyPair = D1 ('MetaData "KeyPair" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "KeyPair" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

Methods

from :: KeyPair -> Rep KeyPair x #

to :: Rep KeyPair x -> KeyPair #

Show KeyPair Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep KeyPair Source # 
Instance details

Defined in Crypto.Curve.Secp256k1

type Rep KeyPair = D1 ('MetaData "KeyPair" "Crypto.Curve.Secp256k1" "ppad-csecp256k1-0.2.0-1RgdwMFgKjCtPM3l8Nv5z" 'True) (C1 ('MetaCons "KeyPair" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ByteString)))

keypair Source #

Arguments

:: Context 
-> ByteString

32-byte secret key

-> IO KeyPair 

Derive a keypair from the provided 32-byte secret key.

>>> wrcontext entropy $ \tex -> keypair tex sec
"<bitcoin-core/secp256k1 keypair>"

keypair_pub :: Context -> KeyPair -> IO Pub Source #

Extract a public key from a keypair.

>>> wrcontext entropy $ \tex -> keypair_pub tex keypair
"<bitcoin-core/secp256k1 public key>"

keypair_sec Source #

Arguments

:: Context 
-> KeyPair 
-> IO ByteString

32-byte secret key

Extract a secret key from a keypair.

>>> wrcontext entropy $ \tex -> keypair_sec tex keypair

data Secp256k1Exception Source #

A catch-all exception type.

Constructors

Secp256k1Error

Thrown when a bitcoin-core/secp256k1 function returns a value indicating failure.

CSecp256k1Error

Thrown when a csecp256k1 function has been passed a bad (i.e., incorrectly-sized) input.