Skip to content

Commit 7c9bd67

Browse files
More cleanup and additional verification in UInt256_10x26
1 parent 16c3124 commit 7c9bd67

File tree

1 file changed

+52
-26
lines changed

1 file changed

+52
-26
lines changed

Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/UInt256_10x26.cs

+52-26
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ public UInt256_10x26 Negate(int m)
963963

964964
ulong u0, u1, u2, u3, u4, u5, u6, u7, u8;
965965
uint t9, t1, t0, t2, t3, t4, t5, t6, t7;
966-
const uint M = 0x03FFFFFFU, R0 = 0x03D10U, R1 = 0x0400U;
966+
const uint M = 0x03FFFFFFU, R0 = 0x3D10U, R1 = 0x0400U;
967967

968968
// [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n.
969969
// for 0 <= x <= 9, px is a shorthand for sum(a[i]*b[x-i], i=0..x).
@@ -1276,21 +1276,21 @@ public UInt256_10x26 Negate(int m)
12761276

12771277
/// <summary>
12781278
/// Returns square (x^(2^n)) of this instance.
1279-
/// <para/>Useful to subsequently compute squares (ie. (((x^2)^2)2)^2)
1279+
/// <para/>Useful to compute squares in a for loop (ie. (((x^2)^2)2)^2)
12801280
/// </summary>
12811281
/// <remarks>
12821282
/// Magnitude must be below 8.
12831283
/// Result's magnitude is 1 but is not normalized.
12841284
/// </remarks>
1285-
/// <param name="times">Number of times to repeat sauaring</param>
1285+
/// <param name="times">Number of times to repeat squaring</param>
12861286
/// <returns>Result</returns>
12871287
public UInt256_10x26 Sqr(int times)
12881288
{
12891289
#if DEBUG
1290-
Debug.Assert(magnitude <= 8);
12911290
Verify();
1291+
VerifyMagnitude(magnitude, 8);
12921292
#endif
1293-
const uint M = 0x03FFFFFFU, R0 = 0x03D10U, R1 = 0x0400U;
1293+
const uint M = 0x03FFFFFFU, R0 = 0x3D10U, R1 = 0x0400U;
12941294
uint r0 = b0;
12951295
uint r1 = b1;
12961296
uint r2 = b2;
@@ -1328,7 +1328,7 @@ public UInt256_10x26 Sqr(int times)
13281328
+ (ulong)(r3 * 2) * r6
13291329
+ (ulong)(r4 * 2) * r5;
13301330
// [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
1331-
t9 = (uint)(d & M); d >>= 26;
1331+
t9 = (uint)d & M; d >>= 26;
13321332
Debug.Assert(t9 >> 26 == 0);
13331333
Debug.Assert(d >> 38 == 0);
13341334
// [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
@@ -1348,7 +1348,7 @@ public UInt256_10x26 Sqr(int times)
13481348
Debug.Assert(d >> 37 == 0);
13491349
Debug.Assert(c >> 61 == 0);
13501350
// [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
1351-
t0 = (uint)(c & M); c >>= 26; c += u0 * R1;
1351+
t0 = (uint)c & M; c >>= 26; c += u0 * R1;
13521352
Debug.Assert(t0 >> 26 == 0);
13531353
Debug.Assert(c >> 37 == 0);
13541354
// [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
@@ -1368,7 +1368,7 @@ public UInt256_10x26 Sqr(int times)
13681368
Debug.Assert(d >> 37 == 0);
13691369
Debug.Assert(c >> 63 == 0);
13701370
// [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
1371-
t1 = (uint)(c & M); c >>= 26; c += u1 * R1;
1371+
t1 = (uint)c & M; c >>= 26; c += u1 * R1;
13721372
Debug.Assert(t1 >> 26 == 0);
13731373
Debug.Assert(c >> 38 == 0);
13741374
// [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
@@ -1389,7 +1389,7 @@ public UInt256_10x26 Sqr(int times)
13891389
Debug.Assert(d >> 37 == 0);
13901390
Debug.Assert(c >> 63 == 0);
13911391
// [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
1392-
t2 = (uint)(c & M); c >>= 26; c += u2 * R1;
1392+
t2 = (uint)c & M; c >>= 26; c += u2 * R1;
13931393
Debug.Assert(t2 >> 26 == 0);
13941394
Debug.Assert(c >> 38 == 0);
13951395
// [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
@@ -1408,7 +1408,7 @@ public UInt256_10x26 Sqr(int times)
14081408
Debug.Assert(u3 >> 26 == 0);
14091409
Debug.Assert(d >> 37 == 0);
14101410
// [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
1411-
t3 = (uint)(c & M); c >>= 26; c += u3 * R1;
1411+
t3 = (uint)c & M; c >>= 26; c += u3 * R1;
14121412
Debug.Assert(t3 >> 26 == 0);
14131413
Debug.Assert(c >> 39 == 0);
14141414
// [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
@@ -1428,7 +1428,7 @@ public UInt256_10x26 Sqr(int times)
14281428
Debug.Assert(u4 >> 26 == 0);
14291429
Debug.Assert(d >> 36 == 0);
14301430
// [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
1431-
t4 = (uint)(c & M); c >>= 26; c += u4 * R1;
1431+
t4 = (uint)c & M; c >>= 26; c += u4 * R1;
14321432
Debug.Assert(t4 >> 26 == 0);
14331433
Debug.Assert(c >> 39 == 0);
14341434
// [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
@@ -1447,7 +1447,7 @@ public UInt256_10x26 Sqr(int times)
14471447
Debug.Assert(u5 >> 26 == 0);
14481448
Debug.Assert(d >> 36 == 0);
14491449
// [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
1450-
t5 = (uint)(c & M); c >>= 26; c += u5 * R1;
1450+
t5 = (uint)c & M; c >>= 26; c += u5 * R1;
14511451
Debug.Assert(t5 >> 26 == 0);
14521452
Debug.Assert(c >> 39 == 0);
14531453
// [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
@@ -1467,7 +1467,7 @@ public UInt256_10x26 Sqr(int times)
14671467
Debug.Assert(u6 >> 26 == 0);
14681468
Debug.Assert(d >> 35 == 0);
14691469
// [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
1470-
t6 = (uint)(c & M); c >>= 26; c += u6 * R1;
1470+
t6 = (uint)c & M; c >>= 26; c += u6 * R1;
14711471
Debug.Assert(t6 >> 26 == 0);
14721472
Debug.Assert(c >> 39 == 0);
14731473
// [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
@@ -1487,7 +1487,7 @@ public UInt256_10x26 Sqr(int times)
14871487
Debug.Assert(d >> 32 == 0);
14881488
Debug.Assert(c <= 0x800001703FFFC2F7UL);
14891489
// [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
1490-
t7 = (uint)(c & M); c >>= 26; c += u7 * R1;
1490+
t7 = (uint)c & M; c >>= 26; c += u7 * R1;
14911491
Debug.Assert(t7 >> 26 == 0);
14921492
Debug.Assert(c >> 38 == 0);
14931493
// [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
@@ -1524,15 +1524,15 @@ public UInt256_10x26 Sqr(int times)
15241524
Debug.Assert(r7 >> 26 == 0);
15251525
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
15261526

1527-
r8 = (uint)(c & M); c >>= 26; c += u8 * R1;
1527+
r8 = (uint)c & M; c >>= 26; c += u8 * R1;
15281528
Debug.Assert(r8 >> 26 == 0);
15291529
Debug.Assert(c >> 39 == 0);
15301530
// [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
15311531
// [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
15321532
c += d * R0 + t9;
15331533
Debug.Assert(c >> 45 == 0);
15341534
// [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1535-
r9 = (uint)(c & (M >> 4)); c >>= 22; c += d * (R1 << 4);
1535+
r9 = (uint)c & (M >> 4); c >>= 22; c += d * (R1 << 4);
15361536
Debug.Assert(r9 >> 22 == 0);
15371537
Debug.Assert(c >> 46 == 0);
15381538
// [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
@@ -1542,7 +1542,7 @@ public UInt256_10x26 Sqr(int times)
15421542
d = c * (R0 >> 4) + t0;
15431543
Debug.Assert(d >> 56 == 0);
15441544
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1545-
r0 = (uint)(d & M); d >>= 26;
1545+
r0 = (uint)d & M; d >>= 26;
15461546
Debug.Assert(r0 >> 26 == 0);
15471547
Debug.Assert(d >> 30 == 0);
15481548
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
@@ -1551,7 +1551,7 @@ public UInt256_10x26 Sqr(int times)
15511551
Debug.Assert(d <= 0x10000003FFFFBFUL);
15521552
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
15531553
// [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
1554-
r1 = (uint)(d & M); d >>= 26;
1554+
r1 = (uint)d & M; d >>= 26;
15551555
Debug.Assert(r1 >> 26 == 0);
15561556
Debug.Assert(d >> 27 == 0);
15571557
Debug.Assert(d <= 0x4000000UL);
@@ -1573,12 +1573,21 @@ public UInt256_10x26 Sqr(int times)
15731573

15741574

15751575
/// <summary>
1576-
/// Return square root of this instance if it has a square root, otherwise returns square root of its negation.
1576+
/// Return square root of this instance if it has a square root (returns true),
1577+
/// otherwise returns square root of its negation (returns false).
15771578
/// </summary>
1579+
/// <remarks>
1580+
/// Magnitude must be below 8.
1581+
/// Result will have a magnitude of 1 but will not be normalized.
1582+
/// </remarks>
15781583
/// <param name="result">Square root result</param>
15791584
/// <returns>True if square root existed, otherwise false.</returns>
15801585
public bool Sqrt(out UInt256_10x26 result)
15811586
{
1587+
#if DEBUG
1588+
Verify();
1589+
VerifyMagnitude(magnitude, 8);
1590+
#endif
15821591
// Given that p is congruent to 3 mod 4, we can compute the square root of
15831592
// a mod p as the (p+1)/4'th power of a.
15841593
//
@@ -1588,12 +1597,11 @@ public bool Sqrt(out UInt256_10x26 result)
15881597
// Also because (p+1)/4 is an even number, the computed square root is
15891598
// itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
15901599

1591-
UInt256_10x26 x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
1592-
15931600
// The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
15941601
// { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
15951602
// 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
15961603

1604+
UInt256_10x26 x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
15971605
x2 = Sqr();
15981606
x2 *= this;
15991607

@@ -1637,7 +1645,16 @@ public bool Sqrt(out UInt256_10x26 result)
16371645

16381646
// Check that a square root was actually calculated
16391647
t1 = result.Sqr();
1640-
return t1.Equals(this);
1648+
bool b = t1.Equals(this);
1649+
#if DEBUG
1650+
if (!b)
1651+
{
1652+
t1 = t1.Negate(1);
1653+
t1 = t1.NormalizeVar();
1654+
Debug.Assert(t1.Equals(this));
1655+
}
1656+
#endif
1657+
return b;
16411658
}
16421659

16431660

@@ -1728,13 +1745,21 @@ public UInt256_10x26 Inverse_old()
17281745
/// <summary>
17291746
/// Conditional move. Sets <paramref name="r"/> equal to <paramref name="a"/> if flag is true (=1).
17301747
/// </summary>
1731-
/// <param name="r"></param>
1732-
/// <param name="a"></param>
1748+
/// <remarks>
1749+
/// This method is constant time.
1750+
/// </remarks>
1751+
/// <param name="r">Destination</param>
1752+
/// <param name="a">Source</param>
17331753
/// <param name="flag">Zero or one. Sets <paramref name="r"/> equal to <paramref name="a"/> if flag is one.</param>
1734-
/// <returns>Result</returns>
1754+
/// <returns><paramref name="a"/> if flag was one; otherwise r.</returns>
17351755
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17361756
public static UInt256_10x26 CMov(in UInt256_10x26 r, in UInt256_10x26 a, uint flag)
17371757
{
1758+
#if DEBUG
1759+
r.Verify();
1760+
a.Verify();
1761+
Debug.Assert(flag == 0 || flag == 1);
1762+
#endif
17381763
uint mask0 = flag + ~0U;
17391764
uint mask1 = ~mask0;
17401765
return new UInt256_10x26(
@@ -1783,6 +1808,7 @@ public void Rescale(ref PointJacobian r)
17831808
public UInt256_8x32 ToUInt256_8x32()
17841809
{
17851810
#if DEBUG
1811+
Verify();
17861812
Debug.Assert(isNormalized);
17871813
#endif
17881814
return new UInt256_8x32(this);
@@ -1863,7 +1889,7 @@ public void WriteToSpan(Span<byte> ba)
18631889
/// Assumes both values are normalized.
18641890
/// </summary>
18651891
/// <remarks>
1866-
/// This method is constant time.
1892+
/// This method is not constant time.
18671893
/// </remarks>
18681894
/// <param name="b">Other value to compare to</param>
18691895
/// <returns>1 if this is bigger than <paramref name="b"/>, -1 if smaller and 0 if equal.</returns>

0 commit comments

Comments
 (0)