From 3c64879ccf1212d2b33d5a764296f93b65563d26 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 7 Jan 2020 00:21:29 +0100 Subject: [PATCH] Optimized ExpMod to operate without recursion --- Ed25519/Extensions.cs | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/Ed25519/Extensions.cs b/Ed25519/Extensions.cs index 20da4b0..39015af 100644 --- a/Ed25519/Extensions.cs +++ b/Ed25519/Extensions.cs @@ -54,20 +54,35 @@ namespace Ed25519 return x; } - internal static BigInteger ExpMod(this BigInteger number, BigInteger exponent, BigInteger modulo) + public static BigInteger ExpMod(this BigInteger number, BigInteger exponent, BigInteger modulo) { - if (exponent.Equals(BigInteger.Zero)) + var numberOperations = (int)Math.Ceiling(BigInteger.Log(exponent, 2)) + 1; + var series = new bool[numberOperations]; + var previousNumber = exponent; + for (var n = 0; n < numberOperations; n++) { - return BigInteger.One; + if (n == 0) + { + series[n] = !exponent.IsEven; + continue; + } + + var next = BigInteger.Divide(previousNumber, Constants.TWO); + series[n] = !next.IsEven; + previousNumber = next; } - var result = BigInteger.Pow(number.ExpMod(exponent / Constants.TWO, modulo), 2).Mod(modulo); - - if (exponent.IsEven) - return result; + var result = BigInteger.One; + for (var n = numberOperations - 2; n >= 0; n--) + { + result = BigInteger.Pow(result, 2).Mod(modulo); + if (series[n]) + { + result *= number; + result = result.Mod(modulo); + } + } - result *= number; - result = result.Mod(modulo); return result; }