< Summary

Information
Class: Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier.WNafUtilities
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\BouncyCastle\math\ec\multiplier\WNafUtilities.cs
Line coverage
42%
Covered lines: 159
Uncovered lines: 218
Coverable lines: 377
Total lines: 579
Line coverage: 42.1%
Branch coverage
34%
Covered branches: 50
Total branches: 146
Branch coverage: 34.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.cctor()100%1100%
GenerateCompactNaf(...)0%120%
GenerateCompactWindowNaf(...)77.27%2288.37%
GenerateJsf(...)0%260%
GenerateNaf(...)0%80%
GenerateWindowNaf(...)0%200%
GetNafWeight(...)50%285.71%
GetWNafPreCompInfo(...)100%10%
GetWNafPreCompInfo(...)100%10%
GetWindowSize(...)100%1100%
GetWindowSize(...)100%4100%
MapPointWithPrecomp(...)100%10%
Precompute(...)100%1100%
Trim(...)100%10%
Trim(...)100%1100%
ResizeTable(...)100%1100%
.ctor(...)100%10%
Precompute(...)0%80%
.ctor(...)100%1100%
Precompute(...)72.22%3677.31%
CheckExisting(...)33.33%6100%
CheckTable(...)0%20%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\BouncyCastle\math\ec\multiplier\WNafUtilities.cs

