summary refs log tree commit diff
path: root/crypto/src/math/ec/multiplier/WNafUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/math/ec/multiplier/WNafUtilities.cs')
-rw-r--r--crypto/src/math/ec/multiplier/WNafUtilities.cs91
1 files changed, 88 insertions, 3 deletions
diff --git a/crypto/src/math/ec/multiplier/WNafUtilities.cs b/crypto/src/math/ec/multiplier/WNafUtilities.cs
index 01599d777..65d876449 100644
--- a/crypto/src/math/ec/multiplier/WNafUtilities.cs
+++ b/crypto/src/math/ec/multiplier/WNafUtilities.cs
@@ -361,6 +361,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             return System.Math.Max(2, System.Math.Min(maxWidth, w + 2));
         }
 
+        [Obsolete]
         public static ECPoint MapPointWithPrecomp(ECPoint p, int minWidth, bool includeNegated,
             ECPointMap pointMap)
         {
@@ -374,7 +375,15 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
 
         public static WNafPreCompInfo Precompute(ECPoint p, int minWidth, bool includeNegated)
         {
-            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new WNafCallback(p, minWidth, includeNegated));
+            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME,
+                new PrecomputeCallback(p, minWidth, includeNegated));
+        }
+
+        public static WNafPreCompInfo PrecomputeWithPointMap(ECPoint p, ECPointMap pointMap, WNafPreCompInfo fromWNaf,
+            bool includeNegated)
+        {
+            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME,
+                new PrecomputeWithPointMapCallback(p, pointMap, fromWNaf, includeNegated));
         }
 
         private static byte[] Trim(byte[] a, int length)
@@ -485,14 +494,14 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
             }
         }
 
-        private class WNafCallback
+        private class PrecomputeCallback
             : IPreCompCallback
         {
             private readonly ECPoint m_p;
             private readonly int m_minWidth;
             private readonly bool m_includeNegated;
 
-            internal WNafCallback(ECPoint p, int minWidth, bool includeNegated)
+            internal PrecomputeCallback(ECPoint p, int minWidth, bool includeNegated)
             {
                 this.m_p = p;
                 this.m_minWidth = minWidth;
@@ -665,5 +674,81 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
                 return null != table && table.Length >= reqLen;
             }
         }
+
+        private class PrecomputeWithPointMapCallback
+            : IPreCompCallback
+        {
+            private readonly ECPoint m_point;
+            private readonly ECPointMap m_pointMap;
+            private readonly WNafPreCompInfo m_fromWNaf;
+            private readonly bool m_includeNegated;
+
+            internal PrecomputeWithPointMapCallback(ECPoint point, ECPointMap pointMap, WNafPreCompInfo fromWNaf,
+                bool includeNegated)
+            {
+                this.m_point = point;
+                this.m_pointMap = pointMap;
+                this.m_fromWNaf = fromWNaf;
+                this.m_includeNegated = includeNegated;
+            }
+
+            public PreCompInfo Precompute(PreCompInfo existing)
+            {
+                WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;
+
+                int width = m_fromWNaf.Width;
+                int reqPreCompLen = m_fromWNaf.PreComp.Length;
+
+                if (CheckExisting(existingWNaf, width, reqPreCompLen, m_includeNegated))
+                    return existingWNaf;
+
+                /*
+                 * TODO Ideally this method would support incremental calculation, but given the
+                 * existing use-cases it would be of little-to-no benefit.
+                 */
+                WNafPreCompInfo result = new WNafPreCompInfo();
+
+                ECPoint twiceFrom = m_fromWNaf.Twice;
+                if (null != twiceFrom)
+                {
+                    ECPoint twice = m_pointMap.Map(twiceFrom);
+                    result.Twice = twice;
+                }
+
+                ECPoint[] preCompFrom = m_fromWNaf.PreComp;
+                ECPoint[] preComp = new ECPoint[preCompFrom.Length];
+                for (int i = 0; i < preCompFrom.Length; ++i)
+                {
+                    preComp[i] = m_pointMap.Map(preCompFrom[i]);
+                }
+                result.PreComp = preComp;
+                result.Width = width;
+
+                if (m_includeNegated)
+                {
+                    ECPoint[] preCompNeg = new ECPoint[preComp.Length];
+                    for (int i = 0; i < preCompNeg.Length; ++i)
+                    {
+                        preCompNeg[i] = preComp[i].Negate();
+                    }
+                    result.PreCompNeg = preCompNeg;
+                }
+
+                return result;
+            }
+
+            private bool CheckExisting(WNafPreCompInfo existingWNaf, int width, int reqPreCompLen, bool includeNegated)
+            {
+                return null != existingWNaf
+                    && existingWNaf.Width >= width
+                    && CheckTable(existingWNaf.PreComp, reqPreCompLen)
+                    && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
+            }
+
+            private bool CheckTable(ECPoint[] table, int reqLen)
+            {
+                return null != table && table.Length >= reqLen;
+            }
+        }
     }
 }