scalars_near_split_bounds in tests.c don't match their documented construction #1920

issue antvpk opened this issue on August 22, 2026
  1. antvpk commented at 7:23 AM on August 22, 2026: none

    The comment above scalars_near_split_bounds[20] in src/tests.c (array at line 4648, comment ending line 4646 on master) says the values are generated as

    (a*LAMBDA + (ORDER+b)/2) % ORDER,  a in {-2,-1,0,1,2},  b in {-3,-1,1,3}

    The array below it doesn't match. None of the 20 entries equal any value of that formula.

    Example, a=0 b=-3, i.e. (ORDER-3)/2:

    (ORDER-3)/2 = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b209f
    array entry = 0x7fffffffffffffffffffffffffffffffd576e73557a4501ddfe92f46681b209f

    They differ in bits 96-127, and every entry is off in that same 32-bit window.

    Because of this the scalars don't reach the split bounds they're named for. Through secp256k1_scalar_split_lambda they top out around 2^126.2 (|k1|) and 2^126.5 (|k2|), whereas the actual maxima are 2^127.35 and 2^127.11. test_scalar_split still passes and there's no security impact, but the 128-bit boundary these vectors exist to cover is never exercised.

    Repro, needs only the order and lambda:

    n   = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
    lam = 0x5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72
    arr = [
     0xd938a5667f479e3eb5b3c7faefdb37493aa0585cc5ea2367e1b660db0209e6fc,
     0xd938a5667f479e3eb5b3c7faefdb37493aa0585cc5ea2367e1b660db0209e6fd,
     0xd938a5667f479e3eb5b3c7faefdb37493aa0585cc5ea2367e1b660db0209e6fe,
     0xd938a5667f479e3eb5b3c7faefdb37493aa0585cc5ea2367e1b660db0209e6ff,
     0x2c9c52b33fa3cf1f5ad9e3fd77ed9ba5b294b8933722e9a500e698ca4cf7632d,
     0x2c9c52b33fa3cf1f5ad9e3fd77ed9ba5b294b8933722e9a500e698ca4cf7632e,
     0x2c9c52b33fa3cf1f5ad9e3fd77ed9ba5b294b8933722e9a500e698ca4cf7632f,
     0x2c9c52b33fa3cf1f5ad9e3fd77ed9ba5b294b8933722e9a500e698ca4cf76330,
     0x7fffffffffffffffffffffffffffffffd576e73557a4501ddfe92f46681b209f,
     0x7fffffffffffffffffffffffffffffffd576e73557a4501ddfe92f46681b20a0,
     0x7fffffffffffffffffffffffffffffffd576e73557a4501ddfe92f46681b20a1,
     0x7fffffffffffffffffffffffffffffffd576e73557a4501ddfe92f46681b20a2,
     0xd363ad4cc05c30e0a5261c0288126459f85915d77825b696beebc5c2833ede11,
     0xd363ad4cc05c30e0a5261c0288126459f85915d77825b696beebc5c2833ede12,
     0xd363ad4cc05c30e0a5261c0288126459f85915d77825b696beebc5c2833ede13,
     0xd363ad4cc05c30e0a5261c0288126459f85915d77825b696beebc5c2833ede14,
     0x26c75a9980b861c14a4c38051024c8b4704d760ee95e7cd3de1bfdb1ce2c5a42,
     0x26c75a9980b861c14a4c38051024c8b4704d760ee95e7cd3de1bfdb1ce2c5a43,
     0x26c75a9980b861c14a4c38051024c8b4704d760ee95e7cd3de1bfdb1ce2c5a44,
     0x26c75a9980b861c14a4c38051024c8b4704d760ee95e7cd3de1bfdb1ce2c5a45,
    ]
    formula = {(a*lam + (n+b)//2) % n for a in (-2,-1,0,1,2) for b in (-3,-1,1,3)}
    print(sum(v in formula for v in arr), "/ 20 match")   # prints 0 / 20

    Fix: regenerate the array from the formula. The b range {-3,-1,1,3} also never hits the |k2| maximum on its own; that scalar is -LAMBDA + (ORDER-11)/2 (b = -11), so the range needs widening to cover both bounds. The two exact extremes:

    max|k1|:  2*LAMBDA + (ORDER-1)/2  = 0x26c75a9980b861c14a4c38051024c8b4c704d760e95e7cd3de1bfdb1ce2c5a43
    max|k2|:  -LAMBDA + (ORDER-11)/2  = 0x2c9c52b33fa3cf1f5ad9e3fd77ed9ba54b294b893722e9a500e698ca4cf76329

    repro_testvectors.py

Contributors

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-08-23 23:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me