#LineLine coverage
 1using System;
 2
 3using Renci.SshNet.Security.Org.BouncyCastle.Utilities;
 4
 5namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier
 6{
 7    internal abstract class WNafUtilities
 8    {
 19        public static readonly string PRECOMP_NAME = "bc_wnaf";
 10
 111        private static readonly int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
 12
 113        private static readonly ECPoint[] EMPTY_POINTS = new ECPoint[0];
 14
 15        public static int[] GenerateCompactNaf(BigInteger k)
 016        {
 017            if ((k.BitLength >> 16) != 0)
 018                throw new ArgumentException("must have bitlength < 2^16", "k");
 019            if (k.SignValue == 0)
 020                return Arrays.EmptyInts;
 21
 022            BigInteger _3k = k.ShiftLeft(1).Add(k);
 23
 024            int bits = _3k.BitLength;
 025            int[] naf = new int[bits >> 1];
 26
 027            BigInteger diff = _3k.Xor(k);
 28
 029            int highBit = bits - 1, length = 0, zeroes = 0;
 030            for (int i = 1; i < highBit; ++i)
 031            {
 032                if (!diff.TestBit(i))
 033                {
 034                    ++zeroes;
 035                    continue;
 36                }
 37
 038                int digit = k.TestBit(i) ? -1 : 1;
 039                naf[length++] = (digit << 16) | zeroes;
 040                zeroes = 1;
 041                ++i;
 042            }
 43
 044            naf[length++] = (1 << 16) | zeroes;
 45
 046            if (naf.Length > length)
 047            {
 048                naf = Trim(naf, length);
 049            }
 50
 051            return naf;
 052        }
 53
 54        public static int[] GenerateCompactWindowNaf(int width, BigInteger k)
 955        {
 956            if (width == 2)
 057            {
 058                return GenerateCompactNaf(k);
 59            }
 60
 961            if (width < 2 || width > 16)
 062                throw new ArgumentException("must be in the range [2, 16]", "width");
 963            if ((k.BitLength >> 16) != 0)
 064                throw new ArgumentException("must have bitlength < 2^16", "k");
 965            if (k.SignValue == 0)
 066                return Arrays.EmptyInts;
 67
 968            int[] wnaf = new int[k.BitLength / width + 1];
 69
 70            // 2^width and a mask and sign bit set accordingly
 971            int pow2 = 1 << width;
 972            int mask = pow2 - 1;
 973            int sign = pow2 >> 1;
 74
 975            bool carry = false;
 1876            int length = 0, pos = 0;
 77
 103578            while (pos <= k.BitLength)
 102679            {
 102680                if (k.TestBit(pos) == carry)
 50581                {
 50582                    ++pos;
 50583                    continue;
 84                }
 85
 52186                k = k.ShiftRight(pos);
 87
 52188                int digit = k.IntValue & mask;
 52189                if (carry)
 26490                {
 26491                    ++digit;
 26492                }
 93
 52194                carry = (digit & sign) != 0;
 52195                if (carry)
 26496                {
 26497                    digit -= pow2;
 26498                }
 99
 521100                int zeroes = length > 0 ? pos - 1 : pos;
 521101                wnaf[length++] = (digit << 16) | zeroes;
 521102                pos = width;
 521103            }
 104
 105            // Reduce the WNAF array to its actual length
 9106            if (wnaf.Length > length)
 9107            {
 9108                wnaf = Trim(wnaf, length);
 9109            }
 110
 9111            return wnaf;
 9112        }
 113
 114        public static byte[] GenerateJsf(BigInteger g, BigInteger h)
 0115        {
 0116            int digits = System.Math.Max(g.BitLength, h.BitLength) + 1;
 0117            byte[] jsf = new byte[digits];
 118
 0119            BigInteger k0 = g, k1 = h;
 0120            int j = 0, d0 = 0, d1 = 0;
 121
 0122            int offset = 0;
 0123            while ((d0 | d1) != 0 || k0.BitLength > offset || k1.BitLength > offset)
 0124            {
 0125                int n0 = ((int)((uint)k0.IntValue >> offset) + d0) & 7;
 0126                int n1 = ((int)((uint)k1.IntValue >> offset) + d1) & 7;
 127
 0128                int u0 = n0 & 1;
 0129                if (u0 != 0)
 0130                {
 0131                    u0 -= (n0 & 2);
 0132                    if ((n0 + u0) == 4 && (n1 & 3) == 2)
 0133                    {
 0134                        u0 = -u0;
 0135                    }
 0136                }
 137
 0138                int u1 = n1 & 1;
 0139                if (u1 != 0)
 0140                {
 0141                    u1 -= (n1 & 2);
 0142                    if ((n1 + u1) == 4 && (n0 & 3) == 2)
 0143                    {
 0144                        u1 = -u1;
 0145                    }
 0146                }
 147
 0148                if ((d0 << 1) == 1 + u0)
 0149                {
 0150                    d0 ^= 1;
 0151                }
 0152                if ((d1 << 1) == 1 + u1)
 0153                {
 0154                    d1 ^= 1;
 0155                }
 156
 0157                if (++offset == 30)
 0158                {
 0159                    offset = 0;
 0160                    k0 = k0.ShiftRight(30);
 0161                    k1 = k1.ShiftRight(30);
 0162                }
 163
 0164                jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF));
 0165            }
 166
 167            // Reduce the JSF array to its actual length
 0168            if (jsf.Length > j)
 0169            {
 0170                jsf = Trim(jsf, j);
 0171            }
 172
 0173            return jsf;
 0174        }
 175
 176        public static byte[] GenerateNaf(BigInteger k)
 0177        {
 0178            if (k.SignValue == 0)
 0179                return Arrays.EmptyBytes;
 180
 0181            BigInteger _3k = k.ShiftLeft(1).Add(k);
 182
 0183            int digits = _3k.BitLength - 1;
 0184            byte[] naf = new byte[digits];
 185
 0186            BigInteger diff = _3k.Xor(k);
 187
 0188            for (int i = 1; i < digits; ++i)
 0189            {
 0190                if (diff.TestBit(i))
 0191                {
 0192                    naf[i - 1] = (byte)(k.TestBit(i) ? -1 : 1);
 0193                    ++i;
 0194                }
 0195            }
 196
 0197            naf[digits - 1] = 1;
 198
 0199            return naf;
 0200        }
 201
 202        /**
 203         * Computes the Window NAF (non-adjacent Form) of an integer.
 204         * @param width The width <code>w</code> of the Window NAF. The width is
 205         * defined as the minimal number <code>w</code>, such that for any
 206         * <code>w</code> consecutive digits in the resulting representation, at
 207         * most one is non-zero.
 208         * @param k The integer of which the Window NAF is computed.
 209         * @return The Window NAF of the given width, such that the following holds:
 210         * <code>k = &amp;sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
 211         * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
 212         * returned <code>byte[]</code>.
 213         */
 214        public static byte[] GenerateWindowNaf(int width, BigInteger k)
 0215        {
 0216            if (width == 2)
 0217            {
 0218                return GenerateNaf(k);
 219            }
 220
 0221            if (width < 2 || width > 8)
 0222                throw new ArgumentException("must be in the range [2, 8]", "width");
 0223            if (k.SignValue == 0)
 0224                return Arrays.EmptyBytes;
 225
 0226            byte[] wnaf = new byte[k.BitLength + 1];
 227
 228            // 2^width and a mask and sign bit set accordingly
 0229            int pow2 = 1 << width;
 0230            int mask = pow2 - 1;
 0231            int sign = pow2 >> 1;
 232
 0233            bool carry = false;
 0234            int length = 0, pos = 0;
 235
 0236            while (pos <= k.BitLength)
 0237            {
 0238                if (k.TestBit(pos) == carry)
 0239                {
 0240                    ++pos;
 0241                    continue;
 242                }
 243
 0244                k = k.ShiftRight(pos);
 245
 0246                int digit = k.IntValue & mask;
 0247                if (carry)
 0248                {
 0249                    ++digit;
 0250                }
 251
 0252                carry = (digit & sign) != 0;
 0253                if (carry)
 0254                {
 0255                    digit -= pow2;
 0256                }
 257
 0258                length += (length > 0) ? pos - 1 : pos;
 0259                wnaf[length++] = (byte)digit;
 0260                pos = width;
 0261            }
 262
 263            // Reduce the WNAF array to its actual length
 0264            if (wnaf.Length > length)
 0265            {
 0266                wnaf = Trim(wnaf, length);
 0267            }
 268
 0269            return wnaf;
 0270        }
 271
 272        public static int GetNafWeight(BigInteger k)
 9273        {
 9274            if (k.SignValue == 0)
 0275                return 0;
 276
 9277            BigInteger _3k = k.ShiftLeft(1).Add(k);
 9278            BigInteger diff = _3k.Xor(k);
 279
 9280            return diff.BitCount;
 9281        }
 282
 283        public static WNafPreCompInfo GetWNafPreCompInfo(ECPoint p)
 0284        {
 0285            return GetWNafPreCompInfo(p.Curve.GetPreCompInfo(p, PRECOMP_NAME));
 0286        }
 287
 288        public static WNafPreCompInfo GetWNafPreCompInfo(PreCompInfo preCompInfo)
 0289        {
 0290            return preCompInfo as WNafPreCompInfo;
 0291        }
 292
 293        /**
 294         * Determine window width to use for a scalar multiplication of the given size.
 295         *
 296         * @param bits the bit-length of the scalar to multiply by
 297         * @return the window size to use
 298         */
 299        public static int GetWindowSize(int bits)
 9300        {
 9301            return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS);
 9302        }
 303
 304        /**
 305         * Determine window width to use for a scalar multiplication of the given size.
 306         *
 307         * @param bits the bit-length of the scalar to multiply by
 308         * @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
 309         * @return the window size to use
 310         */
 311        public static int GetWindowSize(int bits, int[] windowSizeCutoffs)
 9312        {
 9313            int w = 0;
 75314            for (; w < windowSizeCutoffs.Length; ++w)
 42315            {
 42316                if (bits < windowSizeCutoffs[w])
 9317                {
 9318                    break;
 319                }
 33320            }
 9321            return w + 2;
 9322        }
 323
 324        public static ECPoint MapPointWithPrecomp(ECPoint p, int width, bool includeNegated,
 325            ECPointMap pointMap)
 0326        {
 0327            ECCurve c = p.Curve;
 0328            WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated);
 329
 0330            ECPoint q = pointMap.Map(p);
 0331            c.Precompute(q, PRECOMP_NAME, new MapPointCallback(wnafPreCompP, includeNegated, pointMap));
 0332            return q;
 0333        }
 334
 335        public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated)
 9336        {
 9337            return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new WNafCallback(p, width, includeNegated));
 9338        }
 339
 340        private static byte[] Trim(byte[] a, int length)
 0341        {
 0342            byte[] result = new byte[length];
 0343            Array.Copy(a, 0, result, 0, result.Length);
 0344            return result;
 0345        }
 346
 347        private static int[] Trim(int[] a, int length)
 9348        {
 9349            int[] result = new int[length];
 9350            Array.Copy(a, 0, result, 0, result.Length);
 9351            return result;
 9352        }
 353
 354        private static ECPoint[] ResizeTable(ECPoint[] a, int length)
 9355        {
 9356            ECPoint[] result = new ECPoint[length];
 9357            Array.Copy(a, 0, result, 0, a.Length);
 9358            return result;
 9359        }
 360
 361        private class MapPointCallback
 362            : IPreCompCallback
 363        {
 364            private readonly WNafPreCompInfo m_wnafPreCompP;
 365            private readonly bool m_includeNegated;
 366            private readonly ECPointMap m_pointMap;
 367
 0368            internal MapPointCallback(WNafPreCompInfo wnafPreCompP, bool includeNegated, ECPointMap pointMap)
 0369            {
 0370                this.m_wnafPreCompP = wnafPreCompP;
 0371                this.m_includeNegated = includeNegated;
 0372                this.m_pointMap = pointMap;
 0373            }
 374
 375            public PreCompInfo Precompute(PreCompInfo existing)
 0376            {
 0377                WNafPreCompInfo result = new WNafPreCompInfo();
 378
 0379                ECPoint twiceP = m_wnafPreCompP.Twice;
 0380                if (twiceP != null)
 0381                {
 0382                    ECPoint twiceQ = m_pointMap.Map(twiceP);
 0383                    result.Twice = twiceQ;
 0384                }
 385
 0386                ECPoint[] preCompP = m_wnafPreCompP.PreComp;
 0387                ECPoint[] preCompQ = new ECPoint[preCompP.Length];
 0388                for (int i = 0; i < preCompP.Length; ++i)
 0389                {
 0390                    preCompQ[i] = m_pointMap.Map(preCompP[i]);
 0391                }
 0392                result.PreComp = preCompQ;
 393
 0394                if (m_includeNegated)
 0395                {
 0396                    ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length];
 0397                    for (int i = 0; i < preCompNegQ.Length; ++i)
 0398                    {
 0399                        preCompNegQ[i] = preCompQ[i].Negate();
 0400                    }
 0401                    result.PreCompNeg = preCompNegQ;
 0402                }
 403
 0404                return result;
 0405            }
 406        }
 407
 408        private class WNafCallback
 409            : IPreCompCallback
 410        {
 411            private readonly ECPoint m_p;
 412            private readonly int m_width;
 413            private readonly bool m_includeNegated;
 414
 9415            internal WNafCallback(ECPoint p, int width, bool includeNegated)
 9416            {
 9417                this.m_p = p;
 9418                this.m_width = width;
 9419                this.m_includeNegated = includeNegated;
 9420            }
 421
 422            public PreCompInfo Precompute(PreCompInfo existing)
 9423            {
 9424                WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;
 425
 9426                int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2);
 427
 9428                if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated))
 0429                    return existingWNaf;
 430
 9431                ECCurve c = m_p.Curve;
 18432                ECPoint[] preComp = null, preCompNeg = null;
 9433                ECPoint twiceP = null;
 434
 9435                if (existingWNaf != null)
 0436                {
 0437                    preComp = existingWNaf.PreComp;
 0438                    preCompNeg = existingWNaf.PreCompNeg;
 0439                    twiceP = existingWNaf.Twice;
 0440                }
 441
 9442                int iniPreCompLen = 0;
 9443                if (preComp == null)
 9444                {
 9445                    preComp = EMPTY_POINTS;
 9446                }
 447                else
 0448                {
 0449                    iniPreCompLen = preComp.Length;
 0450                }
 451
 9452                if (iniPreCompLen < reqPreCompLen)
 9453                {
 9454                    preComp = WNafUtilities.ResizeTable(preComp, reqPreCompLen);
 455
 9456                    if (reqPreCompLen == 1)
 0457                    {
 0458                        preComp[0] = m_p.Normalize();
 0459                    }
 460                    else
 9461                    {
 9462                        int curPreCompLen = iniPreCompLen;
 9463                        if (curPreCompLen == 0)
 9464                        {
 9465                            preComp[0] = m_p;
 9466                            curPreCompLen = 1;
 9467                        }
 468
 9469                        ECFieldElement iso = null;
 470
 9471                        if (reqPreCompLen == 2)
 0472                        {
 0473                            preComp[1] = m_p.ThreeTimes();
 0474                        }
 475                        else
 9476                        {
 18477                            ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1];
 9478                            if (isoTwiceP == null)
 9479                            {
 9480                                isoTwiceP = preComp[0].Twice();
 9481                                twiceP = isoTwiceP;
 482
 483                                /*
 484                                 * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
 485                                 * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
 486                                 * also requires scaling the initial point's X, Y coordinates, and reversing the
 487                                 * isomorphism as part of the subsequent normalization.
 488                                 *
 489                                 *  NOTE: The correctness of this optimization depends on:
 490                                 *      1) additions do not use the curve's A, B coefficients.
 491                                 *      2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
 492                                 */
 9493                                if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
 9494                                {
 9495                                    switch (c.CoordinateSystem)
 496                                    {
 497                                    case ECCurve.COORD_JACOBIAN:
 498                                    case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
 499                                    case ECCurve.COORD_JACOBIAN_MODIFIED:
 9500                                    {
 9501                                        iso = twiceP.GetZCoord(0);
 9502                                        isoTwiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(),
 9503                                            twiceP.YCoord.ToBigInteger());
 504
 18505                                        ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso);
 9506                                        last = last.ScaleX(iso2).ScaleY(iso3);
 507
 9508                                        if (iniPreCompLen == 0)
 9509                                        {
 9510                                            preComp[0] = last;
 9511                                        }
 9512                                        break;
 513                                    }
 514                                    }
 9515                                }
 9516                            }
 517
 120518                            while (curPreCompLen < reqPreCompLen)
 111519                            {
 520                                /*
 521                                 * Compute the new ECPoints for the precomputation array. The values 1, 3,
 522                                 * 5, ..., 2^(width-1)-1 times p are computed
 523                                 */
 111524                                preComp[curPreCompLen++] = last = last.Add(isoTwiceP);
 111525                            }
 9526                        }
 527
 528                        /*
 529                         * Having oft-used operands in affine form makes operations faster.
 530                         */
 9531                        c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
 9532                    }
 9533                }
 534
 9535                if (m_includeNegated)
 9536                {
 537                    int pos;
 9538                    if (preCompNeg == null)
 9539                    {
 9540                        pos = 0;
 9541                        preCompNeg = new ECPoint[reqPreCompLen];
 9542                    }
 543                    else
 0544                    {
 0545                        pos = preCompNeg.Length;
 0546                        if (pos < reqPreCompLen)
 0547                        {
 0548                            preCompNeg = WNafUtilities.ResizeTable(preCompNeg, reqPreCompLen);
 0549                        }
 0550                    }
 551
 129552                    while (pos < reqPreCompLen)
 120553                    {
 120554                        preCompNeg[pos] = preComp[pos].Negate();
 120555                        ++pos;
 120556                    }
 9557                }
 558
 9559                WNafPreCompInfo result = new WNafPreCompInfo();
 9560                result.PreComp = preComp;
 9561                result.PreCompNeg = preCompNeg;
 9562                result.Twice = twiceP;
 9563                return result;
 9564            }
 565
 566            private bool CheckExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, bool includeNegated)
 9567            {
 9568                return existingWNaf != null
 9569                    && CheckTable(existingWNaf.PreComp, reqPreCompLen)
 9570                    && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
 9571            }
 572
 573            private bool CheckTable(ECPoint[] table, int reqLen)
 0574            {
 0575                return table != null && table.Length >= reqLen;
 0576            }
 577        }
 578    }
 579}

Methods/Properties

.cctor()
GenerateCompactNaf(Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger)
GenerateCompactWindowNaf(System.Int32,Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger)
GenerateJsf(Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger,Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger)
GenerateNaf(Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger)
GenerateWindowNaf(System.Int32,Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger)
GetNafWeight(Renci.SshNet.Security.Org.BouncyCastle.Math.BigInteger)
GetWNafPreCompInfo(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPoint)
GetWNafPreCompInfo(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)
GetWindowSize(System.Int32)
GetWindowSize(System.Int32,System.Int32[])
MapPointWithPrecomp(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPoint,System.Int32,System.Boolean,Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPointMap)
Precompute(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPoint,System.Int32,System.Boolean)
Trim(System.Byte[],System.Int32)
Trim(System.Int32[],System.Int32)
ResizeTable(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPoint[],System.Int32)
.ctor(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo,System.Boolean,Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPointMap)
Precompute(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)
.ctor(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPoint,System.Int32,System.Boolean)
Precompute(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)
CheckExisting(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo,System.Int32,System.Boolean)
CheckTable(Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECPoint[],System.Int32)