8
8
9
9
namespace Autarkysoft . Bitcoin . Cryptography . EllipticCurve
10
10
{
11
+ /// <summary>
12
+ /// Context object used to store randomization data for enhanced protection against side-channel leakage.
13
+ /// </summary>
11
14
public class Context
12
15
{
13
- private Context ( )
16
+ /// <summary>
17
+ /// Instantiate a new instance of <see cref="Context"/> with default values.
18
+ /// </summary>
19
+ public Context ( )
14
20
{
21
+ // secp256k1_context_create() -> secp256k1_ecmult_gen_context_build -> secp256k1_ecmult_gen_blind(ctx, NULL)
22
+ // When seed is NULL, reset the initial point and blinding value.
23
+ initial = Point . G . ToPointJacobian ( ) . Negate ( ) ;
24
+ blind = Scalar8x32 . One ;
15
25
}
16
26
17
27
// Blinding values used when computing (n-b)G + bG.
18
- Scalar8x32 blind ; /* -b */
19
- PointJacobian initial ; /* bG */
28
+ Scalar8x32 blind ; // -b
29
+ PointJacobian initial ; // bG
20
30
21
31
private const int ECMULT_GEN_PREC_BITS = 4 ;
22
32
private static int ECMULT_GEN_PREC_N ( int bits ) => ( 256 / bits ) ;
23
33
private static int ECMULT_GEN_PREC_G ( int bits ) => ( 1 << bits ) ;
24
34
25
35
26
- public static Context Create ( )
36
+ /// <summary>
37
+ /// Randomizes this context to provide enhanced protection against side-channel leakage.
38
+ /// </summary>
39
+ /// <remarks>
40
+ /// It is highly recommended to call this method after instantiation and before using it in
41
+ /// computations involving secret keys like signing and public key generation. It is possible
42
+ /// to call this method more than once, and doing so before every few computations involving
43
+ /// secret keys is recommended as a defense-in-depth measure.
44
+ /// </remarks>
45
+ /// <param name="seed32">a 32-byte random seed</param>
46
+ public void Randomize ( ReadOnlySpan < byte > seed32 )
27
47
{
28
- Context ctx = new Context ( ) ;
29
- secp256k1_ecmult_gen_blind ( ctx , null ) ;
30
- return ctx ;
31
- }
32
-
33
- public void secp256k1_context_randomize ( byte [ ] seed32 )
34
- {
35
- secp256k1_ecmult_gen_blind ( this , seed32 ) ;
48
+ GenBlind ( this , seed32 ) ;
36
49
}
37
50
38
51
39
- private static void secp256k1_ecmult_gen_blind ( Context ctx , ReadOnlySpan < byte > seed32 )
52
+ // secp256k1_ecmult_gen_blind
53
+ private static void GenBlind ( Context ctx , ReadOnlySpan < byte > seed32 )
40
54
{
41
55
if ( seed32 == null )
42
56
{
@@ -71,7 +85,7 @@ private static void secp256k1_ecmult_gen_blind(Context ctx, ReadOnlySpan<byte> s
71
85
nonce32 . Clear ( ) ;
72
86
73
87
// The random projection in ctx->initial ensures that gb will have a random projection.
74
- secp256k1_ecmult_gen ( ctx , out PointJacobian gb , b ) ;
88
+ EcMultGen ( ctx , out PointJacobian gb , b ) ;
75
89
ctx . blind = b . Negate ( ) ;
76
90
ctx . initial = gb ;
77
91
b = Scalar8x32 . Zero ;
@@ -91,8 +105,9 @@ private static void secp256k1_ecmult_gen_blind(Context ctx, ReadOnlySpan<byte> s
91
105
// None of the resulting prec group elements have a known scalar, and neither do any of
92
106
// the intermediate sums while computing a*G.
93
107
// The prec values are stored in secp256k1_ecmult_gen_prec_table[i][n_i] = n_i * (PREC_G)^i * G + U_i.
94
- static unsafe void secp256k1_ecmult_gen ( Context ctx , out PointJacobian r , in Scalar8x32 gn )
108
+ private static unsafe void EcMultGen ( Context ctx , out PointJacobian r , in Scalar8x32 gn )
95
109
{
110
+ // secp256k1_ecmult_gen
96
111
int bits = ECMULT_GEN_PREC_BITS ;
97
112
int g = ECMULT_GEN_PREC_G ( bits ) ;
98
113
int n = ECMULT_GEN_PREC_N ( bits ) ;
0 commit comments