Copyright | (c) 2024 Jared Tobin |
---|---|
License | MIT |
Maintainer | Jared Tobin <jared@ppad.tech> |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
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
- newtype Context = Context (Ptr Context)
- wcontext :: (Context -> IO ()) -> IO ()
- wrcontext :: ByteString -> (Context -> IO ()) -> IO ()
- data Sig
- sign_ecdsa :: Context -> ByteString -> ByteString -> IO Sig
- verify_ecdsa :: Context -> Pub -> ByteString -> Sig -> IO Bool
- sign_schnorr :: Context -> ByteString -> ByteString -> ByteString -> IO ByteString
- verify_schnorr :: Context -> Pub -> ByteString -> ByteString -> IO Bool
- ecdh :: Context -> Pub -> ByteString -> IO ByteString
- parse_der :: Context -> ByteString -> IO Sig
- serialize_der :: Context -> Sig -> IO ByteString
- parse_compact :: Context -> ByteString -> IO Sig
- serialize_compact :: Context -> Sig -> IO ByteString
- newtype Pub = Pub ByteString
- derive_pub :: Context -> ByteString -> IO Pub
- parse_pub :: Context -> ByteString -> IO Pub
- tweak_pub_add :: Context -> Pub -> ByteString -> IO Pub
- tweak_pub_mul :: Context -> Pub -> ByteString -> IO Pub
- tweak_sec_add :: Context -> ByteString -> ByteString -> IO ByteString
- tweak_sec_mul :: Context -> ByteString -> ByteString -> IO ByteString
- serialize_pub :: Context -> Pub -> IO ByteString
- serialize_pub_u :: Context -> Pub -> IO ByteString
- newtype XOnlyPub = XOnlyPub ByteString
- xonly :: Context -> Pub -> IO XOnlyPub
- parse_xonly :: Context -> ByteString -> IO XOnlyPub
- serialize_xonly :: Context -> XOnlyPub -> IO ByteString
- data KeyPair
- keypair :: Context -> ByteString -> IO KeyPair
- keypair_pub :: Context -> KeyPair -> IO Pub
- keypair_sec :: Context -> KeyPair -> IO ByteString
- data Secp256k1Exception
Documentation
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.
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>"
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>"
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
Generic Sig Source # | |||||
Defined in Crypto.Curve.Secp256k1 Associated Types
| |||||
Show Sig Source # | |||||
type Rep Sig Source # | |||||
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))) |
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>"
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
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
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
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
Arguments
:: Context | |
-> Sig | |
-> IO ByteString | DER-encoded signature |
Serialize a signature into a DER-encoded bytestring.
>>>
wcontext $ \tex -> serialize_der tex sig
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
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
Generic Pub Source # | |||||
Defined in Crypto.Curve.Secp256k1 Associated Types
| |||||
Show Pub Source # | |||||
type Rep Pub Source # | |||||
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))) |
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>"
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>"
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
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
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
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
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
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
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
Generic XOnlyPub Source # | |||||
Defined in Crypto.Curve.Secp256k1 Associated Types
| |||||
Show XOnlyPub Source # | |||||
type Rep XOnlyPub Source # | |||||
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>"
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>"
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
A bitcoin-core/secp256k1-internal keypair.
Create a value of this type by passing a secret key to
keypair
.
Instances
Generic KeyPair Source # | |||||
Defined in Crypto.Curve.Secp256k1 Associated Types
| |||||
Show KeyPair Source # | |||||
type Rep KeyPair Source # | |||||
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))) |
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>"
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. |
Instances
Exception Secp256k1Exception Source # | |
Defined in Crypto.Curve.Secp256k1 Methods toException :: Secp256k1Exception -> SomeException # fromException :: SomeException -> Maybe Secp256k1Exception # | |
Show Secp256k1Exception Source # | |
Defined in Crypto.Curve.Secp256k1 Methods showsPrec :: Int -> Secp256k1Exception -> ShowS # show :: Secp256k1Exception -> String # showList :: [Secp256k1Exception] -> ShowS # |