diff --git a/crypto/src/math/ec/endo/ECEndomorphism.cs b/crypto/src/math/ec/endo/ECEndomorphism.cs
new file mode 100644
index 000000000..dfb321368
--- /dev/null
+++ b/crypto/src/math/ec/endo/ECEndomorphism.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+ public interface ECEndomorphism
+ {
+ ECPointMap PointMap { get; }
+
+ bool HasEfficientPointMap { get; }
+ }
+}
diff --git a/crypto/src/math/ec/endo/GlvEndomorphism.cs b/crypto/src/math/ec/endo/GlvEndomorphism.cs
new file mode 100644
index 000000000..f65bdd613
--- /dev/null
+++ b/crypto/src/math/ec/endo/GlvEndomorphism.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+ public interface GlvEndomorphism
+ : ECEndomorphism
+ {
+ BigInteger[] DecomposeScalar(BigInteger k);
+ }
+}
diff --git a/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs b/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs
new file mode 100644
index 000000000..d234d88bf
--- /dev/null
+++ b/crypto/src/math/ec/endo/GlvTypeBEndomorphism.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+ public class GlvTypeBEndomorphism
+ : GlvEndomorphism
+ {
+ protected readonly ECCurve m_curve;
+ protected readonly GlvTypeBParameters m_parameters;
+ protected readonly ECPointMap m_pointMap;
+
+ public GlvTypeBEndomorphism(ECCurve curve, GlvTypeBParameters parameters)
+ {
+ this.m_curve = curve;
+ this.m_parameters = parameters;
+ this.m_pointMap = new ScaleXPointMap(curve.FromBigInteger(parameters.Beta));
+ }
+
+ public virtual BigInteger[] DecomposeScalar(BigInteger k)
+ {
+ int bits = m_parameters.Bits;
+ BigInteger b1 = CalculateB(k, m_parameters.G1, bits);
+ BigInteger b2 = CalculateB(k, m_parameters.G2, bits);
+
+ BigInteger[] v1 = m_parameters.V1, v2 = m_parameters.V2;
+ BigInteger a = k.Subtract((b1.Multiply(v1[0])).Add(b2.Multiply(v2[0])));
+ BigInteger b = (b1.Multiply(v1[1])).Add(b2.Multiply(v2[1])).Negate();
+
+ return new BigInteger[]{ a, b };
+ }
+
+ public virtual ECPointMap PointMap
+ {
+ get { return m_pointMap; }
+ }
+
+ public virtual bool HasEfficientPointMap
+ {
+ get { return true; }
+ }
+
+ protected virtual BigInteger CalculateB(BigInteger k, BigInteger g, int t)
+ {
+ bool negative = (g.SignValue < 0);
+ BigInteger b = k.Multiply(g.Abs());
+ bool extra = b.TestBit(t - 1);
+ b = b.ShiftRight(t);
+ if (extra)
+ {
+ b = b.Add(BigInteger.One);
+ }
+ return negative ? b.Negate() : b;
+ }
+ }
+}
diff --git a/crypto/src/math/ec/endo/GlvTypeBParameters.cs b/crypto/src/math/ec/endo/GlvTypeBParameters.cs
new file mode 100644
index 000000000..f93dfaf2b
--- /dev/null
+++ b/crypto/src/math/ec/endo/GlvTypeBParameters.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+ public class GlvTypeBParameters
+ {
+ protected readonly BigInteger m_beta;
+ protected readonly BigInteger m_lambda;
+ protected readonly BigInteger[] m_v1, m_v2;
+ protected readonly BigInteger m_g1, m_g2;
+ protected readonly int m_bits;
+
+ public GlvTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2,
+ BigInteger g1, BigInteger g2, int bits)
+ {
+ this.m_beta = beta;
+ this.m_lambda = lambda;
+ this.m_v1 = v1;
+ this.m_v2 = v2;
+ this.m_g1 = g1;
+ this.m_g2 = g2;
+ this.m_bits = bits;
+ }
+
+ public virtual BigInteger Beta
+ {
+ get { return m_beta; }
+ }
+
+ public virtual BigInteger Lambda
+ {
+ get { return m_lambda; }
+ }
+
+ public virtual BigInteger[] V1
+ {
+ get { return m_v1; }
+ }
+
+ public virtual BigInteger[] V2
+ {
+ get { return m_v2; }
+ }
+
+ public virtual BigInteger G1
+ {
+ get { return m_g1; }
+ }
+
+ public virtual BigInteger G2
+ {
+ get { return m_g2; }
+ }
+
+ public virtual int Bits
+ {
+ get { return m_bits; }
+ }
+ }
+}
|