Skip to content

Commit acab934

Browse files
roconnor-blockstreamsipa
authored andcommitted
Detailed comments for secp256k1_scalar_split_lambda
1 parent 76ed922 commit acab934

File tree

4 files changed

+154
-35
lines changed

4 files changed

+154
-35
lines changed

src/scalar.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@ static void secp256k1_scalar_order_get_num(secp256k1_num *r);
103103
static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b);
104104

105105
#ifdef USE_ENDOMORPHISM
106-
/** Find r1 and r2 such that r1+r2*2^128 = a. */
107-
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a);
108-
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */
109-
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a);
106+
/** Find r1 and r2 such that r1+r2*2^128 = k. */
107+
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
108+
/** Find r1 and r2 such that r1+r2*lambda = k,
109+
* where r1 and r2 or their negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). */
110+
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
110111
#endif
111112

112113
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */

src/scalar_4x64_impl.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -913,13 +913,13 @@ static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a)
913913
}
914914

915915
#ifdef USE_ENDOMORPHISM
916-
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
917-
r1->d[0] = a->d[0];
918-
r1->d[1] = a->d[1];
916+
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
917+
r1->d[0] = k->d[0];
918+
r1->d[1] = k->d[1];
919919
r1->d[2] = 0;
920920
r1->d[3] = 0;
921-
r2->d[0] = a->d[2];
922-
r2->d[1] = a->d[3];
921+
r2->d[0] = k->d[2];
922+
r2->d[1] = k->d[3];
923923
r2->d[2] = 0;
924924
r2->d[3] = 0;
925925
}

src/scalar_8x32_impl.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -673,19 +673,19 @@ static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a)
673673
}
674674

675675
#ifdef USE_ENDOMORPHISM
676-
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
677-
r1->d[0] = a->d[0];
678-
r1->d[1] = a->d[1];
679-
r1->d[2] = a->d[2];
680-
r1->d[3] = a->d[3];
676+
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
677+
r1->d[0] = k->d[0];
678+
r1->d[1] = k->d[1];
679+
r1->d[2] = k->d[2];
680+
r1->d[3] = k->d[3];
681681
r1->d[4] = 0;
682682
r1->d[5] = 0;
683683
r1->d[6] = 0;
684684
r1->d[7] = 0;
685-
r2->d[0] = a->d[4];
686-
r2->d[1] = a->d[5];
687-
r2->d[2] = a->d[6];
688-
r2->d[3] = a->d[7];
685+
r2->d[0] = k->d[4];
686+
r2->d[1] = k->d[5];
687+
r2->d[2] = k->d[6];
688+
r2->d[3] = k->d[7];
689689
r2->d[4] = 0;
690690
r2->d[5] = 0;
691691
r2->d[6] = 0;

