diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,8 @@
 # Changelog
 
+- 0.3.1 (2025-12-27)
+  * Upgrades to ppad-fixed v0.1.2 and ppad-secp256k1 v0.5.1.
+
 - 0.3.0 (2025-12-21)
   * Upgrades to ppad-secp256k1 v0.5, with significant performance
     improvements as a result.
diff --git a/lib/Crypto/HDKey/BIP32.hs b/lib/Crypto/HDKey/BIP32.hs
--- a/lib/Crypto/HDKey/BIP32.hs
+++ b/lib/Crypto/HDKey/BIP32.hs
@@ -79,10 +79,12 @@
 import qualified Data.ByteString.Builder as BSB
 import qualified Data.ByteString.Internal as BI
 import qualified Data.ByteString.Unsafe as BU
+import qualified Data.Choice as C
 import Data.Word (Word8, Word32)
 import Data.Word.Limb (Limb(..))
 import qualified Data.Word.Limb as L
 import Data.Word.Wider (Wider(..))
+import qualified Data.Word.Wider as W
 import qualified Foreign.Storable as Storable (pokeByteOff)
 import qualified GHC.Exts as Exts
 import GHC.Generics
@@ -258,7 +260,7 @@
 
 -- | An extended private key.
 newtype XPrv = XPrv (X Wider)
-  deriving (Eq, Show, Generic)
+  deriving (Show, Generic)
 
 -- | Read the raw private key from an 'XPrv'.
 xprv_key :: XPrv -> Wider
@@ -328,7 +330,8 @@
         (il, ci) = BS.splitAt 32 l
         pil = unsafe_roll32 il -- safe due to 512-bit hmac
         ki  = S.from (S.to pil + S.to sec)
-    in  if   pil >= Secp256k1._CURVE_Q || ki == 0 -- negl
+        com = W.cmp_vartime pil Secp256k1._CURVE_Q
+    in  if   com /= LT || W.eq_vartime ki 0 -- negl
         then ckd_priv _xprv (succ i)
         else XPrv (X ki ci)
   where
@@ -348,8 +351,9 @@
           (il, ci) = BS.splitAt 32 l
           pil = unsafe_roll32 il -- safe due to 512-bit hmac
       pt <- Secp256k1.mul_vartime Secp256k1._CURVE_G pil
-      let  ki = pt `Secp256k1.add` pub
-      if   pil >= Secp256k1._CURVE_Q || ki == Secp256k1._CURVE_ZERO -- negl
+      let  ki  = pt `Secp256k1.add` pub
+           com = W.cmp_vartime pil Secp256k1._CURVE_Q
+      if   com /= LT || ki == Secp256k1._CURVE_ZERO -- negl
       then ckd_pub _xpub (succ i)
       else pure (XPub (X ki ci))
 
@@ -369,7 +373,8 @@
         (il, ci) = BS.splitAt 32 l
         pil = unsafe_roll32 il -- safe due to 512-bit hmac
         ki  = S.from (S.to pil + S.to sec)
-    in  if   pil >= Secp256k1._CURVE_Q || ki == 0 -- negl
+        com = W.cmp_vartime pil Secp256k1._CURVE_Q
+    in  if   com /= LT || W.eq_vartime ki 0 -- negl
         then ckd_priv' ctx _xprv (succ i)
         else XPrv (X ki ci)
   where
@@ -391,7 +396,8 @@
           pil = unsafe_roll32 il -- safe due to 512-bit hmac
       pt <- Secp256k1.mul_wnaf ctx pil
       let  ki = pt `Secp256k1.add` pub
-      if   pil >= Secp256k1._CURVE_Q || ki == Secp256k1._CURVE_ZERO -- negl
+           com = W.cmp_vartime pil Secp256k1._CURVE_Q
+      if   com /= LT || ki == Secp256k1._CURVE_ZERO -- negl
       then ckd_pub' ctx _xpub (succ i)
       else pure (XPub (X ki ci))
 
@@ -413,7 +419,7 @@
   , hd_parent :: !BS.ByteString      -- ^ parent fingerprint
   , hd_child  :: !BS.ByteString      -- ^ index or child number
   }
-  deriving (Eq, Show, Generic)
+  deriving (Show, Generic)
 
 instance Extended HDKey where
   identifier (HDKey ekey _ _ _) = case ekey of
@@ -748,7 +754,9 @@
         Prv -> do
           (b, unsafe_roll32 -> prv) <- BS.uncons key -- safe, guarded keylen
           guard (b == 0)
-          guard (prv > 0 && prv < Secp256k1._CURVE_Q)
+          let com0 = W.gt prv 0
+              com1 = W.lt prv Secp256k1._CURVE_Q
+          guard (C.decide (C.and com0 com1))
           let hd_key = Right (XPrv (X prv cod))
           pure HDKey {..}
       guard (valid_lineage hd)
diff --git a/ppad-bip32.cabal b/ppad-bip32.cabal
--- a/ppad-bip32.cabal
+++ b/ppad-bip32.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ppad-bip32
-version:            0.3.0
+version:            0.3.1
 synopsis:           BIP32 hierarchical deterministic wallets.
 license:            MIT
 license-file:       LICENSE
@@ -37,9 +37,9 @@
       base >= 4.9 && < 5
     , bytestring >= 0.9 && < 0.13
     , ppad-base58 >= 0.2 && < 0.3
-    , ppad-fixed >= 0.1 && < 0.2
+    , ppad-fixed >= 0.1.2 && < 0.2
     , ppad-ripemd160 >= 0.1.3 && < 0.2
-    , ppad-secp256k1 >= 0.5 && < 0.6
+    , ppad-secp256k1 >= 0.5.1 && < 0.6
     , ppad-sha256 >= 0.2.3 && < 0.3
     , ppad-sha512 >= 0.1.3 && < 0.2
 
@@ -59,6 +59,7 @@
     , ppad-base16
     , ppad-base58
     , ppad-bip32
+    , ppad-fixed
     , tasty
     , tasty-hunit
 
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,4 +1,4 @@
-{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-}
+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns -fno-warn-orphans #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main where
@@ -6,8 +6,21 @@
 import Crypto.HDKey.BIP32
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Base16 as B16
+import qualified Data.Word.Wider as W
 import Test.Tasty
 import qualified Test.Tasty.HUnit as H
+
+instance Eq XPrv where
+  x1 == x2 = W.eq_vartime (xprv_key x1) (xprv_key x2)
+          && xprv_cod x1 == xprv_cod x2
+
+instance Eq HDKey where
+  HDKey k1 d1 p1 c1 == HDKey k2 d2 p2 c2 =
+    eqKey k1 k2 && d1 == d2 && p1 == p2 && c1 == c2
+    where
+      eqKey (Left a) (Left b) = a == b
+      eqKey (Right a) (Right b) = a == b
+      eqKey _ _ = False
 
 -- for testing
 xprv_partial :: HDKey -> BS.ByteString
