fixed

Pure Haskell large fixed-width integers.
git clone git://git.ppad.tech/fixed.git
Log | Files | Refs | README | LICENSE

commit 718cc81fe79096efed60dc523935ecf7db81cc15
parent 621556047e01e29e7c36fa9c06d159cd952640ed
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat,  6 Dec 2025 11:26:53 +0400

test: montgomery tests

Diffstat:
Mtest/Montgomery/Curve.hs | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mtest/Montgomery/Scalar.hs | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 157 insertions(+), 20 deletions(-)

diff --git a/test/Montgomery/Curve.hs b/test/Montgomery/Curve.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE NumericUnderscores #-} @@ -12,19 +13,88 @@ import qualified Numeric.Montgomery.Secp256k1.Curve as C import Test.Tasty import qualified Test.Tasty.HUnit as H +-- modulus +m :: W.Wider +m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F + +-- modulus +mm :: C.Montgomery +mm = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F + +repr :: H.Assertion +repr = H.assertBool mempty (W.eq_vartime 0 (C.from mm)) + +add_case :: String -> W.Wider -> W.Wider -> W.Wider -> H.Assertion +add_case t a b s = do + H.assertEqual "sanity" ((W.from a + W.from b) `mod` W.from m) (W.from s) + H.assertBool t (W.eq_vartime s (C.from (C.to a + C.to b))) + add :: H.Assertion add = do - H.assertBool mempty (W.eq_vartime (1 + 1) (C.from (1 + 1))) - H.assertBool mempty (W.eq_vartime (0 + 1) (C.from (0 + 1))) - let !m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F - !x = 2 ^ (256 :: Word) - 1 - !mm = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F - !mx = 2 ^ (256 :: Word) - 1 - H.assertBool mempty (W.eq_vartime 0 (C.from mm)) - H.assertBool mempty (W.eq_vartime (x - m) (C.from (mx - mm))) + add_case "small" 1 2 3 + add_case "wrap to 0 mod m" + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E 1 0 + add_case "wrap to 1" + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2D 3 1 + add_case "random" + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654321 + 0x0FEEEEEEEEEEEEEEFEEEEEEEEEEEEEEEFEEEEEEEEEEEEEEEFEEEEEEEEEEEEEEE + add_case "near R" + 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 0x5555555555555555555555555555555555555555555555555555555555555555 + 0x00000000000000000000000000000000000000000000000000000001000003D0 + +sub_case :: String -> W.Wider -> W.Wider -> W.Wider -> H.Assertion +sub_case t b a d = do + H.assertEqual "sanity" ((W.from b - W.from a) `mod` W.from m) (W.from d) + H.assertBool t (W.eq_vartime d (C.from (C.to b - C.to a))) + +sub :: H.Assertion +sub = do + sub_case "small" 3 2 1 + sub_case "wrap from 0 mod m" 0 1 + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E + sub_case "wrap to 0" 1 1 0 + sub_case "random" + 0x0FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654321 + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0FECA8641FDB975320ECA8641FDB975320ECA8641FDB975320ECA8641FDB9754 + sub_case "near R" + 0x00000000000000000000000000000000000000000000000000000001000003D0 + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E + 0x00000000000000000000000000000000000000000000000000000001000003D1 + +mul_case :: String -> W.Wider -> W.Wider -> W.Wider -> H.Assertion +mul_case t a b p = do + H.assertEqual "sanity" ((W.from a * W.from b) `mod` W.from m) (W.from p) + H.assertBool t (W.eq_vartime p (C.from (C.to a * C.to b))) + +mul :: H.Assertion +mul = do + mul_case "small" 2 3 6 + mul_case "wrap to 1 mod m" + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E + 0x1 + mul_case "zero" + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0 + 0x0 + mul_case "random" + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654321 + 0xCEF9C520FC3502A4BA6F1CE3B2550511D5E474A66875077EF159DE87E15148FC + mul_case "near R" + 0x00000000000000000000000000000000000000000000000000000001000003D1 + 0x00000000000000000000000000000000000000000000000000000001000003D1 + 0x000000000000000000000000000000000000000000000001000007A2000E90A1 tests :: TestTree tests = testGroup "montgomery tests (curve)" [ - H.testCase "add" add + H.testCase "representation" repr + , H.testCase "add" add + , H.testCase "sub" sub + , H.testCase "mul" mul ] diff --git a/test/Montgomery/Scalar.hs b/test/Montgomery/Scalar.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE NumericUnderscores #-} @@ -12,22 +13,88 @@ import qualified Numeric.Montgomery.Secp256k1.Scalar as S import Test.Tasty import qualified Test.Tasty.HUnit as H --- modulus :: S.Montgomery --- modulus = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +-- modulus +m :: W.Wider +m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + +-- modulus +mm :: S.Montgomery +mm = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + +repr :: H.Assertion +repr = H.assertBool mempty (W.eq_vartime 0 (S.from mm)) + +add_case :: String -> W.Wider -> W.Wider -> W.Wider -> H.Assertion +add_case t a b s = do + H.assertEqual "sanity" ((W.from a + W.from b) `mod` W.from m) (W.from s) + H.assertBool t (W.eq_vartime s (S.from (S.to a + S.to b))) add :: H.Assertion add = do - H.assertBool mempty (W.eq_vartime (1 + 1) (S.from (1 + 1))) - H.assertBool mempty (W.eq_vartime (0 + 1) (S.from (0 + 1))) - let !m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - !x = 2 ^ (256 :: Word) - 1 - !mm = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - !mx = 2 ^ (256 :: Word) - 1 - H.assertBool mempty (W.eq_vartime 0 (S.from mm)) - H.assertBool mempty (W.eq_vartime (x - m) (S.from (mx - mm))) + add_case "small" 1 2 3 + add_case "wrap to 0 mod m" + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 1 0 + add_case "wrap to 1" + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F 3 1 + add_case "random" + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654321 + 0x0FEEEEEEEEEEEEEEFEEEEEEEEEEEEEEEFEEEEEEEEEEEEEEEFEEEEEEEEEEEEEEE + add_case "near R" + 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 0x5555555555555555555555555555555555555555555555555555555555555555 + 0x000000000000000000000000000000014551231950B75FC4402DA1732FC9BEBE + +sub_case :: String -> W.Wider -> W.Wider -> W.Wider -> H.Assertion +sub_case t b a d = do + H.assertEqual "sanity" ((W.from b - W.from a) `mod` W.from m) (W.from d) + H.assertBool t (W.eq_vartime d (S.from (S.to b - S.to a))) + +sub :: H.Assertion +sub = do + sub_case "small" 3 2 1 + sub_case "wrap from 0 mod m" 0 1 + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 + sub_case "wrap to 0" 1 1 0 + sub_case "random" + 0x0FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654321 + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0FECA8641FDB975320ECA8641FDB975320ECA8641FDB975320ECA8641FDB9754 + sub_case "near R" + 0x000000000000000000000000000000014551231950B75FC4402DA1732FC9BEBE + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 + 0x000000000000000000000000000000014551231950B75FC4402DA1732FC9BEBF + +mul_case :: String -> W.Wider -> W.Wider -> W.Wider -> H.Assertion +mul_case t a b p = do + H.assertEqual "sanity" ((W.from a * W.from b) `mod` W.from m) (W.from p) + H.assertBool t (W.eq_vartime p (S.from (S.to a * S.to b))) + +mul :: H.Assertion +mul = do + mul_case "small" 2 3 6 + mul_case "wrap to 1 mod m" + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 + 0x1 + mul_case "zero" + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0 + 0x0 + mul_case "random" + 0x000123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCD + 0x0FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654321 + 0x1A9B526FE2B5CE72CE59A8E81612BC5785CED8C6B231B643B36DA80BE2A60636 + mul_case "near R" + 0x000000000000000000000000000000014551231950B75FC4402DA1732FC9BEBF + 0x000000000000000000000000000000014551231950B75FC4402DA1732FC9BEBF + 0x9D671CD581C69BC5E697F5E45BCD07C6741496C20E7CF878896CF21467D7D140 tests :: TestTree tests = testGroup "montgomery tests (scalar)" [ - H.testCase "add" add + H.testCase "representation" repr + , H.testCase "add" add + , H.testCase "sub" sub + , H.testCase "mul" mul ]