src/scalar_impl.h

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -279,19 +279,31 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
279279
* lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
280280
* 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72}
281281
*
282-
* "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
283-
* (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
284-
* and k2 have a small size.
285-
* It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are:
282+
* Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and
283+
* beta^3 == 1 mod p, where n is the curve order and p is the field order.
284+
*
285+
* Futhermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are
286+
* roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p.
287+
* (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.)
288+
*
289+
* Let l = -1/2 + i*sqrt(3)/2, the complex root of X^2 + X + 1. We can define a ring
290+
* homomorphism phi : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. The kernel of phi
291+
* is a lattice over Z[l] (considering Z[l] as a Z-module). This lattice is generated by a
292+
* reduced basis {a1 + b1*l, a2 + b2*l} where
286293
*
287294
* - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
288295
* - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3}
289296
* - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8}
290297
* - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
291298
*
292-
* The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives
299+
* "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
300+
* (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
301+
* and k2 have a small size.
302+
*
303+
* The algorithm computes c1 = round(b2 * k / n) and c2 = round((-b1) * k / n), and gives
293304
* k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and
294-
* compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2.
305+
* compute k - k2 * lambda (mod n) which is equivalent to k1 (mod n), avoiding the need for
306+
* the constants a1 and a2.
295307
*
296308
* g1, g2 are precomputed constants used to replace division with a rounded multiplication
297309
* when decomposing the scalar for an endomorphism-based point multiplication.
@@ -303,16 +315,122 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
303315
* Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
304316
* Section 4.3 (here we use a somewhat higher-precision estimate):
305317
* d = a1*b2 - b1*a2
306-
* g1 = round((2^384)*b2/d)
307-
* g2 = round((2^384)*(-b1)/d)
318+
* g1 = round(2^384 * b2/d)
319+
* g2 = round(2^384 * (-b1)/d)
320+
*
321+
* (Note that d is also equal to the curve order, n, here because [a1,b1] and [a2,b2]
322+
* can be found as outputs of the Extended Euclidean Algorithm on inputs n and lambda).
323+
*
324+
* The function below splits k into r1 and r2, such that
325+
* - r1 + lambda * r2 == k (mod n)
326+
* - either r1 < 2^128 or -r1 mod n < 2^128
327+
* - either r2 < 2^128 or -r2 mod n < 2^128
328+
*
329+
* Proof.
330+
*
331+
* Let
332+
* - epsilon1 = 2^256 * |g1/2^384 - b2/d|
333+
* - epsilon2 = 2^256 * |g2/2^384 - (-b1)/d|
334+
* - c1 = round(k*g1/2^384)
335+
* - c2 = round(k*g2/2^384)
336+
*
337+
* Lemma 1: |c1 - k*b2/d| < 2^-1 + epsilon1
308338
*
309-
* (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
310-
* as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
339+
* |c1 - k*b2/d|
340+
* =
341+
* |c1 - k*g1/2^384 + k*g1/2^384 - k*b2/d|
342+
* <= {triangle inequality}
343+
* |c1 - k*g1/2^384| + |k*g1/2^384 - k*b2/d|
344+
* =
345+
* |c1 - k*g1/2^384| + k*|g1/2^384 - b2/d|
346+
* < {rounding in c1 and 0 <= k < 2^256}
347+
* 2^-1 + 2^256 * |g1/2^384 - b2/d|
348+
* = {definition of epsilon1}
349+
* 2^-1 + epsilon1
311350
*
312-
* The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order).
351+
* Lemma 2: |c2 - k*(-b1)/d| < 2^-1 + epsilon2
352+
*
353+
* |c2 - k*(-b1)/d|
354+
* =
355+
* |c2 - k*g2/2^384 + k*g2/2^384 - k*(-b1)/d|
356+
* <= {triangle inequality}
357+
* |c2 - k*g2/2^384| + |k*g2/2^384 - k*(-b1)/d|
358+
* =
359+
* |c2 - k*g2/2^384| + k*|g2/2^384 - (-b1)/d|
360+
* < {rounding in c2 and 0 <= k < 2^256}
361+
* 2^-1 + 2^256 * |g2/2^384 - (-b1)/d|
362+
* = {definition of epsilon2}
363+
* 2^-1 + epsilon2
364+
*
365+
* Let
366+
* - k1 = k - c1*a1 - c2*a2
367+
* - k2 = - c1*b1 - c2*b2
368+
*
369+
* Lemma 3: |k1| < (a1 + a2 + 1)/2 < 2^128
370+
*
371+
* |k1|
372+
* = {definition of k1}
373+
* |k - c1*a1 - c2*a2|
374+
* = {(a1*b2 - b1*a2)/n = 1}
375+
* |k*(a1*b2 - b1*a2)/n - c1*a1 - c2*a2|
376+
* =
377+
* |a1*(k*b2/n - c1) + a2*(k*(-b1)/n - c2)|
378+
* <= {triangle inequality}
379+
* a1*|k*b2/n - c1| + a2*|k*(-b1)/n - c2|
380+
* < {Lemma 1 and Lemma 2}
381+
* a1*(2^-1 + epslion1) + a2*(2^-1 + epsilon2)
382+
* < {rounding up to an integer}
383+
* (a1 + a2 + 1)/2
384+
* < {rounding up to a power of 2}
385+
* 2^128
386+
*
387+
* Lemma 4: |k2| < (-b1 + b2)/2 + 1 < 2^128
388+
*
389+
* |k2|
390+
* = {definition of k2}
391+
* |- c1*a1 - c2*a2|
392+
* = {(b1*b2 - b1*b2)/n = 0}
393+
* |k*(b1*b2 - b1*b2)/n - c1*b1 - c2*b2|
394+
* =
395+
* |b1*(k*b2/n - c1) + b2*(k*(-b1)/n - c2)|
396+
* <= {triangle inequality}
397+
* (-b1)*|k*b2/n - c1| + b2*|k*(-b1)/n - c2|
398+
* < {Lemma 1 and Lemma 2}
399+
* (-b1)*(2^-1 + epslion1) + b2*(2^-1 + epsilon2)
400+
* < {rounding up to an integer}
401+
* (-b1 + b2)/2 + 1
402+
* < {rounding up to a power of 2}
403+
* 2^128
404+
*
405+
* Let
406+
* - r2 = k2 mod n
407+
* - r1 = k - r2*lambda mod n.
408+
*
409+
* Notice that r1 is defined such that r1 + r2 * lambda == k (mod n).
410+
*
411+
* Lemma 5: r1 == k1 mod n.
412+
*
413+
* r1
414+
* == {definition of r1 and r2}
415+
* k - k2*lambda
416+
* == {definition of k2}
417+
* k - (- c1*b1 - c2*b2)*lambda
418+
* ==
419+
* k + c1*b1*lambda + c2*b2*lambda
420+
* == {a1 + b1*lambda == 0 mod n and a2 + b2*lambda == 0 mod n}
421+
* k - c1*a1 - c2*a2
422+
* == {definition of k1}
423+
* k1
424+
*
425+
* From Lemma 3, Lemma 4, Lemma 5 and the definition of r2, we can conclude that
426+
*
427+
* - either r1 < 2^128 or -r1 mod n < 2^128
428+
* - either r2 < 2^128 or -r2 mod n < 2^128.
429+
*
430+
* Q.E.D.
313431
*/
314432

315-
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
433+
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
316434
secp256k1_scalar c1, c2;
317435
static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST(
318436
0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL,
@@ -334,16 +452,16 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
334452
0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C4UL,
335453
0x221208ACUL, 0x9DF506C6UL, 0x1571B4AEUL, 0x8AC47F71UL
336454
);
337-
VERIFY_CHECK(r1 != a);
338-
VERIFY_CHECK(r2 != a);
455+
VERIFY_CHECK(r1 != k);
456+
VERIFY_CHECK(r2 != k);
339457
/* these _var calls are constant time since the shift amount is constant */
340-
secp256k1_scalar_mul_shift_var(&c1, a, &g1, 384);
341-
secp256k1_scalar_mul_shift_var(&c2, a, &g2, 384);
458+
secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384);
459+
secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384);
342460
secp256k1_scalar_mul(&c1, &c1, &minus_b1);
343461
secp256k1_scalar_mul(&c2, &c2, &minus_b2);
344462
secp256k1_scalar_add(r2, &c1, &c2);
345463
secp256k1_scalar_mul(r1, r2, &minus_lambda);
346-
secp256k1_scalar_add(r1, r1, a);
464+
secp256k1_scalar_add(r1, r1, k);
347465
}
348466
#endif
349467
#endif

0 commit comments

Comments
 (0)