This commit is contained in:
2020-07-09 08:50:24 +08:00
parent 13d25f4707
commit c523462b82
1818 changed files with 174940 additions and 582 deletions

View File

@@ -0,0 +1,28 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
namespace Org.BouncyCastle.Math.EC.Multiplier
{
public abstract class AbstractECMultiplier
: ECMultiplier
{
public virtual ECPoint Multiply(ECPoint p, BigInteger k)
{
int sign = k.SignValue;
if (sign == 0 || p.IsInfinity)
return p.Curve.Infinity;
ECPoint positive = MultiplyPositive(p, k.Abs());
ECPoint result = sign > 0 ? positive : positive.Negate();
/*
* Although the various multipliers ought not to produce invalid output under normal
* circumstances, a final check here is advised to guard against fault attacks.
*/
return ECAlgorithms.ValidatePoint(result);
}
protected abstract ECPoint MultiplyPositive(ECPoint p, BigInteger k);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b4f8520b47bd4dfb8a6863a8adfe63d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Interface for classes encapsulating a point multiplication algorithm
* for <code>ECPoint</code>s.
*/
public interface ECMultiplier
{
/**
* Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
* <code>p</code> is added <code>k</code> times to itself.
* @param p The <code>ECPoint</code> to be multiplied.
* @param k The factor by which <code>p</code> is multiplied.
* @return <code>p</code> multiplied by <code>k</code>.
*/
ECPoint Multiply(ECPoint p, BigInteger k);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 882631c68fada416ba901b77fbf418d4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
public class FixedPointCombMultiplier
: AbstractECMultiplier
{
protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
{
ECCurve c = p.Curve;
int size = FixedPointUtilities.GetCombSize(c);
if (k.BitLength > size)
{
/*
* TODO The comb works best when the scalars are less than the (possibly unknown) order.
* Still, if we want to handle larger scalars, we could allow customization of the comb
* size, or alternatively we could deal with the 'extra' bits either by running the comb
* multiple times as necessary, or by using an alternative multiplier as prelude.
*/
throw new InvalidOperationException("fixed-point comb doesn't support scalars larger than the curve order");
}
int minWidth = GetWidthForCombSize(size);
FixedPointPreCompInfo info = FixedPointUtilities.Precompute(p, minWidth);
ECPoint[] lookupTable = info.PreComp;
int width = info.Width;
int d = (size + width - 1) / width;
ECPoint R = c.Infinity;
int top = d * width - 1;
for (int i = 0; i < d; ++i)
{
int index = 0;
for (int j = top - i; j >= 0; j -= d)
{
index <<= 1;
if (k.TestBit(j))
{
index |= 1;
}
}
R = R.TwicePlus(lookupTable[index]);
}
return R;
}
protected virtual int GetWidthForCombSize(int combSize)
{
return combSize > 257 ? 6 : 5;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6e1324f7275a3452fbb142b00c435077
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class holding precomputation data for fixed-point multiplications.
*/
public class FixedPointPreCompInfo
: PreCompInfo
{
/**
* Array holding the precomputed <code>ECPoint</code>s used for a fixed
* point multiplication.
*/
protected ECPoint[] m_preComp = null;
/**
* The width used for the precomputation. If a larger width precomputation
* is already available this may be larger than was requested, so calling
* code should refer to the actual width.
*/
protected int m_width = -1;
public virtual ECPoint[] PreComp
{
get { return m_preComp; }
set { this.m_preComp = value; }
}
public virtual int Width
{
get { return m_width; }
set { this.m_width = value; }
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3a5cd33f0a1643d3ac754c68feb0fc1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
public class FixedPointUtilities
{
public static readonly string PRECOMP_NAME = "bc_fixed_point";
public static int GetCombSize(ECCurve c)
{
BigInteger order = c.Order;
return order == null ? c.FieldSize + 1 : order.BitLength;
}
public static FixedPointPreCompInfo GetFixedPointPreCompInfo(PreCompInfo preCompInfo)
{
if ((preCompInfo != null) && (preCompInfo is FixedPointPreCompInfo))
{
return (FixedPointPreCompInfo)preCompInfo;
}
return new FixedPointPreCompInfo();
}
public static FixedPointPreCompInfo Precompute(ECPoint p, int minWidth)
{
ECCurve c = p.Curve;
int n = 1 << minWidth;
FixedPointPreCompInfo info = GetFixedPointPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME));
ECPoint[] lookupTable = info.PreComp;
if (lookupTable == null || lookupTable.Length < n)
{
int bits = GetCombSize(c);
int d = (bits + minWidth - 1) / minWidth;
ECPoint[] pow2Table = new ECPoint[minWidth];
pow2Table[0] = p;
for (int i = 1; i < minWidth; ++i)
{
pow2Table[i] = pow2Table[i - 1].TimesPow2(d);
}
c.NormalizeAll(pow2Table);
lookupTable = new ECPoint[n];
lookupTable[0] = c.Infinity;
for (int bit = minWidth - 1; bit >= 0; --bit)
{
ECPoint pow2 = pow2Table[bit];
int step = 1 << bit;
for (int i = step; i < n; i += (step << 1))
{
lookupTable[i] = lookupTable[i - step].Add(pow2);
}
}
c.NormalizeAll(lookupTable);
info.PreComp = lookupTable;
info.Width = minWidth;
c.SetPreCompInfo(p, PRECOMP_NAME, info);
}
return info;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad7c87979fc1144dd917d0c915b9e234
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Math.EC.Endo;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
public class GlvMultiplier
: AbstractECMultiplier
{
protected readonly ECCurve curve;
protected readonly GlvEndomorphism glvEndomorphism;
public GlvMultiplier(ECCurve curve, GlvEndomorphism glvEndomorphism)
{
if (curve == null || curve.Order == null)
throw new ArgumentException("Need curve with known group order", "curve");
this.curve = curve;
this.glvEndomorphism = glvEndomorphism;
}
protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
{
if (!curve.Equals(p.Curve))
throw new InvalidOperationException();
BigInteger n = p.Curve.Order;
BigInteger[] ab = glvEndomorphism.DecomposeScalar(k.Mod(n));
BigInteger a = ab[0], b = ab[1];
ECPointMap pointMap = glvEndomorphism.PointMap;
if (glvEndomorphism.HasEfficientPointMap)
{
return ECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap, b);
}
return ECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap.Map(p), b);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6cbc389e37c0340bd9977589c7954973
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Interface for classes storing precomputation data for multiplication
* algorithms. Used as a Memento (see GOF patterns) for
* <code>WNafMultiplier</code>.
*/
public interface PreCompInfo
{
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f4fca2177f994edbba83dd38e4aaacf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,102 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class implementing the WNAF (Window Non-Adjacent Form) multiplication
* algorithm.
*/
public class WNafL2RMultiplier
: AbstractECMultiplier
{
/**
* Multiplies <code>this</code> by an integer <code>k</code> using the
* Window NAF method.
* @param k The integer by which <code>this</code> is multiplied.
* @return A new <code>ECPoint</code> which equals <code>this</code>
* multiplied by <code>k</code>.
*/
protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
{
// Clamp the window width in the range [2, 16]
int width = System.Math.Max(2, System.Math.Min(16, GetWindowSize(k.BitLength)));
WNafPreCompInfo wnafPreCompInfo = WNafUtilities.Precompute(p, width, true);
ECPoint[] preComp = wnafPreCompInfo.PreComp;
ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k);
ECPoint R = p.Curve.Infinity;
int i = wnaf.Length;
/*
* NOTE: We try to optimize the first window using the precomputed points to substitute an
* addition for 2 or more doublings.
*/
if (i > 1)
{
int wi = wnaf[--i];
int digit = wi >> 16, zeroes = wi & 0xFFFF;
int n = System.Math.Abs(digit);
ECPoint[] table = digit < 0 ? preCompNeg : preComp;
// Optimization can only be used for values in the lower half of the table
if ((n << 2) < (1 << width))
{
int highest = LongArray.BitLengths[n];
// TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
int scale = width - highest;
int lowBits = n ^ (1 << (highest - 1));
int i1 = ((1 << (width - 1)) - 1);
int i2 = (lowBits << scale) + 1;
R = table[i1 >> 1].Add(table[i2 >> 1]);
zeroes -= scale;
//Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2);
}
else
{
R = table[n >> 1];
}
R = R.TimesPow2(zeroes);
}
while (i > 0)
{
int wi = wnaf[--i];
int digit = wi >> 16, zeroes = wi & 0xFFFF;
int n = System.Math.Abs(digit);
ECPoint[] table = digit < 0 ? preCompNeg : preComp;
ECPoint r = table[n >> 1];
R = R.TwicePlus(r);
R = R.TimesPow2(zeroes);
}
return R;
}
/**
* Determine window width to use for a scalar multiplication of the given size.
*
* @param bits the bit-length of the scalar to multiply by
* @return the window size to use
*/
protected virtual int GetWindowSize(int bits)
{
return WNafUtilities.GetWindowSize(bits);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 709fa089a69944425a1ac6253594cce6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
* algorithm.
*/
public class WNafPreCompInfo
: PreCompInfo
{
/**
* Array holding the precomputed <code>ECPoint</code>s used for a Window
* NAF multiplication.
*/
protected ECPoint[] m_preComp = null;
/**
* Array holding the negations of the precomputed <code>ECPoint</code>s used
* for a Window NAF multiplication.
*/
protected ECPoint[] m_preCompNeg = null;
/**
* Holds an <code>ECPoint</code> representing Twice(this). Used for the
* Window NAF multiplication to create or extend the precomputed values.
*/
protected ECPoint m_twice = null;
public virtual ECPoint[] PreComp
{
get { return m_preComp; }
set { this.m_preComp = value; }
}
public virtual ECPoint[] PreCompNeg
{
get { return m_preCompNeg; }
set { this.m_preCompNeg = value; }
}
public virtual ECPoint Twice
{
get { return m_twice; }
set { this.m_twice = value; }
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 46ac5d0f75e084673a754e29c08aed1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,528 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
public abstract class WNafUtilities
{
public static readonly string PRECOMP_NAME = "bc_wnaf";
private static readonly int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
private static readonly byte[] EMPTY_BYTES = new byte[0];
private static readonly int[] EMPTY_INTS = new int[0];
private static readonly ECPoint[] EMPTY_POINTS = new ECPoint[0];
public static int[] GenerateCompactNaf(BigInteger k)
{
if ((k.BitLength >> 16) != 0)
throw new ArgumentException("must have bitlength < 2^16", "k");
if (k.SignValue == 0)
return EMPTY_INTS;
BigInteger _3k = k.ShiftLeft(1).Add(k);
int bits = _3k.BitLength;
int[] naf = new int[bits >> 1];
BigInteger diff = _3k.Xor(k);
int highBit = bits - 1, length = 0, zeroes = 0;
for (int i = 1; i < highBit; ++i)
{
if (!diff.TestBit(i))
{
++zeroes;
continue;
}
int digit = k.TestBit(i) ? -1 : 1;
naf[length++] = (digit << 16) | zeroes;
zeroes = 1;
++i;
}
naf[length++] = (1 << 16) | zeroes;
if (naf.Length > length)
{
naf = Trim(naf, length);
}
return naf;
}
public static int[] GenerateCompactWindowNaf(int width, BigInteger k)
{
if (width == 2)
{
return GenerateCompactNaf(k);
}
if (width < 2 || width > 16)
throw new ArgumentException("must be in the range [2, 16]", "width");
if ((k.BitLength >> 16) != 0)
throw new ArgumentException("must have bitlength < 2^16", "k");
if (k.SignValue == 0)
return EMPTY_INTS;
int[] wnaf = new int[k.BitLength / width + 1];
// 2^width and a mask and sign bit set accordingly
int pow2 = 1 << width;
int mask = pow2 - 1;
int sign = pow2 >> 1;
bool carry = false;
int length = 0, pos = 0;
while (pos <= k.BitLength)
{
if (k.TestBit(pos) == carry)
{
++pos;
continue;
}
k = k.ShiftRight(pos);
int digit = k.IntValue & mask;
if (carry)
{
++digit;
}
carry = (digit & sign) != 0;
if (carry)
{
digit -= pow2;
}
int zeroes = length > 0 ? pos - 1 : pos;
wnaf[length++] = (digit << 16) | zeroes;
pos = width;
}
// Reduce the WNAF array to its actual length
if (wnaf.Length > length)
{
wnaf = Trim(wnaf, length);
}
return wnaf;
}
public static byte[] GenerateJsf(BigInteger g, BigInteger h)
{
int digits = System.Math.Max(g.BitLength, h.BitLength) + 1;
byte[] jsf = new byte[digits];
BigInteger k0 = g, k1 = h;
int j = 0, d0 = 0, d1 = 0;
int offset = 0;
while ((d0 | d1) != 0 || k0.BitLength > offset || k1.BitLength > offset)
{
int n0 = ((int)((uint)k0.IntValue >> offset) + d0) & 7;
int n1 = ((int)((uint)k1.IntValue >> offset) + d1) & 7;
int u0 = n0 & 1;
if (u0 != 0)
{
u0 -= (n0 & 2);
if ((n0 + u0) == 4 && (n1 & 3) == 2)
{
u0 = -u0;
}
}
int u1 = n1 & 1;
if (u1 != 0)
{
u1 -= (n1 & 2);
if ((n1 + u1) == 4 && (n0 & 3) == 2)
{
u1 = -u1;
}
}
if ((d0 << 1) == 1 + u0)
{
d0 ^= 1;
}
if ((d1 << 1) == 1 + u1)
{
d1 ^= 1;
}
if (++offset == 30)
{
offset = 0;
k0 = k0.ShiftRight(30);
k1 = k1.ShiftRight(30);
}
jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF));
}
// Reduce the JSF array to its actual length
if (jsf.Length > j)
{
jsf = Trim(jsf, j);
}
return jsf;
}
public static byte[] GenerateNaf(BigInteger k)
{
if (k.SignValue == 0)
return EMPTY_BYTES;
BigInteger _3k = k.ShiftLeft(1).Add(k);
int digits = _3k.BitLength - 1;
byte[] naf = new byte[digits];
BigInteger diff = _3k.Xor(k);
for (int i = 1; i < digits; ++i)
{
if (diff.TestBit(i))
{
naf[i - 1] = (byte)(k.TestBit(i) ? -1 : 1);
++i;
}
}
naf[digits - 1] = 1;
return naf;
}
/**
* Computes the Window NAF (non-adjacent Form) of an integer.
* @param width The width <code>w</code> of the Window NAF. The width is
* defined as the minimal number <code>w</code>, such that for any
* <code>w</code> consecutive digits in the resulting representation, at
* most one is non-zero.
* @param k The integer of which the Window NAF is computed.
* @return The Window NAF of the given width, such that the following holds:
* <code>k = &amp;sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
* </code>, where the <code>k<sub>i</sub></code> denote the elements of the
* returned <code>byte[]</code>.
*/
public static byte[] GenerateWindowNaf(int width, BigInteger k)
{
if (width == 2)
{
return GenerateNaf(k);
}
if (width < 2 || width > 8)
throw new ArgumentException("must be in the range [2, 8]", "width");
if (k.SignValue == 0)
return EMPTY_BYTES;
byte[] wnaf = new byte[k.BitLength + 1];
// 2^width and a mask and sign bit set accordingly
int pow2 = 1 << width;
int mask = pow2 - 1;
int sign = pow2 >> 1;
bool carry = false;
int length = 0, pos = 0;
while (pos <= k.BitLength)
{
if (k.TestBit(pos) == carry)
{
++pos;
continue;
}
k = k.ShiftRight(pos);
int digit = k.IntValue & mask;
if (carry)
{
++digit;
}
carry = (digit & sign) != 0;
if (carry)
{
digit -= pow2;
}
length += (length > 0) ? pos - 1 : pos;
wnaf[length++] = (byte)digit;
pos = width;
}
// Reduce the WNAF array to its actual length
if (wnaf.Length > length)
{
wnaf = Trim(wnaf, length);
}
return wnaf;
}
public static int GetNafWeight(BigInteger k)
{
if (k.SignValue == 0)
return 0;
BigInteger _3k = k.ShiftLeft(1).Add(k);
BigInteger diff = _3k.Xor(k);
return diff.BitCount;
}
public static WNafPreCompInfo GetWNafPreCompInfo(ECPoint p)
{
return GetWNafPreCompInfo(p.Curve.GetPreCompInfo(p, PRECOMP_NAME));
}
public static WNafPreCompInfo GetWNafPreCompInfo(PreCompInfo preCompInfo)
{
if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo))
{
return (WNafPreCompInfo)preCompInfo;
}
return new WNafPreCompInfo();
}
/**
* Determine window width to use for a scalar multiplication of the given size.
*
* @param bits the bit-length of the scalar to multiply by
* @return the window size to use
*/
public static int GetWindowSize(int bits)
{
return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS);
}
/**
* Determine window width to use for a scalar multiplication of the given size.
*
* @param bits the bit-length of the scalar to multiply by
* @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
* @return the window size to use
*/
public static int GetWindowSize(int bits, int[] windowSizeCutoffs)
{
int w = 0;
for (; w < windowSizeCutoffs.Length; ++w)
{
if (bits < windowSizeCutoffs[w])
{
break;
}
}
return w + 2;
}
public static ECPoint MapPointWithPrecomp(ECPoint p, int width, bool includeNegated,
ECPointMap pointMap)
{
ECCurve c = p.Curve;
WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated);
ECPoint q = pointMap.Map(p);
WNafPreCompInfo wnafPreCompQ = GetWNafPreCompInfo(c.GetPreCompInfo(q, PRECOMP_NAME));
ECPoint twiceP = wnafPreCompP.Twice;
if (twiceP != null)
{
ECPoint twiceQ = pointMap.Map(twiceP);
wnafPreCompQ.Twice = twiceQ;
}
ECPoint[] preCompP = wnafPreCompP.PreComp;
ECPoint[] preCompQ = new ECPoint[preCompP.Length];
for (int i = 0; i < preCompP.Length; ++i)
{
preCompQ[i] = pointMap.Map(preCompP[i]);
}
wnafPreCompQ.PreComp = preCompQ;
if (includeNegated)
{
ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length];
for (int i = 0; i < preCompNegQ.Length; ++i)
{
preCompNegQ[i] = preCompQ[i].Negate();
}
wnafPreCompQ.PreCompNeg = preCompNegQ;
}
c.SetPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
return q;
}
public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated)
{
ECCurve c = p.Curve;
WNafPreCompInfo wnafPreCompInfo = GetWNafPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME));
int iniPreCompLen = 0, reqPreCompLen = 1 << System.Math.Max(0, width - 2);
ECPoint[] preComp = wnafPreCompInfo.PreComp;
if (preComp == null)
{
preComp = EMPTY_POINTS;
}
else
{
iniPreCompLen = preComp.Length;
}
if (iniPreCompLen < reqPreCompLen)
{
preComp = ResizeTable(preComp, reqPreCompLen);
if (reqPreCompLen == 1)
{
preComp[0] = p.Normalize();
}
else
{
int curPreCompLen = iniPreCompLen;
if (curPreCompLen == 0)
{
preComp[0] = p;
curPreCompLen = 1;
}
ECFieldElement iso = null;
if (reqPreCompLen == 2)
{
preComp[1] = p.ThreeTimes();
}
else
{
ECPoint twiceP = wnafPreCompInfo.Twice, last = preComp[curPreCompLen - 1];
if (twiceP == null)
{
twiceP = preComp[0].Twice();
wnafPreCompInfo.Twice = twiceP;
/*
* For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
* where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
* also requires scaling the initial point's X, Y coordinates, and reversing the
* isomorphism as part of the subsequent normalization.
*
* NOTE: The correctness of this optimization depends on:
* 1) additions do not use the curve's A, B coefficients.
* 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
*/
if (ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64)
{
switch (c.CoordinateSystem)
{
case ECCurve.COORD_JACOBIAN:
case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
case ECCurve.COORD_JACOBIAN_MODIFIED:
{
iso = twiceP.GetZCoord(0);
twiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(),
twiceP.YCoord.ToBigInteger());
ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso);
last = last.ScaleX(iso2).ScaleY(iso3);
if (iniPreCompLen == 0)
{
preComp[0] = last;
}
break;
}
}
}
}
while (curPreCompLen < reqPreCompLen)
{
/*
* Compute the new ECPoints for the precomputation array. The values 1, 3,
* 5, ..., 2^(width-1)-1 times p are computed
*/
preComp[curPreCompLen++] = last = last.Add(twiceP);
}
}
/*
* Having oft-used operands in affine form makes operations faster.
*/
c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
}
}
wnafPreCompInfo.PreComp = preComp;
if (includeNegated)
{
ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
int pos;
if (preCompNeg == null)
{
pos = 0;
preCompNeg = new ECPoint[reqPreCompLen];
}
else
{
pos = preCompNeg.Length;
if (pos < reqPreCompLen)
{
preCompNeg = ResizeTable(preCompNeg, reqPreCompLen);
}
}
while (pos < reqPreCompLen)
{
preCompNeg[pos] = preComp[pos].Negate();
++pos;
}
wnafPreCompInfo.PreCompNeg = preCompNeg;
}
c.SetPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo);
return wnafPreCompInfo;
}
private static byte[] Trim(byte[] a, int length)
{
byte[] result = new byte[length];
Array.Copy(a, 0, result, 0, result.Length);
return result;
}
private static int[] Trim(int[] a, int length)
{
int[] result = new int[length];
Array.Copy(a, 0, result, 0, result.Length);
return result;
}
private static ECPoint[] ResizeTable(ECPoint[] a, int length)
{
ECPoint[] result = new ECPoint[length];
Array.Copy(a, 0, result, 0, a.Length);
return result;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66ffc4380bb204a01a45487596cd4837
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Math.EC.Abc;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class implementing the WTNAF (Window
* <code>&#964;</code>-adic Non-Adjacent Form) algorithm.
*/
public class WTauNafMultiplier
: AbstractECMultiplier
{
// TODO Create WTauNafUtilities class and move various functionality into it
internal static readonly string PRECOMP_NAME = "bc_wtnaf";
/**
* Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by <code>k</code> using the reduced <code>&#964;</code>-adic NAF (RTNAF)
* method.
* @param p The AbstractF2mPoint to multiply.
* @param k The integer by which to multiply <code>k</code>.
* @return <code>p</code> multiplied by <code>k</code>.
*/
protected override ECPoint MultiplyPositive(ECPoint point, BigInteger k)
{
if (!(point is AbstractF2mPoint))
throw new ArgumentException("Only AbstractF2mPoint can be used in WTauNafMultiplier");
AbstractF2mPoint p = (AbstractF2mPoint)point;
AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
int m = curve.FieldSize;
sbyte a = (sbyte)curve.A.ToBigInteger().IntValue;
sbyte mu = Tnaf.GetMu(a);
BigInteger[] s = curve.GetSi();
ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10);
return MultiplyWTnaf(p, rho, curve.GetPreCompInfo(p, PRECOMP_NAME), a, mu);
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code> using
* the <code>&#964;</code>-adic NAF (TNAF) method.
* @param p The AbstractF2mPoint to multiply.
* @param lambda The element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code> of which to compute the
* <code>[&#964;]</code>-adic NAF.
* @return <code>p</code> multiplied by <code>&#955;</code>.
*/
private AbstractF2mPoint MultiplyWTnaf(AbstractF2mPoint p, ZTauElement lambda,
PreCompInfo preCompInfo, sbyte a, sbyte mu)
{
ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1;
BigInteger tw = Tnaf.GetTw(mu, Tnaf.Width);
sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width,
BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha);
return MultiplyFromWTnaf(p, u, preCompInfo);
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
* using the window <code>&#964;</code>-adic NAF (TNAF) method, given the
* WTNAF of <code>&#955;</code>.
* @param p The AbstractF2mPoint to multiply.
* @param u The the WTNAF of <code>&#955;</code>..
* @return <code>&#955; * p</code>
*/
private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u, PreCompInfo preCompInfo)
{
AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
sbyte a = (sbyte)curve.A.ToBigInteger().IntValue;
AbstractF2mPoint[] pu;
if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo))
{
pu = Tnaf.GetPreComp(p, a);
WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
pre.PreComp = pu;
curve.SetPreCompInfo(p, PRECOMP_NAME, pre);
}
else
{
pu = ((WTauNafPreCompInfo)preCompInfo).PreComp;
}
// TODO Include negations in precomp (optionally) and use from here
AbstractF2mPoint[] puNeg = new AbstractF2mPoint[pu.Length];
for (int i = 0; i < pu.Length; ++i)
{
puNeg[i] = (AbstractF2mPoint)pu[i].Negate();
}
// q = infinity
AbstractF2mPoint q = (AbstractF2mPoint) p.Curve.Infinity;
int tauCount = 0;
for (int i = u.Length - 1; i >= 0; i--)
{
++tauCount;
int ui = u[i];
if (ui != 0)
{
q = q.TauPow(tauCount);
tauCount = 0;
ECPoint x = ui > 0 ? pu[ui >> 1] : puNeg[(-ui) >> 1];
q = (AbstractF2mPoint)q.Add(x);
}
}
if (tauCount > 0)
{
q = q.TauPow(tauCount);
}
return q;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbc36afbae9454fb1aaf12d8bdba7eaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class holding precomputation data for the WTNAF (Window
* <code>&#964;</code>-adic Non-Adjacent Form) algorithm.
*/
public class WTauNafPreCompInfo
: PreCompInfo
{
/**
* Array holding the precomputed <code>AbstractF2mPoint</code>s used for the
* WTNAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
* WTauNafMultiplier.multiply()}</code>.
*/
protected AbstractF2mPoint[] m_preComp;
public virtual AbstractF2mPoint[] PreComp
{
get { return m_preComp; }
set { this.m_preComp = value; }
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 10af485d4a2b24c3b869653e6da23da1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: