ppad-fixed-0.1.0: Large fixed-width words and constant-time arithmetic.
Copyright(c) 2025 Jared Tobin
LicenseMIT
MaintainerJared Tobin <jared@ppad.tech>
Safe HaskellNone
LanguageHaskell2010

Numeric.Montgomery.Secp256k1.Curve

Description

Montgomery form Wider words, as well as arithmetic operations, with domain derived from the secp256k1 elliptic curve field prime.

Synopsis

Montgomery form, secp256k1 field prime modulus

data Montgomery Source #

Montgomery-form Wider words, on the Montgomery domain defined by the secp256k1 scalar group order.

>>> let one = 1 :: Montgomery
>>> one
1
>>> putStrLn (render one)
(4294968273, 0, 0, 0)

Constructors

Montgomery !(# Limb, Limb, Limb, Limb #) 

render :: Montgomery -> String Source #

Render a Montgomery value as a String, showing its individual Limbs.

>>> putStrLn (render 1)
(4294968273, 0, 0, 0)

to :: Wider -> Montgomery Source #

Convert a Wider word to the Montgomery domain.

from :: Montgomery -> Wider Source #

Retrieve a Montgomery word from the Montgomery domain.

This function is a synonym for retr.

zero :: Montgomery Source #

Zero (the additive unit) in the Montgomery domain.

one :: Montgomery Source #

One (the multiplicative unit) in the Montgomery domain.

Comparison

eq :: Montgomery -> Montgomery -> Choice Source #

Constant-time equality comparison.

eq_vartime :: Montgomery -> Montgomery -> Bool Source #

Variable-time equality comparison.

Reduction and retrieval

redc Source #

Arguments

:: Montgomery

low wider-word, Montgomery form

-> Montgomery

high wider-word, Montgomery form

-> Montgomery

reduced value

Montgomery reduction.

The first argument represents the low words, and the second the high words, of an extra-large eight-limb word in Montgomery form.

retr Source #

Arguments

:: Montgomery

value in montgomery form

-> Wider

retrieved value

Retrieve a Montgomery value from the Montgomery domain, producing a Wider word.

redc# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

lower limbs

-> (# Limb, Limb, Limb, Limb #)

upper limbs

-> (# Limb, Limb, Limb, Limb #)

result

Montgomery reduction.

retr# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

Constant-time selection

select# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

a

-> (# Limb, Limb, Limb, Limb #)

b

-> Choice

c

-> (# Limb, Limb, Limb, Limb #)

result

select Source #

Arguments

:: Montgomery

a

-> Montgomery

b

-> Choice

c

-> Montgomery

result

Return a if c is truthy, otherwise return b.

>>> import qualified Data.Choice as C
>>> select 0 1 (C.true# ())
1

Montgomery arithmetic

add :: Montgomery -> Montgomery -> Montgomery Source #

Addition in the Montgomery domain.

Note that Montgomery is an instance of Num, so you can use + to apply this function.

>>> 1 + 1 :: Montgomery
2

add# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

augend

-> (# Limb, Limb, Limb, Limb #)

addend

-> (# Limb, Limb, Limb, Limb #)

sum

sub :: Montgomery -> Montgomery -> Montgomery Source #

Subtraction in the Montgomery domain.

Note that Montgomery is an instance of Num, so you can use - to apply this function.

>>> 1 - 1 :: Montgomery
0

sub# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

minuend

-> (# Limb, Limb, Limb, Limb #)

subtrahend

-> (# Limb, Limb, Limb, Limb #)

difference

mul Source #

Arguments

:: Montgomery

multiplicand in montgomery form

-> Montgomery

multiplier in montgomery form

-> Montgomery

montgomery product

Multiplication in the Montgomery domain.

Note that Montgomery is an instance of Num, so you can use * to apply this function.

>>> 1 * 1 :: Montgomery
1

mul# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

sqr :: Montgomery -> Montgomery Source #

Squaring in the Montgomery domain.

>>> sqr 1
1
>>> sqr 2
4
>>> sqr (negate 2)
4

sqr# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

neg :: Montgomery -> Montgomery Source #

Additive inverse in the Montgomery domain.

Note that Montgomery is an instance of Num, so you can use negate to apply this function.

>>> negate 1 :: Montgomery
115792089237316195423570985008687907853269984665640564039457584007908834671662
>>> (negate 1 :: Montgomery) + 1
0

neg# Source #

Arguments

:: (# Limb, Limb, Limb, Limb #)

argument

-> (# Limb, Limb, Limb, Limb #)

modular negation

inv :: Montgomery -> Montgomery Source #

Multiplicative inverse in the Montgomery domain.

> inv 2

57896044618658097711785492504343953926634992332820282019728792003954417335832 >> inv 2 * 2 1

inv# :: (# Limb, Limb, Limb, Limb #) -> (# Limb, Limb, Limb, Limb #) Source #

sqrt :: Montgomery -> Maybe Montgomery Source #

Square root (Tonelli-Shanks) in the Montgomery domain.

For a, return x such that a = x x mod p. Returns nothing if no such square root exists.

>>> sqrt 4
Just 2
>>> sqrt 15
Just 69211104694897500952317515077652022726490027694212560352756646854116994689233
>>> (*) <$> sqrt 15 <*> sqrt 15
Just 15

sqrt# :: (# Limb, Limb, Limb, Limb #) -> (# (# Limb, Limb, Limb, Limb #) | () #) Source #

exp :: Montgomery -> Wider -> Montgomery Source #

Exponentiation in the Montgomery domain.

>>> exp 2 3
8
>>> exp 2 10
1024

odd# :: (# Limb, Limb, Limb, Limb #) -> Choice Source #

odd :: Montgomery -> Bool Source #

Check if a Montgomery value is odd.

>>> odd 1
True
>>> odd 2
False
>>> Data.Word.Wider.odd (retr 3) -- parity is preserved
True