packages feed

secp256k1-haskell-2.0.0: src/Crypto/Secp256k1.hs

{-# LANGUAGE DuplicateRecordFields #-}

-- | ECDSA and BIP-340 Schnorr signatures on the secp256k1 curve, through
-- <https://github.com/bitcoin-core/secp256k1 libsecp256k1>.
--
-- == Values
--
-- Every value is built through a smart constructor or an import function
-- that validates it, so a value of one of these types is always well formed:
--
-- * 'SecKey': a 32-byte big-endian number in the range 1 to n−1, where n is
--   the order of the curve ('secKey').
-- * 'PubKey': a point on the curve ('importPubKey' for the SEC1 encoding).
-- * 'Sig': a signature whose components are both in the range 1 to n−1
--   ('importSig' for DER, 'importCompactSig' for the compact encoding).
-- * 'Msg': a 32-byte hash ('msg').
-- * 'Tweak': a 32-byte big-endian number in the range 0 to n−1 ('tweak').
-- * 'SchnorrSig': a 64-byte BIP-340 signature ('schnorrSig' checks the
--   length, 'verifySchnorr' the values).
--
-- The @get@ field of each type gives its bytes. For 'SecKey', 'Msg', 'Tweak',
-- 'CompactSig' and 'SchnorrSig' these are the standard big-endian bytes. For 'PubKey' and
-- 'Sig' they are the internal representation of libsecp256k1, which is
-- opaque and not portable. Use 'exportPubKey', 'exportSig' and
-- 'exportCompactSig' to serialize those.
--
-- 'Show', 'Read' and 'Data.String.IsString' use hex of a standard encoding: compressed
-- SEC1 for 'PubKey', compact for 'Sig', and the plain bytes for the others.
-- 'Show' prints secret keys. See 'SecKey' for what that means for logging.
--
-- The raw constructors are not exported from this module. They are in
-- "Crypto.Secp256k1.Internal.Base", which has no API stability guarantee.
--
-- == Schnorr signatures
--
-- BIP-340 public keys are x-only: the 32-byte x coordinate of a point whose
-- y coordinate is even. This module keeps them as 'PubKey' and converts with
-- 'importXOnlyPubKey' and 'exportXOnlyPubKey'. 'verifySchnorr' uses only the
-- x coordinate, so a key and its negation verify the same signatures.
-- 'tweakAddXOnlyPubKey' and 'tweakAddXOnlySecKey' apply a BIP-341 Taproot
-- tweak. Computing the tweak itself, a tagged hash of the internal key and
-- the script tree, is left to the caller.
--
-- 'signSchnorr' is deterministic. BIP-340 recommends fresh auxiliary
-- randomness for every signature, which 'signSchnorrIO' provides. Every
-- Schnorr signing function verifies the signature before returning it, as
-- BIP-340 requires.
--
-- == Contexts
--
-- Every operation takes a 'Ctx'. Create one with 'createContext' and share it
-- between threads. Only 'randomizeContext' modifies a context and needs
-- exclusive access.
--
-- == Differences from Bitcoin Core
--
-- 'signMsg' is plain RFC 6979 and matches the published test vectors.
-- Bitcoin Core also grinds the nonce until r is below 2^255, which keeps DER
-- signatures at 70 bytes. 'signMsgLowR' does the same and gives the same
-- signatures as Bitcoin Core.
--
-- 'verifySig' only accepts lower-S signatures, as libsecp256k1 does. Bitcoin
-- Core normalizes a signature before verifying it, because high-S signatures
-- exist in old blocks. Use 'normalizeSig' before 'verifySig' for that.
--
-- Bitcoin Core verifies every ECDSA signature it makes, as a precaution
-- against a corrupted signature. 'signMsg' does not. The Schnorr signing
-- functions do, because BIP-340 requires it.
--
-- Bitcoin Core's Schnorr signing applies the Taproot tweak itself when it is
-- given a Merkle root. Here 'tweakAddXOnlySecKey' does that step separately.
--
-- == Public key recovery
--
-- ECDSA public key recovery, which Bitcoin signed messages use, is in the
-- module @Crypto.Secp256k1.Recovery@. It is built when the @recovery@ flag of
-- the package is on, which is the default.
module Crypto.Secp256k1
  ( -- * Context
    Ctx,
    withContext,
    createContext,
    randomizeContext,
    cloneContext,

    -- * Messages
    Msg (get),
    msg,

    -- * Secret Keys
    SecKey (get),
    secKey,
    derivePubKey,

    -- * Public Keys
    PubKey (get),
    pubKey,
    importPubKey,
    exportPubKey,

    -- * Signatures
    Sig (get),
    sig,
    signMsg,
    signMsgLowR,
    verifySig,
    normalizeSig,
    isLowS,
    isLowR,

    -- ** DER
    importSig,
    exportSig,

    -- ** Compact
    CompactSig (get),
    compactSig,
    exportCompactSig,
    importCompactSig,

    -- * Addition & Multiplication
    Tweak (get),
    tweak,
    tweakAddSecKey,
    tweakMulSecKey,
    tweakAddPubKey,
    tweakMulPubKey,
    combinePubKeys,
    tweakNegate,

    -- * Schnorr Signatures (BIP-340)
    SchnorrSig (get),
    schnorrSig,
    signSchnorr,
    signSchnorrWithAux,
    signSchnorrIO,
    verifySchnorr,

    -- ** X-Only Public Keys
    importXOnlyPubKey,
    exportXOnlyPubKey,

    -- ** Taproot Tweaks (BIP-341)
    tweakAddXOnlyPubKey,
    tweakAddXOnlySecKey,
  )
where

import Crypto.Secp256k1.Internal.Base
import Crypto.Secp256k1.Internal.Context