Skip to content

Commit

Permalink
Add a new scalar method to set and verity a private key
Browse files Browse the repository at this point in the history
  • Loading branch information
Coding-Enthusiast committed Feb 6, 2024
1 parent cf5b429 commit 1a4fc21
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Src/Autarkysoft.Bitcoin/Cryptography/EllipticCurve/Scalar8x32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,23 @@ public bool IsHigh
}


/// <summary>
/// Creates a new instance of <see cref="Scalar8x32"/> using the given big-endian array
/// and reduces the result modulo curve order (n).
/// Return value indicates validity of the result as a private key.
/// </summary>
/// <param name="data">Array to use</param>
/// <param name="res">Scalar</param>
/// <returns>True if value was non-zero and smaller than curve order; otherwise false</returns>
public static bool TrySetPrivateKey(ReadOnlySpan<byte> data, out Scalar8x32 res)
{
// secp256k1_scalar_set_b32_seckey
res = new Scalar8x32(data, out bool overflow);
Debug.Assert(res.Verify());
return !overflow && !res.IsZero;
}


/// <summary>
/// Multiply a scalar with the multiplicative inverse of 2
/// </summary>
Expand Down
52 changes: 52 additions & 0 deletions Src/Tests/Bitcoin/Cryptography/EllipticCurve/Scalar8x32Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,32 @@ internal static Scalar8x32 CreateRandom(TestRNG rng)
} while (true);
}

/// <summary>
/// random_scalar_order
/// </summary>
private static Scalar8x32 RandomScalarOrder(TestRNG rng)
{
do
{
byte[] b32 = new byte[32];
rng.Rand256(b32);
Scalar8x32 num = new(b32, out bool overflow);
if (!overflow && !num.IsZero)
{
return num;
}
} while (true);
}

/// <summary>
/// random_scalar_order_b32
/// </summary>
private static byte[] RandomScalarOrderB32(TestRNG rng)
{
Scalar8x32 num = RandomScalarOrder(rng);
return num.ToByteArray();
}

// scalar_test(void)
private static unsafe void ScalarTest(TestRNG rng)
{
Expand Down Expand Up @@ -622,6 +648,27 @@ private static unsafe void ScalarTest(TestRNG rng)
}
}


// run_scalar_set_b32_seckey_tests
private static void SetB32SeckeyTests(TestRNG rng)
{
// Usually set_b32 and set_b32_seckey give the same result
Span<byte> b32 = RandomScalarOrderB32(rng);

Scalar8x32 s1 = new(b32, out _);
bool b = Scalar8x32.TrySetPrivateKey(b32, out Scalar8x32 s2);
Assert.True(b);
Assert.True(s1.Equals(s2));

b32.Clear(); // b32.Fill(0);
b = Scalar8x32.TrySetPrivateKey(b32, out _);
Assert.False(b);

b32.Fill(0xff);
b = Scalar8x32.TrySetPrivateKey(b32, out _);
Assert.False(b);
}

[Fact]
public void Libsecp256k1Tests() // run_scalar_tests
{
Expand All @@ -633,6 +680,11 @@ private static unsafe void ScalarTest(TestRNG rng)
ScalarTest(rng);
}

for (int i = 0; i < Count; i++)
{
SetB32SeckeyTests(rng);
}

// Check that the scalar constants secp256k1_scalar_zero and
// secp256k1_scalar_one contain the expected values.
// Note: these are tested in StaticPropTest()
Expand Down

0 comments on commit 1a4fc21

Please sign in to comment.