diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index ec03a3071..cb00f9912 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -5404,6 +5404,246 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\math\ec\custom\sec\SecT113Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT113FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT113R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT113R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT113R2Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT113R2Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT131Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT131FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT131R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT131R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT131R2Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT131R2Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163K1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163K1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163R2Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT163R2Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT233Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT233FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT233K1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT233K1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT233R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT233R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT239Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT239FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT239K1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT239K1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT283Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT283FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT283K1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT283K1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT283R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT283R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT409Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT409FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT409K1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT409K1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT409R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT409R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT571Field.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT571FieldElement.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT571K1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT571K1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT571R1Curve.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\math\ec\custom\sec\SecT571R1Point.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\math\ec\endo\ECEndomorphism.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs
index e4d1da668..9b7935523 100644
--- a/crypto/src/crypto/ec/CustomNamedCurves.cs
+++ b/crypto/src/crypto/ec/CustomNamedCurves.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
@@ -368,6 +368,342 @@ namespace Org.BouncyCastle.Crypto.EC
}
}
+ /*
+ * sect113r1
+ */
+ internal class SecT113R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT113R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT113R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
+ ECCurve curve = ConfigureCurve(new SecT113R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "009D73616F35F4AB1407D73562C10F"
+ + "00A52830277958EE84D1315ED31886"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect113r2
+ */
+ internal class SecT113R2Holder
+ : X9ECParametersHolder
+ {
+ private SecT113R2Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT113R2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("10C0FB15760860DEF1EEF4D696E676875615175D");
+ ECCurve curve = ConfigureCurve(new SecT113R2Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "01A57A6A7B26CA5EF52FCDB8164797"
+ + "00B3ADC94ED1FE674C06E695BABA1D"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect131r1
+ */
+ internal class SecT131R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT131R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT131R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("4D696E676875615175985BD3ADBADA21B43A97E2");
+ ECCurve curve = ConfigureCurve(new SecT131R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0081BAF91FDF9833C40F9C181343638399"
+ + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect131r2
+ */
+ internal class SecT131R2Holder
+ : X9ECParametersHolder
+ {
+ private SecT131R2Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT131R2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
+ ECCurve curve = ConfigureCurve(new SecT131R2Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0356DCD8F2F95031AD652D23951BB366A8"
+ + "0648F06D867940A5366D9E265DE9EB240F"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect163k1
+ */
+ internal class SecT163K1Holder
+ : X9ECParametersHolder
+ {
+ private SecT163K1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT163K1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SecT163K1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect163r1
+ */
+ internal class SecT163R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT163R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT163R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
+ ECCurve curve = ConfigureCurve(new SecT163R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0369979697AB43897789566789567F787A7876A654"
+ + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect163r2
+ */
+ internal class SecT163R2Holder
+ : X9ECParametersHolder
+ {
+ private SecT163R2Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT163R2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
+ ECCurve curve = ConfigureCurve(new SecT163R2Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect233k1
+ */
+ internal class SecT233K1Holder
+ : X9ECParametersHolder
+ {
+ private SecT233K1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT233K1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SecT233K1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect233r1
+ */
+ internal class SecT233R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT233R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT233R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
+ ECCurve curve = ConfigureCurve(new SecT233R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect239k1
+ */
+ internal class SecT239K1Holder
+ : X9ECParametersHolder
+ {
+ private SecT239K1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT239K1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SecT239K1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect283k1
+ */
+ internal class SecT283K1Holder
+ : X9ECParametersHolder
+ {
+ private SecT283K1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT283K1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SecT283K1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect283r1
+ */
+ internal class SecT283R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT283R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT283R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
+ ECCurve curve = ConfigureCurve(new SecT283R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect409k1
+ */
+ internal class SecT409K1Holder
+ : X9ECParametersHolder
+ {
+ private SecT409K1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT409K1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SecT409K1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect409r1
+ */
+ internal class SecT409R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT409R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT409R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
+ ECCurve curve = ConfigureCurve(new SecT409R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect571k1
+ */
+ internal class SecT571K1Holder
+ : X9ECParametersHolder
+ {
+ private SecT571K1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT571K1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SecT571K1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
+ /*
+ * sect571r1
+ */
+ internal class SecT571R1Holder
+ : X9ECParametersHolder
+ {
+ private SecT571R1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SecT571R1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = Hex.Decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
+ ECCurve curve = ConfigureCurve(new SecT571R1Curve());
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ };
+
private static readonly IDictionary nameToCurve = Platform.CreateHashtable();
private static readonly IDictionary nameToOid = Platform.CreateHashtable();
@@ -423,6 +759,35 @@ namespace Org.BouncyCastle.Crypto.EC
DefineCurveWithOid("secp384r1", SecObjectIdentifiers.SecP384r1, SecP384R1Holder.Instance);
DefineCurveWithOid("secp521r1", SecObjectIdentifiers.SecP521r1, SecP521R1Holder.Instance);
+ DefineCurveWithOid("sect113r1", SecObjectIdentifiers.SecT113r1, SecT113R1Holder.Instance);
+ DefineCurveWithOid("sect113r2", SecObjectIdentifiers.SecT113r2, SecT113R2Holder.Instance);
+ DefineCurveWithOid("sect131r1", SecObjectIdentifiers.SecT131r1, SecT131R1Holder.Instance);
+ DefineCurveWithOid("sect131r2", SecObjectIdentifiers.SecT131r2, SecT131R2Holder.Instance);
+ DefineCurveWithOid("sect163k1", SecObjectIdentifiers.SecT163k1, SecT163K1Holder.Instance);
+ DefineCurveWithOid("sect163r1", SecObjectIdentifiers.SecT163r1, SecT163R1Holder.Instance);
+ DefineCurveWithOid("sect163r2", SecObjectIdentifiers.SecT163r2, SecT163R2Holder.Instance);
+ DefineCurveWithOid("sect233k1", SecObjectIdentifiers.SecT233k1, SecT233K1Holder.Instance);
+ DefineCurveWithOid("sect233r1", SecObjectIdentifiers.SecT233r1, SecT233R1Holder.Instance);
+ DefineCurveWithOid("sect239k1", SecObjectIdentifiers.SecT239k1, SecT239K1Holder.Instance);
+ DefineCurveWithOid("sect283k1", SecObjectIdentifiers.SecT283k1, SecT283K1Holder.Instance);
+ DefineCurveWithOid("sect283r1", SecObjectIdentifiers.SecT283r1, SecT283R1Holder.Instance);
+ DefineCurveWithOid("sect409k1", SecObjectIdentifiers.SecT409k1, SecT409K1Holder.Instance);
+ DefineCurveWithOid("sect409r1", SecObjectIdentifiers.SecT409r1, SecT409R1Holder.Instance);
+ DefineCurveWithOid("sect571k1", SecObjectIdentifiers.SecT571k1, SecT571K1Holder.Instance);
+ DefineCurveWithOid("sect571r1", SecObjectIdentifiers.SecT571r1, SecT571R1Holder.Instance);
+
+ DefineCurveAlias("B-163", SecObjectIdentifiers.SecT163r2);
+ DefineCurveAlias("B-233", SecObjectIdentifiers.SecT233r1);
+ DefineCurveAlias("B-283", SecObjectIdentifiers.SecT283r1);
+ DefineCurveAlias("B-409", SecObjectIdentifiers.SecT409r1);
+ DefineCurveAlias("B-571", SecObjectIdentifiers.SecT571r1);
+
+ DefineCurveAlias("K-163", SecObjectIdentifiers.SecT163k1);
+ DefineCurveAlias("K-233", SecObjectIdentifiers.SecT233k1);
+ DefineCurveAlias("K-283", SecObjectIdentifiers.SecT283k1);
+ DefineCurveAlias("K-409", SecObjectIdentifiers.SecT409k1);
+ DefineCurveAlias("K-571", SecObjectIdentifiers.SecT571k1);
+
DefineCurveAlias("P-192", SecObjectIdentifiers.SecP192r1);
DefineCurveAlias("P-224", SecObjectIdentifiers.SecP224r1);
DefineCurveAlias("P-256", SecObjectIdentifiers.SecP256r1);
diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs
new file mode 100644
index 000000000..dbb645e6f
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT113Field
+ {
+ private const ulong M49 = ulong.MaxValue >> 15;
+ private const ulong M57 = ulong.MaxValue >> 7;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ zz[0] = xx[0] ^ yy[0];
+ zz[1] = xx[1] ^ yy[1];
+ zz[2] = xx[2] ^ yy[2];
+ zz[3] = xx[3] ^ yy[3];
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat128.FromBigInteger64(x);
+ Reduce15(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat128.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat128.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3];
+
+ x1 ^= (x3 << 15) ^ (x3 << 24);
+ x2 ^= (x3 >> 49) ^ (x3 >> 40);
+
+ x0 ^= (x2 << 15) ^ (x2 << 24);
+ x1 ^= (x2 >> 49) ^ (x2 >> 40);
+
+ ulong t = x1 >> 49;
+ z[0] = x0 ^ t ^ (t << 9);
+ z[1] = x1 & M49;
+ }
+
+ public static void Reduce15(ulong[] z, int zOff)
+ {
+ ulong z1 = z[zOff + 1], t = z1 >> 49;
+ z[zOff ] ^= t ^ (t << 9);
+ z[zOff + 1] = z1 & M49;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat128.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat128.CreateExt64();
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat128.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ /*
+ * "Three-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein.
+ */
+
+ ulong f0 = x[0], f1 = x[1];
+ f1 = ((f0 >> 57) ^ (f1 << 7)) & M57;
+ f0 &= M57;
+
+ ulong g0 = y[0], g1 = y[1];
+ g1 = ((g0 >> 57) ^ (g1 << 7)) & M57;
+ g0 &= M57;
+
+ ulong[] H = new ulong[6];
+
+ ImplMulw(f0, g0, H, 0); // H(0) 57/56 bits
+ ImplMulw(f1, g1, H, 2); // H(INF) 57/54 bits
+ ImplMulw(f0 ^ f1, g0 ^ g1, H, 4); // H(1) 57/56 bits
+
+ ulong r = H[1] ^ H[2];
+ ulong z0 = H[0],
+ z3 = H[3],
+ z1 = H[4] ^ z0 ^ r,
+ z2 = H[5] ^ z3 ^ r;
+
+ zz[0] = z0 ^ (z1 << 57);
+ zz[1] = (z1 >> 7) ^ (z2 << 50);
+ zz[2] = (z2 >> 14) ^ (z3 << 43);
+ zz[3] = (z3 >> 21);
+ }
+
+ protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(x >> 57 == 0);
+ Debug.Assert(y >> 57 == 0);
+
+ ulong[] u = new ulong[8];
+ //u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 7];
+ int k = 48;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3
+ ^ u[(j >> 6) & 7] << 6;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 9) > 0);
+
+ h ^= ((x & 0x0100804020100800UL) & (ulong)(((long)y << 7) >> 63)) >> 8;
+
+ Debug.Assert(h >> 49 == 0);
+
+ z[zOff ] = l & M57;
+ z[zOff + 1] = (l >> 57) ^ (h << 7);
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ Interleave.Expand64To128(x[0], zz, 0);
+ Interleave.Expand64To128(x[1], zz, 2);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
new file mode 100644
index 000000000..7e9d53e44
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT113FieldElement
+ : ECFieldElement
+ {
+ protected internal readonly ulong[] x;
+
+ public SecT113FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT113FieldElement", "x");
+
+ this.x = SecT113Field.FromBigInteger(x);
+ }
+
+ public SecT113FieldElement()
+ {
+ this.x = Nat128.Create64();
+ }
+
+ protected internal SecT113FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat128.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat128.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1L) != 0L;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat128.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT113Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 113; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat128.Create64();
+ SecT113Field.Add(x, ((SecT113FieldElement)b).x, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat128.Create64();
+ SecT113Field.AddOne(x, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and Subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat128.Create64();
+ SecT113Field.Multiply(x, ((SecT113FieldElement)b).x, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT113FieldElement)b).x;
+ ulong[] xx = ((SecT113FieldElement)x).x, yx = ((SecT113FieldElement)y).x;
+
+ ulong[] tt = Nat128.CreateExt64();
+ SecT113Field.MultiplyAddToExt(ax, bx, tt);
+ SecT113Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat128.Create64();
+ SecT113Field.Reduce(tt, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat128.Create64();
+ SecT113Field.Square(x, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT113FieldElement)x).x, yx = ((SecT113FieldElement)y).x;
+
+ ulong[] tt = Nat128.CreateExt64();
+ SecT113Field.SquareAddToExt(ax, tt);
+ SecT113Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat128.Create64();
+ SecT113Field.Reduce(tt, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat128.Create64();
+ SecT113Field.SquareN(x, pow, z);
+ return new SecT113FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT113FieldElement(
+ AbstractF2mCurve.Inverse(113, new int[]{ 9 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Tpb; }
+ }
+
+ public virtual int M
+ {
+ get { return 113; }
+ }
+
+ public virtual int K1
+ {
+ get { return 9; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT113FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT113FieldElement);
+ }
+
+ public virtual bool Equals(SecT113FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat128.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 113009 ^ Arrays.GetHashCode(x, 0, 2);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
new file mode 100644
index 000000000..04e69e2a8
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT113R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT113R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT113R1Point m_infinity;
+
+ public SecT113R1Curve()
+ : base(113, 9, 0, 0)
+ {
+ this.m_infinity = new SecT113R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("003088250CA6E7C7FE649CE85820F7")));
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("00E8BEE4D3E2260744188BE0E9C723")));
+ this.m_order = new BigInteger(1, Hex.Decode("0100000000000000D9CCEC8A39E56F"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT113R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT113R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 113; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT113FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT113R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT113R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(113, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 113; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 113; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 9; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT113R1Point.cs b/crypto/src/math/ec/custom/sec/SecT113R1Point.cs
new file mode 100644
index 000000000..6ecc8b01a
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT113R1Point.cs
@@ -0,0 +1,281 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT113R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT113R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT113R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT113R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT113R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ if (X3.IsZero)
+ {
+ return new SecT113R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT113R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT113R1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement a = curve.A;
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq);
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq);
+ if (T.IsZero)
+ {
+ return new SecT113R1Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT113R1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT113R1Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT113R1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT113R1Point(Curve, X, L.Add(Z), new ECFieldElement[]{ Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
new file mode 100644
index 000000000..a02db6b25
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
@@ -0,0 +1,190 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT113R2Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT113R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT113R2Point m_infinity;
+
+ public SecT113R2Curve()
+ : base(113, 9, 0, 0)
+ {
+ this.m_infinity = new SecT113R2Point(this, null, null);
+
+ this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("00689918DBEC7E5A0DD6DFC0AA55C7")));
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0095E9A9EC9B297BD4BF36E059184F")));
+ this.m_order = new BigInteger(1, Hex.Decode("010000000000000108789B2496AF93"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT113R2_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT113R2Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 113; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT113FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT113R2Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT113R2Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(113, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 113; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 113; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 9; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT113R2Point.cs b/crypto/src/math/ec/custom/sec/SecT113R2Point.cs
new file mode 100644
index 000000000..1453d78c3
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT113R2Point.cs
@@ -0,0 +1,291 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT113R2Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT113R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT113R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT113R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT113R2Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ {
+ return b;
+ }
+ if (b.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ if (X3.IsZero)
+ {
+ return new SecT113R2Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT113R2Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT113R2Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement a = curve.A;
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq);
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq);
+ if (T.IsZero)
+ {
+ return new SecT113R2Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT113R2Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ {
+ return b;
+ }
+ if (b.IsInfinity)
+ {
+ return Twice();
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT113R2Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT113R2Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT113R2Point(Curve, X, L.Add(Z), new ECFieldElement[]{ Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs
new file mode 100644
index 000000000..df75dfcd7
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs
@@ -0,0 +1,274 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT131Field
+ {
+ private const ulong M03 = ulong.MaxValue >> 61;
+ private const ulong M44 = ulong.MaxValue >> 20;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ zz[0] = xx[0] ^ yy[0];
+ zz[1] = xx[1] ^ yy[1];
+ zz[2] = xx[2] ^ yy[2];
+ zz[3] = xx[3] ^ yy[3];
+ zz[4] = xx[4] ^ yy[4];
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ z[2] = x[2];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat192.FromBigInteger64(x);
+ Reduce61(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat192.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat192.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4];
+
+ x1 ^= (x4 << 61) ^ (x4 << 63);
+ x2 ^= (x4 >> 3) ^ (x4 >> 1) ^ x4 ^ (x4 << 5);
+ x3 ^= (x4 >> 59);
+
+ x0 ^= (x3 << 61) ^ (x3 << 63);
+ x1 ^= (x3 >> 3) ^ (x3 >> 1) ^ x3 ^ (x3 << 5);
+ x2 ^= (x3 >> 59);
+
+ ulong t = x2 >> 3;
+ z[0] = x0 ^ t ^ (t << 2) ^ (t << 3) ^ (t << 8);
+ z[1] = x1 ^ (t >> 56);
+ z[2] = x2 & M03;
+ }
+
+ public static void Reduce61(ulong[] z, int zOff)
+ {
+ ulong z2 = z[zOff + 2], t = z2 >> 3;
+ z[zOff ] ^= t ^ (t << 2) ^ (t << 3) ^ (t << 8);
+ z[zOff + 1] ^= (t >> 56);
+ z[zOff + 2] = z2 & M03;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat.Create64(5);
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat.Create64(5);
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat.Create64(5);
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplCompactExt(ulong[] zz)
+ {
+ ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5];
+ zz[0] = z0 ^ (z1 << 44);
+ zz[1] = (z1 >> 20) ^ (z2 << 24);
+ zz[2] = (z2 >> 40) ^ (z3 << 4)
+ ^ (z4 << 48);
+ zz[3] = (z3 >> 60) ^ (z5 << 28)
+ ^ (z4 >> 16);
+ zz[4] = (z5 >> 36);
+ zz[5] = 0;
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ /*
+ * "Five-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein.
+ */
+
+ ulong f0 = x[0], f1 = x[1], f2 = x[2];
+ f2 = ((f1 >> 24) ^ (f2 << 40)) & M44;
+ f1 = ((f0 >> 44) ^ (f1 << 20)) & M44;
+ f0 &= M44;
+
+ ulong g0 = y[0], g1 = y[1], g2 = y[2];
+ g2 = ((g1 >> 24) ^ (g2 << 40)) & M44;
+ g1 = ((g0 >> 44) ^ (g1 << 20)) & M44;
+ g0 &= M44;
+
+ ulong[] H = new ulong[10];
+
+ ImplMulw(f0, g0, H, 0); // H(0) 44/43 bits
+ ImplMulw(f2, g2, H, 2); // H(INF) 44/41 bits
+
+ ulong t0 = f0 ^ f1 ^ f2;
+ ulong t1 = g0 ^ g1 ^ g2;
+
+ ImplMulw(t0, t1, H, 4); // H(1) 44/43 bits
+
+ ulong t2 = (f1 << 1) ^ (f2 << 2);
+ ulong t3 = (g1 << 1) ^ (g2 << 2);
+
+ ImplMulw(f0 ^ t2, g0 ^ t3, H, 6); // H(t) 44/45 bits
+ ImplMulw(t0 ^ t2, t1 ^ t3, H, 8); // H(t + 1) 44/45 bits
+
+ ulong t4 = H[6] ^ H[8];
+ ulong t5 = H[7] ^ H[9];
+
+ Debug.Assert(t5 >> 44 == 0);
+
+ // Calculate V
+ ulong v0 = (t4 << 1) ^ H[6];
+ ulong v1 = t4 ^ (t5 << 1) ^ H[7];
+ ulong v2 = t5;
+
+ // Calculate U
+ ulong u0 = H[0];
+ ulong u1 = H[1] ^ H[0] ^ H[4];
+ ulong u2 = H[1] ^ H[5];
+
+ // Calculate W
+ ulong w0 = u0 ^ v0 ^ (H[2] << 4) ^ (H[2] << 1);
+ ulong w1 = u1 ^ v1 ^ (H[3] << 4) ^ (H[3] << 1);
+ ulong w2 = u2 ^ v2;
+
+ // Propagate carries
+ w1 ^= (w0 >> 44); w0 &= M44;
+ w2 ^= (w1 >> 44); w1 &= M44;
+
+ Debug.Assert((w0 & 1UL) == 0);
+
+ // Divide W by t
+
+ w0 = (w0 >> 1) ^ ((w1 & 1UL) << 43);
+ w1 = (w1 >> 1) ^ ((w2 & 1UL) << 43);
+ w2 = (w2 >> 1);
+
+ // Divide W by (t + 1)
+
+ w0 ^= (w0 << 1);
+ w0 ^= (w0 << 2);
+ w0 ^= (w0 << 4);
+ w0 ^= (w0 << 8);
+ w0 ^= (w0 << 16);
+ w0 ^= (w0 << 32);
+
+ w0 &= M44; w1 ^= (w0 >> 43);
+
+ w1 ^= (w1 << 1);
+ w1 ^= (w1 << 2);
+ w1 ^= (w1 << 4);
+ w1 ^= (w1 << 8);
+ w1 ^= (w1 << 16);
+ w1 ^= (w1 << 32);
+
+ w1 &= M44; w2 ^= (w1 >> 43);
+
+ w2 ^= (w2 << 1);
+ w2 ^= (w2 << 2);
+ w2 ^= (w2 << 4);
+ w2 ^= (w2 << 8);
+ w2 ^= (w2 << 16);
+ w2 ^= (w2 << 32);
+
+ Debug.Assert(w2 >> 42 == 0);
+
+ zz[0] = u0;
+ zz[1] = u1 ^ w0 ^ H[2];
+ zz[2] = u2 ^ w1 ^ w0 ^ H[3];
+ zz[3] = w2 ^ w1;
+ zz[4] = w2 ^ H[2];
+ zz[5] = H[3];
+
+ ImplCompactExt(zz);
+ }
+
+ protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(x >> 45 == 0);
+ Debug.Assert(y >> 45 == 0);
+
+ ulong[] u = new ulong[8];
+ // u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3
+ ^ u[(j >> 6) & 7] << 6;
+ int k = 33;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3
+ ^ u[(j >> 6) & 7] << 6
+ ^ u[(j >> 9) & 7] << 9;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 12) > 0);
+
+ Debug.Assert(h >> 25 == 0);
+
+ z[zOff ] = l & M44;
+ z[zOff + 1] = (l >> 44) ^ (h << 20);
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ Interleave.Expand64To128(x[0], zz, 0);
+ Interleave.Expand64To128(x[1], zz, 2);
+
+ zz[4] = Interleave.Expand8to16((uint)x[2]);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
new file mode 100644
index 000000000..d60c7ed7d
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT131FieldElement
+ : ECFieldElement
+ {
+ protected readonly ulong[] x;
+
+ public SecT131FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT131FieldElement", "x");
+
+ this.x = SecT131Field.FromBigInteger(x);
+ }
+
+ public SecT131FieldElement()
+ {
+ this.x = Nat192.Create64();
+ }
+
+ protected internal SecT131FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat192.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat192.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1UL) != 0UL;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat192.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT131Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 131; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat192.Create64();
+ SecT131Field.Add(x, ((SecT131FieldElement)b).x, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat192.Create64();
+ SecT131Field.AddOne(x, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and Subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat192.Create64();
+ SecT131Field.Multiply(x, ((SecT131FieldElement)b).x, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT131FieldElement)b).x;
+ ulong[] xx = ((SecT131FieldElement)x).x, yx = ((SecT131FieldElement)y).x;
+
+ ulong[] tt = Nat.Create64(5);
+ SecT131Field.MultiplyAddToExt(ax, bx, tt);
+ SecT131Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat192.Create64();
+ SecT131Field.Reduce(tt, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat192.Create64();
+ SecT131Field.Square(x, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT131FieldElement)x).x, yx = ((SecT131FieldElement)y).x;
+
+ ulong[] tt = Nat.Create64(5);
+ SecT131Field.SquareAddToExt(ax, tt);
+ SecT131Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat192.Create64();
+ SecT131Field.Reduce(tt, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat192.Create64();
+ SecT131Field.SquareN(x, pow, z);
+ return new SecT131FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT131FieldElement(
+ AbstractF2mCurve.Inverse(131, new int[] { 2, 3, 8 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Ppb; }
+ }
+
+ public virtual int M
+ {
+ get { return 131; }
+ }
+
+ public virtual int K1
+ {
+ get { return 2; }
+ }
+
+ public virtual int K2
+ {
+ get { return 3; }
+ }
+
+ public virtual int K3
+ {
+ get { return 8; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT131FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT131FieldElement);
+ }
+
+ public virtual bool Equals(SecT131FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat192.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 131832 ^ Arrays.GetHashCode(x, 0, 3);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
new file mode 100644
index 000000000..789e3c0c3
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT131R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT131R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT131R1Point m_infinity;
+
+ public SecT131R1Curve()
+ : base(131, 2, 3, 8)
+ {
+ this.m_infinity = new SecT131R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("07A11B09A76B562144418FF3FF8C2570B8")));
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0217C05610884B63B9C6C7291678F9D341")));
+ this.m_order = new BigInteger(1, Hex.Decode("0400000000000000023123953A9464B54D"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT131R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT131R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 131; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT131FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT131R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT131R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(131, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 131; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 131; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 2; }
+ }
+
+ public virtual int K2
+ {
+ get { return 3; }
+ }
+
+ public virtual int K3
+ {
+ get { return 8; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT131R1Point.cs b/crypto/src/math/ec/custom/sec/SecT131R1Point.cs
new file mode 100644
index 000000000..7afdad89c
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT131R1Point.cs
@@ -0,0 +1,287 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT131R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT131R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT131R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT131R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT131R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ if (X3.IsZero)
+ {
+ return new SecT131R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT131R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT131R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement a = curve.A;
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq);
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq);
+ if (T.IsZero)
+ {
+ return new SecT131R1Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT131R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ {
+ return b;
+ }
+ if (b.IsInfinity)
+ {
+ return Twice();
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT131R1Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT131R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT131R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
new file mode 100644
index 000000000..2004f84ca
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
@@ -0,0 +1,190 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT131R2Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT131R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT131R2Point m_infinity;
+
+ public SecT131R2Curve()
+ : base(131, 2, 3, 8)
+ {
+ this.m_infinity = new SecT131R2Point(this, null, null);
+
+ this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("03E5A88919D7CAFCBF415F07C2176573B2")));
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("04B8266A46C55657AC734CE38F018F2192")));
+ this.m_order = new BigInteger(1, Hex.Decode("0400000000000000016954A233049BA98F"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT131R2_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT131R2Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override int FieldSize
+ {
+ get { return 131; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT131FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT131R2Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT131R2Point(this, x, y, zs, withCompression);
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(131, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 131; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 131; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 2; }
+ }
+
+ public virtual int K2
+ {
+ get { return 3; }
+ }
+
+ public virtual int K3
+ {
+ get { return 8; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT131R2Point.cs b/crypto/src/math/ec/custom/sec/SecT131R2Point.cs
new file mode 100644
index 000000000..be61561da
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT131R2Point.cs
@@ -0,0 +1,283 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT131R2Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT131R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT131R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT131R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT131R2Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ if (X3.IsZero)
+ {
+ return new SecT131R2Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT131R2Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT131R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement a = curve.A;
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq);
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq);
+ if (T.IsZero)
+ {
+ return new SecT131R2Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT131R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT131R2Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT131R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT131R2Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs
new file mode 100644
index 000000000..2a775e20d
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163Field
+ {
+ private const ulong M35 = ulong.MaxValue >> 29;
+ private const ulong M55 = ulong.MaxValue >> 9;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ zz[0] = xx[0] ^ yy[0];
+ zz[1] = xx[1] ^ yy[1];
+ zz[2] = xx[2] ^ yy[2];
+ zz[3] = xx[3] ^ yy[3];
+ zz[4] = xx[4] ^ yy[4];
+ zz[5] = xx[5] ^ yy[5];
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ z[2] = x[2];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat192.FromBigInteger64(x);
+ Reduce29(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat192.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat192.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4], x5 = xx[5];
+
+ x2 ^= (x5 << 29) ^ (x5 << 32) ^ (x5 << 35) ^ (x5 << 36);
+ x3 ^= (x5 >> 35) ^ (x5 >> 32) ^ (x5 >> 29) ^ (x5 >> 28);
+
+ x1 ^= (x4 << 29) ^ (x4 << 32) ^ (x4 << 35) ^ (x4 << 36);
+ x2 ^= (x4 >> 35) ^ (x4 >> 32) ^ (x4 >> 29) ^ (x4 >> 28);
+
+ x0 ^= (x3 << 29) ^ (x3 << 32) ^ (x3 << 35) ^ (x3 << 36);
+ x1 ^= (x3 >> 35) ^ (x3 >> 32) ^ (x3 >> 29) ^ (x3 >> 28);
+
+ ulong t = x2 >> 35;
+ z[0] = x0 ^ t ^ (t << 3) ^ (t << 6) ^ (t << 7);
+ z[1] = x1;
+ z[2] = x2 & M35;
+ }
+
+ public static void Reduce29(ulong[] z, int zOff)
+ {
+ ulong z2 = z[zOff + 2], t = z2 >> 35;
+ z[zOff ] ^= t ^ (t << 3) ^ (t << 6) ^ (t << 7);
+ z[zOff + 2] = z2 & M35;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat192.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat192.CreateExt64();
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat192.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplCompactExt(ulong[] zz)
+ {
+ ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5];
+ zz[0] = z0 ^ (z1 << 55);
+ zz[1] = (z1 >> 9) ^ (z2 << 46);
+ zz[2] = (z2 >> 18) ^ (z3 << 37);
+ zz[3] = (z3 >> 27) ^ (z4 << 28);
+ zz[4] = (z4 >> 36) ^ (z5 << 19);
+ zz[5] = (z5 >> 45);
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ /*
+ * "Five-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein.
+ */
+
+ ulong f0 = x[0], f1 = x[1], f2 = x[2];
+ f2 = ((f1 >> 46) ^ (f2 << 18));
+ f1 = ((f0 >> 55) ^ (f1 << 9)) & M55;
+ f0 &= M55;
+
+ ulong g0 = y[0], g1 = y[1], g2 = y[2];
+ g2 = ((g1 >> 46) ^ (g2 << 18));
+ g1 = ((g0 >> 55) ^ (g1 << 9)) & M55;
+ g0 &= M55;
+
+ ulong[] H = new ulong[10];
+
+ ImplMulw(f0, g0, H, 0); // H(0) 55/54 bits
+ ImplMulw(f2, g2, H, 2); // H(INF) 55/50 bits
+
+ ulong t0 = f0 ^ f1 ^ f2;
+ ulong t1 = g0 ^ g1 ^ g2;
+
+ ImplMulw(t0, t1, H, 4); // H(1) 55/54 bits
+
+ ulong t2 = (f1 << 1) ^ (f2 << 2);
+ ulong t3 = (g1 << 1) ^ (g2 << 2);
+
+ ImplMulw(f0 ^ t2, g0 ^ t3, H, 6); // H(t) 55/56 bits
+ ImplMulw(t0 ^ t2, t1 ^ t3, H, 8); // H(t + 1) 55/56 bits
+
+ ulong t4 = H[6] ^ H[8];
+ ulong t5 = H[7] ^ H[9];
+
+ Debug.Assert(t5 >> 55 == 0);
+
+ // Calculate V
+ ulong v0 = (t4 << 1) ^ H[6];
+ ulong v1 = t4 ^ (t5 << 1) ^ H[7];
+ ulong v2 = t5;
+
+ // Calculate U
+ ulong u0 = H[0];
+ ulong u1 = H[1] ^ H[0] ^ H[4];
+ ulong u2 = H[1] ^ H[5];
+
+ // Calculate W
+ ulong w0 = u0 ^ v0 ^ (H[2] << 4) ^ (H[2] << 1);
+ ulong w1 = u1 ^ v1 ^ (H[3] << 4) ^ (H[3] << 1);
+ ulong w2 = u2 ^ v2;
+
+ // Propagate carries
+ w1 ^= (w0 >> 55); w0 &= M55;
+ w2 ^= (w1 >> 55); w1 &= M55;
+
+ Debug.Assert((w0 & 1UL) == 0UL);
+
+ // Divide W by t
+
+ w0 = (w0 >> 1) ^ ((w1 & 1UL) << 54);
+ w1 = (w1 >> 1) ^ ((w2 & 1UL) << 54);
+ w2 = (w2 >> 1);
+
+ // Divide W by (t + 1)
+
+ w0 ^= (w0 << 1);
+ w0 ^= (w0 << 2);
+ w0 ^= (w0 << 4);
+ w0 ^= (w0 << 8);
+ w0 ^= (w0 << 16);
+ w0 ^= (w0 << 32);
+
+ w0 &= M55; w1 ^= (w0 >> 54);
+
+ w1 ^= (w1 << 1);
+ w1 ^= (w1 << 2);
+ w1 ^= (w1 << 4);
+ w1 ^= (w1 << 8);
+ w1 ^= (w1 << 16);
+ w1 ^= (w1 << 32);
+
+ w1 &= M55; w2 ^= (w1 >> 54);
+
+ w2 ^= (w2 << 1);
+ w2 ^= (w2 << 2);
+ w2 ^= (w2 << 4);
+ w2 ^= (w2 << 8);
+ w2 ^= (w2 << 16);
+ w2 ^= (w2 << 32);
+
+ Debug.Assert(w2 >> 52 == 0);
+
+ zz[0] = u0;
+ zz[1] = u1 ^ w0 ^ H[2];
+ zz[2] = u2 ^ w1 ^ w0 ^ H[3];
+ zz[3] = w2 ^ w1;
+ zz[4] = w2 ^ H[2];
+ zz[5] = H[3];
+
+ ImplCompactExt(zz);
+ }
+
+ protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(x >> 56 == 0);
+ Debug.Assert(y >> 56 == 0);
+
+ ulong[] u = new ulong[8];
+ // u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 3];
+ int k = 47;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3
+ ^ u[(j >> 6) & 7] << 6;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 9) > 0);
+
+ Debug.Assert(h >> 47 == 0);
+
+ z[zOff ] = l & M55;
+ z[zOff + 1] = (l >> 55) ^ (h << 9);
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ Interleave.Expand64To128(x[0], zz, 0);
+ Interleave.Expand64To128(x[1], zz, 2);
+
+ ulong x2 = x[2];
+ zz[4] = Interleave.Expand32to64((uint)x2);
+ zz[5] = Interleave.Expand8to16((uint)(x2 >> 32));
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
new file mode 100644
index 000000000..0ef421c71
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163FieldElement
+ : ECFieldElement
+ {
+ protected readonly ulong[] x;
+
+ public SecT163FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT163FieldElement", "x");
+
+ this.x = SecT163Field.FromBigInteger(x);
+ }
+
+ public SecT163FieldElement()
+ {
+ this.x = Nat192.Create64();
+ }
+
+ protected internal SecT163FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat192.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat192.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1L) != 0L;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat192.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT163Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 163; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat192.Create64();
+ SecT163Field.Add(x, ((SecT163FieldElement)b).x, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat192.Create64();
+ SecT163Field.AddOne(x, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat192.Create64();
+ SecT163Field.Multiply(x, ((SecT163FieldElement)b).x, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT163FieldElement)b).x;
+ ulong[] xx = ((SecT163FieldElement)x).x, yx = ((SecT163FieldElement)y).x;
+
+ ulong[] tt = Nat192.CreateExt64();
+ SecT163Field.MultiplyAddToExt(ax, bx, tt);
+ SecT163Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat192.Create64();
+ SecT163Field.Reduce(tt, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat192.Create64();
+ SecT163Field.Square(x, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT163FieldElement)x).x, yx = ((SecT163FieldElement)y).x;
+
+ ulong[] tt = Nat192.CreateExt64();
+ SecT163Field.SquareAddToExt(ax, tt);
+ SecT163Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat192.Create64();
+ SecT163Field.Reduce(tt, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat192.Create64();
+ SecT163Field.SquareN(x, pow, z);
+ return new SecT163FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT163FieldElement(
+ AbstractF2mCurve.Inverse(163, new int[] { 3, 6, 7 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Ppb; }
+ }
+
+ public virtual int M
+ {
+ get { return 163; }
+ }
+
+ public virtual int K1
+ {
+ get { return 3; }
+ }
+
+ public virtual int K2
+ {
+ get { return 6; }
+ }
+
+ public virtual int K3
+ {
+ get { return 7; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT163FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT163FieldElement);
+ }
+
+ public virtual bool Equals(SecT163FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat192.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 163763 ^ Arrays.GetHashCode(x, 0, 3);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
new file mode 100644
index 000000000..1cfd09e1c
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
@@ -0,0 +1,194 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163K1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT163K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT163K1Point m_infinity;
+
+ public SecT163K1Curve()
+ : base(163, 3, 6, 7)
+ {
+ this.m_infinity = new SecT163K1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.One);
+ this.m_b = this.m_a;
+ this.m_order = new BigInteger(1, Hex.Decode("04000000000000000000020108A2E0CC0D99F8A5EF"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT163K1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT163K1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected override ECMultiplier CreateDefaultMultiplier()
+ {
+ return new WTauNafMultiplier();
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 163; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT163FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT163K1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT163K1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return true; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(163, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 163; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 163; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 3; }
+ }
+
+ public virtual int K2
+ {
+ get { return 6; }
+ }
+
+ public virtual int K3
+ {
+ get { return 7; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163K1Point.cs b/crypto/src/math/ec/custom/sec/SecT163K1Point.cs
new file mode 100644
index 000000000..2e3ba57d0
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163K1Point.cs
@@ -0,0 +1,289 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163K1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT163K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT163K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT163K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT163K1Point(null, this.AffineXCoord, this.AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.getA());
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ //return new SecT163K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT163K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT163K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT163K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT163K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq);
+ if (T.IsZero)
+ {
+ //return new SecT163K1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT163K1Point(curve, T, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement t1 = L1.Add(X1).Square();
+ ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(X3);
+
+ return new SecT163K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ // NOTE: TwicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.getA().Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.getA().Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT163K1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT163K1Point(curve, A, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT163K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT163K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
new file mode 100644
index 000000000..fc18e1094
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
@@ -0,0 +1,190 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT163R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT163R1Point m_infinity;
+
+ public SecT163R1Curve()
+ : base(163, 3, 6, 7)
+ {
+ this.m_infinity = new SecT163R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2")));
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9")));
+ this.m_order = new BigInteger(1, Hex.Decode("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT163R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT163R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 163; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT163FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT163R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT163R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(163, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 163; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 163; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 3; }
+ }
+
+ public virtual int K2
+ {
+ get { return 6; }
+ }
+
+ public virtual int K3
+ {
+ get { return 7; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163R1Point.cs b/crypto/src/math/ec/custom/sec/SecT163R1Point.cs
new file mode 100644
index 000000000..811a09f14
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163R1Point.cs
@@ -0,0 +1,283 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT163R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT163R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT163R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT163R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ if (X3.IsZero)
+ {
+ return new SecT163R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT163R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT163R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement a = curve.A;
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq);
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq);
+ if (T.IsZero)
+ {
+ return new SecT163R1Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT163R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT163R1Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT163R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT163R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
new file mode 100644
index 000000000..9efe11c3e
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163R2Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT163R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT163R2Point m_infinity;
+
+ public SecT163R2Curve()
+ : base(163, 3, 6, 7)
+ {
+ this.m_infinity = new SecT163R2Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.One);
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("020A601907B8C953CA1481EB10512F78744A3205FD")));
+ this.m_order = new BigInteger(1, Hex.Decode("040000000000000000000292FE77E70C12A4234C33"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT163R2_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT163R2Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 163; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT163FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT163R2Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT163R2Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(163, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 163; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 163; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 3; }
+ }
+
+ public virtual int K2
+ {
+ get { return 6; }
+ }
+
+ public virtual int K3
+ {
+ get { return 7; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT163R2Point.cs b/crypto/src/math/ec/custom/sec/SecT163R2Point.cs
new file mode 100644
index 000000000..07b3f1fd9
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT163R2Point.cs
@@ -0,0 +1,290 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT163R2Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT163R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT163R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT163R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT163R2Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ {
+ return Twice();
+ }
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ return new SecT163R2Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT163R2Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT163R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq);
+ if (T.IsZero)
+ {
+ return new SecT163R2Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT163R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ {
+ return b;
+ }
+ if (b.IsInfinity)
+ {
+ return Twice();
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT163R2Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT163R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT163R2Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs
new file mode 100644
index 000000000..165fadbf3
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT233Field
+ {
+ private const ulong M41 = ulong.MaxValue >> 23;
+ private const ulong M59 = ulong.MaxValue >> 5;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ zz[0] = xx[0] ^ yy[0];
+ zz[1] = xx[1] ^ yy[1];
+ zz[2] = xx[2] ^ yy[2];
+ zz[3] = xx[3] ^ yy[3];
+ zz[4] = xx[4] ^ yy[4];
+ zz[5] = xx[5] ^ yy[5];
+ zz[6] = xx[6] ^ yy[6];
+ zz[7] = xx[7] ^ yy[7];
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat256.FromBigInteger64(x);
+ Reduce23(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3];
+ ulong x4 = xx[4], x5 = xx[5], x6 = xx[6], x7 = xx[7];
+
+ x3 ^= (x7 << 23);
+ x4 ^= (x7 >> 41) ^ (x7 << 33);
+ x5 ^= (x7 >> 31);
+
+ x2 ^= (x6 << 23);
+ x3 ^= (x6 >> 41) ^ (x6 << 33);
+ x4 ^= (x6 >> 31);
+
+ x1 ^= (x5 << 23);
+ x2 ^= (x5 >> 41) ^ (x5 << 33);
+ x3 ^= (x5 >> 31);
+
+ x0 ^= (x4 << 23);
+ x1 ^= (x4 >> 41) ^ (x4 << 33);
+ x2 ^= (x4 >> 31);
+
+ ulong t = x3 >> 41;
+ z[0] = x0 ^ t;
+ z[1] = x1 ^ (t << 10);
+ z[2] = x2;
+ z[3] = x3 & M41;
+ }
+
+ public static void Reduce23(ulong[] z, int zOff)
+ {
+ ulong z3 = z[zOff + 3], t = z3 >> 41;
+ z[zOff ] ^= t;
+ z[zOff + 1] ^= (t << 10);
+ z[zOff + 3] = z3 & M41;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat256.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplCompactExt(ulong[] zz)
+ {
+ ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7];
+ zz[0] = z0 ^ (z1 << 59);
+ zz[1] = (z1 >> 5) ^ (z2 << 54);
+ zz[2] = (z2 >> 10) ^ (z3 << 49);
+ zz[3] = (z3 >> 15) ^ (z4 << 44);
+ zz[4] = (z4 >> 20) ^ (z5 << 39);
+ zz[5] = (z5 >> 25) ^ (z6 << 34);
+ zz[6] = (z6 >> 30) ^ (z7 << 29);
+ zz[7] = (z7 >> 35);
+ }
+
+ protected static void ImplExpand(ulong[] x, ulong[] z)
+ {
+ ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+ z[0] = x0 & M59;
+ z[1] = ((x0 >> 59) ^ (x1 << 5)) & M59;
+ z[2] = ((x1 >> 54) ^ (x2 << 10)) & M59;
+ z[3] = ((x2 >> 49) ^ (x3 << 15));
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ /*
+ * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein.
+ */
+
+ ulong[] f = new ulong[4], g = new ulong[4];
+ ImplExpand(x, f);
+ ImplExpand(y, g);
+
+ ImplMulwAcc(f[0], g[0], zz, 0);
+ ImplMulwAcc(f[1], g[1], zz, 1);
+ ImplMulwAcc(f[2], g[2], zz, 2);
+ ImplMulwAcc(f[3], g[3], zz, 3);
+
+ // U *= (1 - t^n)
+ for (int i = 5; i > 0; --i)
+ {
+ zz[i] ^= zz[i - 1];
+ }
+
+ ImplMulwAcc(f[0] ^ f[1], g[0] ^ g[1], zz, 1);
+ ImplMulwAcc(f[2] ^ f[3], g[2] ^ g[3], zz, 3);
+
+ // V *= (1 - t^2n)
+ for (int i = 7; i > 1; --i)
+ {
+ zz[i] ^= zz[i - 2];
+ }
+
+ // Double-length recursion
+ {
+ ulong c0 = f[0] ^ f[2], c1 = f[1] ^ f[3];
+ ulong d0 = g[0] ^ g[2], d1 = g[1] ^ g[3];
+ ImplMulwAcc(c0 ^ c1, d0 ^ d1, zz, 3);
+ ulong[] t = new ulong[3];
+ ImplMulwAcc(c0, d0, t, 0);
+ ImplMulwAcc(c1, d1, t, 1);
+ ulong t0 = t[0], t1 = t[1], t2 = t[2];
+ zz[2] ^= t0;
+ zz[3] ^= t0 ^ t1;
+ zz[4] ^= t2 ^ t1;
+ zz[5] ^= t2;
+ }
+
+ ImplCompactExt(zz);
+ }
+
+ protected static void ImplMulwAcc(ulong x, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(x >> 59 == 0);
+ Debug.Assert(y >> 59 == 0);
+
+ ulong[] u = new ulong[8];
+ // u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 7]
+ ^ (u[(j >> 3) & 7] << 3);
+ int k = 54;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 6) > 0);
+
+ Debug.Assert(h >> 53 == 0);
+
+ z[zOff ] ^= l & M59;
+ z[zOff + 1] ^= (l >> 59) ^ (h << 5);
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ Interleave.Expand64To128(x[0], zz, 0);
+ Interleave.Expand64To128(x[1], zz, 2);
+ Interleave.Expand64To128(x[2], zz, 4);
+
+ ulong x3 = x[3];
+ zz[6] = Interleave.Expand32to64((uint)x3);
+ zz[7] = Interleave.Expand16to32((uint)(x3 >> 32));
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
new file mode 100644
index 000000000..439c41d37
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT233FieldElement
+ : ECFieldElement
+ {
+ protected readonly ulong[] x;
+
+ public SecT233FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT233FieldElement", "x");
+
+ this.x = SecT233Field.FromBigInteger(x);
+ }
+
+ public SecT233FieldElement()
+ {
+ this.x = Nat256.Create64();
+ }
+
+ protected internal SecT233FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat256.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat256.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1UL) != 0UL;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat256.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT233Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 233; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat256.Create64();
+ SecT233Field.Add(x, ((SecT233FieldElement)b).x, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat256.Create64();
+ SecT233Field.AddOne(x, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and Subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat256.Create64();
+ SecT233Field.Multiply(x, ((SecT233FieldElement)b).x, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT233FieldElement)b).x;
+ ulong[] xx = ((SecT233FieldElement)x).x, yx = ((SecT233FieldElement)y).x;
+
+ ulong[] tt = Nat256.CreateExt64();
+ SecT233Field.MultiplyAddToExt(ax, bx, tt);
+ SecT233Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat256.Create64();
+ SecT233Field.Reduce(tt, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat256.Create64();
+ SecT233Field.Square(x, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT233FieldElement)x).x, yx = ((SecT233FieldElement)y).x;
+
+ ulong[] tt = Nat256.CreateExt64();
+ SecT233Field.SquareAddToExt(ax, tt);
+ SecT233Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat256.Create64();
+ SecT233Field.Reduce(tt, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat256.Create64();
+ SecT233Field.SquareN(x, pow, z);
+ return new SecT233FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT233FieldElement(
+ AbstractF2mCurve.Inverse(233, new int[] { 74 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Tpb; }
+ }
+
+ public virtual int M
+ {
+ get { return 233; }
+ }
+
+ public virtual int K1
+ {
+ get { return 74; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT233FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT233FieldElement);
+ }
+
+ public virtual bool Equals(SecT233FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat256.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 2330074 ^ Arrays.GetHashCode(x, 0, 4);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
new file mode 100644
index 000000000..8768eaa81
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
@@ -0,0 +1,196 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT233K1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT233K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT233K1Point m_infinity;
+
+ public SecT233K1Curve()
+ : base(233, 74, 0, 0)
+ {
+ this.m_infinity = new SecT233K1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.Zero);
+ this.m_b = FromBigInteger(BigInteger.One);
+ this.m_order = new BigInteger(1, Hex.Decode("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF"));
+ this.m_cofactor = BigInteger.ValueOf(4);
+
+ this.m_coord = SecT233K1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT233K1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected override ECMultiplier CreateDefaultMultiplier()
+ {
+ return new WTauNafMultiplier();
+ }
+
+ public override int FieldSize
+ {
+ get { return 233; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT233FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT233K1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT233K1Point(this, x, y, zs, withCompression);
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return true; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(233, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 233; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 233; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 74; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT233K1Point.cs b/crypto/src/math/ec/custom/sec/SecT233K1Point.cs
new file mode 100644
index 000000000..7e7ee8f0b
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT233K1Point.cs
@@ -0,0 +1,302 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT233K1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT233K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT233K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT233K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT233K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ {
+ return curve.Infinity;
+ }
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1);
+ if (X3.IsZero)
+ {
+ //return new SecT233K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT233K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT233K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT233K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT233K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ {
+ return this;
+ }
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T;
+ if (Z1IsOne)
+ {
+ T = L1.Square().Add(L1);
+ }
+ else
+ {
+ T = L1.Add(Z1).Multiply(L1);
+ }
+
+ if (T.IsZero)
+ {
+ //return new SecT233K1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT233K1Point(curve, T, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement t1 = L1.Add(X1).Square();
+ ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square();
+ ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+ return new SecT233K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ // NOTE: TwicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = L1Sq.Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ {
+ return b.Twice();
+ }
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT233K1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT233K1Point(curve, A, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT233K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT233K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
new file mode 100644
index 000000000..92795b8a7
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT233R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT233R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT233R1Point m_infinity;
+
+ public SecT233R1Curve()
+ : base(233, 74, 0, 0)
+ {
+ this.m_infinity = new SecT233R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.One);
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD")));
+ this.m_order = new BigInteger(1, Hex.Decode("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT233R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT233R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 233; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT233FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT233R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT233R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(233, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 233; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 233; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 74; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT233R1Point.cs b/crypto/src/math/ec/custom/sec/SecT233R1Point.cs
new file mode 100644
index 000000000..ffac89d15
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT233R1Point.cs
@@ -0,0 +1,282 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT233R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT233R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT233R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT233R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT233R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ return new SecT233R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT233R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT233R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq);
+ if (T.IsZero)
+ {
+ return new SecT233R1Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT233R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT233R1Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT233R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT233R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs
new file mode 100644
index 000000000..1e0824af9
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT239Field
+ {
+ private const ulong M47 = ulong.MaxValue >> 17;
+ private const ulong M60 = ulong.MaxValue >> 4;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ zz[0] = xx[0] ^ yy[0];
+ zz[1] = xx[1] ^ yy[1];
+ zz[2] = xx[2] ^ yy[2];
+ zz[3] = xx[3] ^ yy[3];
+ zz[4] = xx[4] ^ yy[4];
+ zz[5] = xx[5] ^ yy[5];
+ zz[6] = xx[6] ^ yy[6];
+ zz[7] = xx[7] ^ yy[7];
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat256.FromBigInteger64(x);
+ Reduce17(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3];
+ ulong x4 = xx[4], x5 = xx[5], x6 = xx[6], x7 = xx[7];
+
+ x3 ^= (x7 << 17);
+ x4 ^= (x7 >> 47);
+ x5 ^= (x7 << 47);
+ x6 ^= (x7 >> 17);
+
+ x2 ^= (x6 << 17);
+ x3 ^= (x6 >> 47);
+ x4 ^= (x6 << 47);
+ x5 ^= (x6 >> 17);
+
+ x1 ^= (x5 << 17);
+ x2 ^= (x5 >> 47);
+ x3 ^= (x5 << 47);
+ x4 ^= (x5 >> 17);
+
+ x0 ^= (x4 << 17);
+ x1 ^= (x4 >> 47);
+ x2 ^= (x4 << 47);
+ x3 ^= (x4 >> 17);
+
+ ulong t = x3 >> 47;
+ z[0] = x0 ^ t;
+ z[1] = x1;
+ z[2] = x2 ^ (t << 30);
+ z[3] = x3 & M47;
+ }
+
+ public static void Reduce17(ulong[] z, int zOff)
+ {
+ ulong z3 = z[zOff + 3], t = z3 >> 47;
+ z[zOff ] ^= t;
+ z[zOff + 2] ^= (t << 30);
+ z[zOff + 3] = z3 & M47;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat256.CreateExt64();
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat256.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplCompactExt(ulong[] zz)
+ {
+ ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7];
+ zz[0] = z0 ^ (z1 << 60);
+ zz[1] = (z1 >> 4) ^ (z2 << 56);
+ zz[2] = (z2 >> 8) ^ (z3 << 52);
+ zz[3] = (z3 >> 12) ^ (z4 << 48);
+ zz[4] = (z4 >> 16) ^ (z5 << 44);
+ zz[5] = (z5 >> 20) ^ (z6 << 40);
+ zz[6] = (z6 >> 24) ^ (z7 << 36);
+ zz[7] = (z7 >> 28);
+ }
+
+ protected static void ImplExpand(ulong[] x, ulong[] z)
+ {
+ ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+ z[0] = x0 & M60;
+ z[1] = ((x0 >> 60) ^ (x1 << 4)) & M60;
+ z[2] = ((x1 >> 56) ^ (x2 << 8)) & M60;
+ z[3] = ((x2 >> 52) ^ (x3 << 12));
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ /*
+ * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein.
+ */
+
+ ulong[] f = new ulong[4], g = new ulong[4];
+ ImplExpand(x, f);
+ ImplExpand(y, g);
+
+ ImplMulwAcc(f[0], g[0], zz, 0);
+ ImplMulwAcc(f[1], g[1], zz, 1);
+ ImplMulwAcc(f[2], g[2], zz, 2);
+ ImplMulwAcc(f[3], g[3], zz, 3);
+
+ // U *= (1 - t^n)
+ for (int i = 5; i > 0; --i)
+ {
+ zz[i] ^= zz[i - 1];
+ }
+
+ ImplMulwAcc(f[0] ^ f[1], g[0] ^ g[1], zz, 1);
+ ImplMulwAcc(f[2] ^ f[3], g[2] ^ g[3], zz, 3);
+
+ // V *= (1 - t^2n)
+ for (int i = 7; i > 1; --i)
+ {
+ zz[i] ^= zz[i - 2];
+ }
+
+ // Double-length recursion
+ {
+ ulong c0 = f[0] ^ f[2], c1 = f[1] ^ f[3];
+ ulong d0 = g[0] ^ g[2], d1 = g[1] ^ g[3];
+ ImplMulwAcc(c0 ^ c1, d0 ^ d1, zz, 3);
+ ulong[] t = new ulong[3];
+ ImplMulwAcc(c0, d0, t, 0);
+ ImplMulwAcc(c1, d1, t, 1);
+ ulong t0 = t[0], t1 = t[1], t2 = t[2];
+ zz[2] ^= t0;
+ zz[3] ^= t0 ^ t1;
+ zz[4] ^= t2 ^ t1;
+ zz[5] ^= t2;
+ }
+
+ ImplCompactExt(zz);
+ }
+
+ protected static void ImplMulwAcc(ulong x, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(x >> 60 == 0);
+ Debug.Assert(y >> 60 == 0);
+
+ ulong[] u = new ulong[8];
+ // u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 7]
+ ^ (u[(j >> 3) & 7] << 3);
+ int k = 54;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 6) > 0);
+
+ h ^= ((x & 0x0820820820820820L) & (ulong)(((long)y << 4) >> 63)) >> 5;
+
+ Debug.Assert(h >> 55 == 0);
+
+ z[zOff ] ^= l & M60;
+ z[zOff + 1] ^= (l >> 60) ^ (h << 4);
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ Interleave.Expand64To128(x[0], zz, 0);
+ Interleave.Expand64To128(x[1], zz, 2);
+ Interleave.Expand64To128(x[2], zz, 4);
+
+ ulong x3 = x[3];
+ zz[6] = Interleave.Expand32to64((uint)x3);
+ zz[7] = Interleave.Expand16to32((uint)(x3 >> 32));
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
new file mode 100644
index 000000000..c89b484b1
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT239FieldElement
+ : ECFieldElement
+ {
+ protected ulong[] x;
+
+ public SecT239FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT239FieldElement", "x");
+
+ this.x = SecT239Field.FromBigInteger(x);
+ }
+
+ public SecT239FieldElement()
+ {
+ this.x = Nat256.Create64();
+ }
+
+ protected internal SecT239FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat256.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat256.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1L) != 0L;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat256.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT239Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 239; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat256.Create64();
+ SecT239Field.Add(x, ((SecT239FieldElement)b).x, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat256.Create64();
+ SecT239Field.AddOne(x, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and Subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat256.Create64();
+ SecT239Field.Multiply(x, ((SecT239FieldElement)b).x, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT239FieldElement)b).x;
+ ulong[] xx = ((SecT239FieldElement)x).x, yx = ((SecT239FieldElement)y).x;
+
+ ulong[] tt = Nat256.CreateExt64();
+ SecT239Field.MultiplyAddToExt(ax, bx, tt);
+ SecT239Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat256.Create64();
+ SecT239Field.Reduce(tt, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat256.Create64();
+ SecT239Field.Square(x, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT239FieldElement)x).x, yx = ((SecT239FieldElement)y).x;
+
+ ulong[] tt = Nat256.CreateExt64();
+ SecT239Field.SquareAddToExt(ax, tt);
+ SecT239Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat256.Create64();
+ SecT239Field.Reduce(tt, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat256.Create64();
+ SecT239Field.SquareN(x, pow, z);
+ return new SecT239FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT239FieldElement(
+ AbstractF2mCurve.Inverse(239, new int[] { 158 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Tpb; }
+ }
+
+ public virtual int M
+ {
+ get { return 239; }
+ }
+
+ public virtual int K1
+ {
+ get { return 158; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT239FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT239FieldElement);
+ }
+
+ public virtual bool Equals(SecT239FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat256.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 23900158 ^ Arrays.GetHashCode(x, 0, 4);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
new file mode 100644
index 000000000..2c73d941f
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
@@ -0,0 +1,194 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT239K1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT239K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT239K1Point m_infinity;
+
+ public SecT239K1Curve()
+ : base(239, 158, 0, 0)
+ {
+ this.m_infinity = new SecT239K1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.Zero);
+ this.m_b = FromBigInteger(BigInteger.One);
+ this.m_order = new BigInteger(1, Hex.Decode("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5"));
+ this.m_cofactor = BigInteger.ValueOf(4);
+
+ this.m_coord = SecT239K1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT239K1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected override ECMultiplier CreateDefaultMultiplier()
+ {
+ return new WTauNafMultiplier();
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 239; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT239FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT239K1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT239K1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return true; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(239, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 239; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 239; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 158; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT239K1Point.cs b/crypto/src/math/ec/custom/sec/SecT239K1Point.cs
new file mode 100644
index 000000000..ac079ad1e
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT239K1Point.cs
@@ -0,0 +1,297 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT239K1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT239K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT239K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT239K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT239K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ // X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1);
+ if (X3.IsZero)
+ {
+ //return new SecT239K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT239K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT239K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT239K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT239K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T;
+ if (Z1IsOne)
+ {
+ T = L1.Square().Add(L1);
+ }
+ else
+ {
+ T = L1.Add(Z1).Multiply(L1);
+ }
+
+ if (T.IsZero)
+ {
+ //return new SecT239K1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT239K1Point(curve, T, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement t1 = L1.Add(X1).Square();
+ ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square();
+ ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+ return new SecT239K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ // NOTE: TwicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = L1Sq.Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT239K1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT239K1Point(curve, A, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT239K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT239K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs
new file mode 100644
index 000000000..9afb27461
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT283Field
+ {
+ private const ulong M27 = ulong.MaxValue >> 37;
+ private const ulong M57 = ulong.MaxValue >> 7;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
+ z[4] = x[4] ^ y[4];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ zz[0] = xx[0] ^ yy[0];
+ zz[1] = xx[1] ^ yy[1];
+ zz[2] = xx[2] ^ yy[2];
+ zz[3] = xx[3] ^ yy[3];
+ zz[4] = xx[4] ^ yy[4];
+ zz[5] = xx[5] ^ yy[5];
+ zz[6] = xx[6] ^ yy[6];
+ zz[7] = xx[7] ^ yy[7];
+ zz[8] = xx[8] ^ yy[8];
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat320.FromBigInteger64(x);
+ Reduce37(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat320.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat320.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4];
+ ulong x5 = xx[5], x6 = xx[6], x7 = xx[7], x8 = xx[8];
+
+ x3 ^= (x8 << 37) ^ (x8 << 42) ^ (x8 << 44) ^ (x8 << 49);
+ x4 ^= (x8 >> 27) ^ (x8 >> 22) ^ (x8 >> 20) ^ (x8 >> 15);
+
+ x2 ^= (x7 << 37) ^ (x7 << 42) ^ (x7 << 44) ^ (x7 << 49);
+ x3 ^= (x7 >> 27) ^ (x7 >> 22) ^ (x7 >> 20) ^ (x7 >> 15);
+
+ x1 ^= (x6 << 37) ^ (x6 << 42) ^ (x6 << 44) ^ (x6 << 49);
+ x2 ^= (x6 >> 27) ^ (x6 >> 22) ^ (x6 >> 20) ^ (x6 >> 15);
+
+ x0 ^= (x5 << 37) ^ (x5 << 42) ^ (x5 << 44) ^ (x5 << 49);
+ x1 ^= (x5 >> 27) ^ (x5 >> 22) ^ (x5 >> 20) ^ (x5 >> 15);
+
+ ulong t = x4 >> 27;
+ z[0] = x0 ^ t ^ (t << 5) ^ (t << 7) ^ (t << 12);
+ z[1] = x1;
+ z[2] = x2;
+ z[3] = x3;
+ z[4] = x4 & M27;
+ }
+
+ public static void Reduce37(ulong[] z, int zOff)
+ {
+ ulong z4 = z[zOff + 4], t = z4 >> 27;
+ z[zOff ] ^= t ^ (t << 5) ^ (t << 7) ^ (t << 12);
+ z[zOff + 4] = z4 & M27;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat.Create64(9);
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat.Create64(9);
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat.Create64(9);
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplCompactExt(ulong[] zz)
+ {
+ ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4];
+ ulong z5 = zz[5], z6 = zz[6], z7 = zz[7], z8 = zz[8], z9 = zz[9];
+ zz[0] = z0 ^ (z1 << 57);
+ zz[1] = (z1 >> 7) ^ (z2 << 50);
+ zz[2] = (z2 >> 14) ^ (z3 << 43);
+ zz[3] = (z3 >> 21) ^ (z4 << 36);
+ zz[4] = (z4 >> 28) ^ (z5 << 29);
+ zz[5] = (z5 >> 35) ^ (z6 << 22);
+ zz[6] = (z6 >> 42) ^ (z7 << 15);
+ zz[7] = (z7 >> 49) ^ (z8 << 8);
+ zz[8] = (z8 >> 56) ^ (z9 << 1);
+ zz[9] = (z9 >> 63); // Zero!
+ }
+
+ protected static void ImplExpand(ulong[] x, ulong[] z)
+ {
+ ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4];
+ z[0] = x0 & M57;
+ z[1] = ((x0 >> 57) ^ (x1 << 7)) & M57;
+ z[2] = ((x1 >> 50) ^ (x2 << 14)) & M57;
+ z[3] = ((x2 >> 43) ^ (x3 << 21)) & M57;
+ z[4] = ((x3 >> 36) ^ (x4 << 28));
+ }
+
+ //protected static void AddMs(ulong[] zz, int zOff, ulong[] p, params int[] ms)
+ //{
+ // ulong t0 = 0, t1 = 0;
+ // foreach (int m in ms)
+ // {
+ // int i = (m - 1) << 1;
+ // t0 ^= p[i ];
+ // t1 ^= p[i + 1];
+ // }
+ // zz[zOff ] ^= t0;
+ // zz[zOff + 1] ^= t1;
+ //}
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ /*
+ * Formula (17) from "Some New Results on Binary Polynomial Multiplication",
+ * Murat Cenk and M. Anwar Hasan.
+ *
+ * The formula as given contained an error in the term t25, as noted below
+ */
+ ulong[] a = new ulong[5], b = new ulong[5];
+ ImplExpand(x, a);
+ ImplExpand(y, b);
+
+ ulong[] p = new ulong[26];
+
+ ImplMulw(a[0], b[0], p, 0); // m1
+ ImplMulw(a[1], b[1], p, 2); // m2
+ ImplMulw(a[2], b[2], p, 4); // m3
+ ImplMulw(a[3], b[3], p, 6); // m4
+ ImplMulw(a[4], b[4], p, 8); // m5
+
+ ulong u0 = a[0] ^ a[1], v0 = b[0] ^ b[1];
+ ulong u1 = a[0] ^ a[2], v1 = b[0] ^ b[2];
+ ulong u2 = a[2] ^ a[4], v2 = b[2] ^ b[4];
+ ulong u3 = a[3] ^ a[4], v3 = b[3] ^ b[4];
+
+ ImplMulw(u1 ^ a[3], v1 ^ b[3], p, 18); // m10
+ ImplMulw(u2 ^ a[1], v2 ^ b[1], p, 20); // m11
+
+ ulong A4 = u0 ^ u3 , B4 = v0 ^ v3;
+ ulong A5 = A4 ^ a[2], B5 = B4 ^ b[2];
+
+ ImplMulw(A4, B4, p, 22); // m12
+ ImplMulw(A5, B5, p, 24); // m13
+
+ ImplMulw(u0, v0, p, 10); // m6
+ ImplMulw(u1, v1, p, 12); // m7
+ ImplMulw(u2, v2, p, 14); // m8
+ ImplMulw(u3, v3, p, 16); // m9
+
+
+ // Original method, corresponding to formula (16)
+ //AddMs(zz, 0, p, 1);
+ //AddMs(zz, 1, p, 1, 2, 6);
+ //AddMs(zz, 2, p, 1, 2, 3, 7);
+ //AddMs(zz, 3, p, 1, 3, 4, 5, 8, 10, 12, 13);
+ //AddMs(zz, 4, p, 1, 2, 4, 5, 6, 9, 10, 11, 13);
+ //AddMs(zz, 5, p, 1, 2, 3, 5, 7, 11, 12, 13);
+ //AddMs(zz, 6, p, 3, 4, 5, 8);
+ //AddMs(zz, 7, p, 4, 5, 9);
+ //AddMs(zz, 8, p, 5);
+
+ // Improved method factors out common single-word terms
+ // NOTE: p1,...,p26 in the paper maps to p[0],...,p[25] here
+
+ zz[0] = p[ 0];
+ zz[9] = p[ 9];
+
+ ulong t1 = p[ 0] ^ p[ 1];
+ ulong t2 = t1 ^ p[ 2];
+ ulong t3 = t2 ^ p[10];
+
+ zz[1] = t3;
+
+ ulong t4 = p[ 3] ^ p[ 4];
+ ulong t5 = p[11] ^ p[12];
+ ulong t6 = t4 ^ t5;
+ ulong t7 = t2 ^ t6;
+
+ zz[2] = t7;
+
+ ulong t8 = t1 ^ t4;
+ ulong t9 = p[ 5] ^ p[ 6];
+ ulong t10 = t8 ^ t9;
+ ulong t11 = t10 ^ p[ 8];
+ ulong t12 = p[13] ^ p[14];
+ ulong t13 = t11 ^ t12;
+ ulong t14 = p[18] ^ p[22];
+ ulong t15 = t14 ^ p[24];
+ ulong t16 = t13 ^ t15;
+
+ zz[3] = t16;
+
+ ulong t17 = p[ 7] ^ p[ 8];
+ ulong t18 = t17 ^ p[ 9];
+ ulong t19 = t18 ^ p[17];
+
+ zz[8] = t19;
+
+ ulong t20 = t18 ^ t9;
+ ulong t21 = p[15] ^ p[16];
+ ulong t22 = t20 ^ t21;
+
+ zz[7] = t22;
+
+ ulong t23 = t22 ^ t3;
+ ulong t24 = p[19] ^ p[20];
+ // ulong t25 = p[23] ^ p[24];
+ ulong t25 = p[25] ^ p[24]; // Fixes an error in the paper: p[23] -> p{25]
+ ulong t26 = p[18] ^ p[23];
+ ulong t27 = t24 ^ t25;
+ ulong t28 = t27 ^ t26;
+ ulong t29 = t28 ^ t23;
+
+ zz[4] = t29;
+
+ ulong t30 = t7 ^ t19;
+ ulong t31 = t27 ^ t30;
+ ulong t32 = p[21] ^ p[22];
+ ulong t33 = t31 ^ t32;
+
+ zz[5] = t33;
+
+ ulong t34 = t11 ^ p[0];
+ ulong t35 = t34 ^ p[9];
+ ulong t36 = t35 ^ t12;
+ ulong t37 = t36 ^ p[21];
+ ulong t38 = t37 ^ p[23];
+ ulong t39 = t38 ^ p[25];
+
+ zz[6] = t39;
+
+ ImplCompactExt(zz);
+ }
+
+ protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(x >> 57 == 0);
+ Debug.Assert(y >> 57 == 0);
+
+ ulong[] u = new ulong[8];
+ // u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 7];
+ int k = 48;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3
+ ^ u[(j >> 6) & 7] << 6;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 9) > 0);
+
+ h ^= ((x & 0x0100804020100800L) & (ulong)(((long)y << 7) >> 63)) >> 8;
+
+ Debug.Assert(h >> 49 == 0);
+
+ z[zOff ] = l & M57;
+ z[zOff + 1] = (l >> 57) ^ (h << 7);
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ for (int i = 0; i < 4; ++i)
+ {
+ Interleave.Expand64To128(x[i], zz, i << 1);
+ }
+ zz[8] = Interleave.Expand32to64((uint)x[4]);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
new file mode 100644
index 000000000..09243e859
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT283FieldElement
+ : ECFieldElement
+ {
+ protected readonly ulong[] x;
+
+ public SecT283FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT283FieldElement", "x");
+
+ this.x = SecT283Field.FromBigInteger(x);
+ }
+
+ public SecT283FieldElement()
+ {
+ this.x = Nat320.Create64();
+ }
+
+ protected internal SecT283FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat320.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat320.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1UL) != 0UL;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat320.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT283Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 283; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat320.Create64();
+ SecT283Field.Add(x, ((SecT283FieldElement)b).x, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat320.Create64();
+ SecT283Field.AddOne(x, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat320.Create64();
+ SecT283Field.Multiply(x, ((SecT283FieldElement)b).x, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT283FieldElement)b).x;
+ ulong[] xx = ((SecT283FieldElement)x).x, yx = ((SecT283FieldElement)y).x;
+
+ ulong[] tt = Nat.Create64(9);
+ SecT283Field.MultiplyAddToExt(ax, bx, tt);
+ SecT283Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat320.Create64();
+ SecT283Field.Reduce(tt, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat320.Create64();
+ SecT283Field.Square(x, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT283FieldElement)x).x, yx = ((SecT283FieldElement)y).x;
+
+ ulong[] tt = Nat.Create64(9);
+ SecT283Field.SquareAddToExt(ax, tt);
+ SecT283Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat320.Create64();
+ SecT283Field.Reduce(tt, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat320.Create64();
+ SecT283Field.SquareN(x, pow, z);
+ return new SecT283FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT283FieldElement(
+ AbstractF2mCurve.Inverse(283, new int[] { 5, 7, 12 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Ppb; }
+ }
+
+ public virtual int M
+ {
+ get { return 283; }
+ }
+
+ public virtual int K1
+ {
+ get { return 5; }
+ }
+
+ public virtual int K2
+ {
+ get { return 7; }
+ }
+
+ public virtual int K3
+ {
+ get { return 12; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT283FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT283FieldElement);
+ }
+
+ public virtual bool Equals(SecT283FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat320.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 2831275 ^ Arrays.GetHashCode(x, 0, 5);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
new file mode 100644
index 000000000..42414401f
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
@@ -0,0 +1,194 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT283K1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT283K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT283K1Point m_infinity;
+
+ public SecT283K1Curve()
+ : base(283, 5, 7, 12)
+ {
+ this.m_infinity = new SecT283K1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.Zero);
+ this.m_b = FromBigInteger(BigInteger.One);
+ this.m_order = new BigInteger(1, Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61"));
+ this.m_cofactor = BigInteger.ValueOf(4);
+
+ this.m_coord = SecT283K1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT283K1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected override ECMultiplier CreateDefaultMultiplier()
+ {
+ return new WTauNafMultiplier();
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 283; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT283FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT283K1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT283K1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return true; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(283, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 283; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 283; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 5; }
+ }
+
+ public virtual int K2
+ {
+ get { return 7; }
+ }
+
+ public virtual int K3
+ {
+ get { return 12; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT283K1Point.cs b/crypto/src/math/ec/custom/sec/SecT283K1Point.cs
new file mode 100644
index 000000000..f85706c63
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT283K1Point.cs
@@ -0,0 +1,296 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT283K1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT283K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1);
+ if (X3.IsZero)
+ {
+ //return new SecT283K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT283K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT283K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT283K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T;
+ if (Z1IsOne)
+ {
+ T = L1.Square().Add(L1);
+ }
+ else
+ {
+ T = L1.Add(Z1).Multiply(L1);
+ }
+
+ if (T.IsZero)
+ {
+ //return new SecT283K1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT283K1Point(curve, T, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement t1 = L1.Add(X1).Square();
+ ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square();
+ ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+ return new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ // NOTE: TwicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = L1Sq.Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT283K1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT283K1Point(curve, A, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT283K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
new file mode 100644
index 000000000..d8c462eeb
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT283R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT283R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT283R1Point m_infinity;
+
+ public SecT283R1Curve()
+ : base(283, 5, 7, 12)
+ {
+ this.m_infinity = new SecT283R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.One);
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5")));
+ this.m_order = new BigInteger(1, Hex.Decode("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT283R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT283R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 283; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT283FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT283R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT283R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(283, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 283; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 283; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 5; }
+ }
+
+ public virtual int K2
+ {
+ get { return 7; }
+ }
+
+ public virtual int K3
+ {
+ get { return 12; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT283R1Point.cs b/crypto/src/math/ec/custom/sec/SecT283R1Point.cs
new file mode 100644
index 000000000..340bbdae6
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT283R1Point.cs
@@ -0,0 +1,282 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT283R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT283R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT283R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT283R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT283R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ return new SecT283R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT283R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT283R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq);
+ if (T.IsZero)
+ {
+ return new SecT283R1Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT283R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT283R1Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT283R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT283R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs
new file mode 100644
index 000000000..d71f5b5f9
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs
@@ -0,0 +1,244 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT409Field
+ {
+ private const ulong M25 = ulong.MaxValue >> 39;
+ private const ulong M59 = ulong.MaxValue >> 5;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
+ z[4] = x[4] ^ y[4];
+ z[5] = x[5] ^ y[5];
+ z[6] = x[6] ^ y[6];
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ for (int i = 0; i < 13; ++i)
+ {
+ zz[i] = xx[i] ^ yy[i];
+ }
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ z[6] = x[6];
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat448.FromBigInteger64(x);
+ Reduce39(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat448.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat448.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong x00 = xx[0], x01 = xx[1], x02 = xx[2], x03 = xx[3];
+ ulong x04 = xx[4], x05 = xx[5], x06 = xx[6], x07 = xx[7];
+
+ ulong u = xx[12];
+ x05 ^= (u << 39);
+ x06 ^= (u >> 25) ^ (u << 62);
+ x07 ^= (u >> 2);
+
+ u = xx[11];
+ x04 ^= (u << 39);
+ x05 ^= (u >> 25) ^ (u << 62);
+ x06 ^= (u >> 2);
+
+ u = xx[10];
+ x03 ^= (u << 39);
+ x04 ^= (u >> 25) ^ (u << 62);
+ x05 ^= (u >> 2);
+
+ u = xx[9];
+ x02 ^= (u << 39);
+ x03 ^= (u >> 25) ^ (u << 62);
+ x04 ^= (u >> 2);
+
+ u = xx[8];
+ x01 ^= (u << 39);
+ x02 ^= (u >> 25) ^ (u << 62);
+ x03 ^= (u >> 2);
+
+ u = x07;
+ x00 ^= (u << 39);
+ x01 ^= (u >> 25) ^ (u << 62);
+ x02 ^= (u >> 2);
+
+ ulong t = x06 >> 25;
+ z[0] = x00 ^ t;
+ z[1] = x01 ^ (t << 23);
+ z[2] = x02;
+ z[3] = x03;
+ z[4] = x04;
+ z[5] = x05;
+ z[6] = x06 & M25;
+ }
+
+ public static void Reduce39(ulong[] z, int zOff)
+ {
+ ulong z6 = z[zOff + 6], t = z6 >> 25;
+ z[zOff ] ^= t;
+ z[zOff + 1] ^= (t << 23);
+ z[zOff + 6] = z6 & M25;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat.Create64(13);
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat.Create64(13);
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat.Create64(13);
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplCompactExt(ulong[] zz)
+ {
+ ulong z00 = zz[ 0], z01 = zz[ 1], z02 = zz[ 2], z03 = zz[ 3], z04 = zz[ 4], z05 = zz[ 5], z06 = zz[ 6];
+ ulong z07 = zz[ 7], z08 = zz[ 8], z09 = zz[ 9], z10 = zz[10], z11 = zz[11], z12 = zz[12], z13 = zz[13];
+ zz[ 0] = z00 ^ (z01 << 59);
+ zz[ 1] = (z01 >> 5) ^ (z02 << 54);
+ zz[ 2] = (z02 >> 10) ^ (z03 << 49);
+ zz[ 3] = (z03 >> 15) ^ (z04 << 44);
+ zz[ 4] = (z04 >> 20) ^ (z05 << 39);
+ zz[ 5] = (z05 >> 25) ^ (z06 << 34);
+ zz[ 6] = (z06 >> 30) ^ (z07 << 29);
+ zz[ 7] = (z07 >> 35) ^ (z08 << 24);
+ zz[ 8] = (z08 >> 40) ^ (z09 << 19);
+ zz[ 9] = (z09 >> 45) ^ (z10 << 14);
+ zz[10] = (z10 >> 50) ^ (z11 << 9);
+ zz[11] = (z11 >> 55) ^ (z12 << 4)
+ ^ (z13 << 63);
+ zz[12] = (z12 >> 60)
+ ^ (z13 >> 1);
+ zz[13] = 0;
+ }
+
+ protected static void ImplExpand(ulong[] x, ulong[] z)
+ {
+ ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6];
+ z[0] = x0 & M59;
+ z[1] = ((x0 >> 59) ^ (x1 << 5)) & M59;
+ z[2] = ((x1 >> 54) ^ (x2 << 10)) & M59;
+ z[3] = ((x2 >> 49) ^ (x3 << 15)) & M59;
+ z[4] = ((x3 >> 44) ^ (x4 << 20)) & M59;
+ z[5] = ((x4 >> 39) ^ (x5 << 25)) & M59;
+ z[6] = ((x5 >> 34) ^ (x6 << 30));
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] a = new ulong[7], b = new ulong[7];
+ ImplExpand(x, a);
+ ImplExpand(y, b);
+
+ for (int i = 0; i < 7; ++i)
+ {
+ ImplMulwAcc(a, b[i], zz, i);
+ }
+
+ ImplCompactExt(zz);
+ }
+
+ protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff)
+ {
+ Debug.Assert(y >> 59 == 0);
+
+ ulong[] u = new ulong[8];
+ // u[0] = 0;
+ u[1] = y;
+ u[2] = u[1] << 1;
+ u[3] = u[2] ^ y;
+ u[4] = u[2] << 1;
+ u[5] = u[4] ^ y;
+ u[6] = u[3] << 1;
+ u[7] = u[6] ^ y;
+
+ for (int i = 0; i < 7; ++i)
+ {
+ ulong x = xs[i];
+
+ Debug.Assert(x >> 59 == 0);
+
+ uint j = (uint)x;
+ ulong g, h = 0, l = u[j & 7]
+ ^ (u[(j >> 3) & 7] << 3);
+ int k = 54;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 7]
+ ^ u[(j >> 3) & 7] << 3;
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 6) > 0);
+
+ Debug.Assert(h >> 53 == 0);
+
+ z[zOff + i ] ^= l & M59;
+ z[zOff + i + 1] ^= (l >> 59) ^ (h << 5);
+ }
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ for (int i = 0; i < 6; ++i)
+ {
+ Interleave.Expand64To128(x[i], zz, i << 1);
+ }
+ zz[12] = Interleave.Expand32to64((uint)x[6]);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
new file mode 100644
index 000000000..6dabf6a7a
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT409FieldElement
+ : ECFieldElement
+ {
+ protected ulong[] x;
+
+ public SecT409FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT409FieldElement", "x");
+
+ this.x = SecT409Field.FromBigInteger(x);
+ }
+
+ public SecT409FieldElement()
+ {
+ this.x = Nat448.Create64();
+ }
+
+ protected internal SecT409FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat448.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat448.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1UL) != 0UL;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat448.ToBigInteger64(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SecT409Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 409; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat448.Create64();
+ SecT409Field.Add(x, ((SecT409FieldElement)b).x, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat448.Create64();
+ SecT409Field.AddOne(x, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat448.Create64();
+ SecT409Field.Multiply(x, ((SecT409FieldElement)b).x, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT409FieldElement)b).x;
+ ulong[] xx = ((SecT409FieldElement)x).x, yx = ((SecT409FieldElement)y).x;
+
+ ulong[] tt = Nat.Create64(13);
+ SecT409Field.MultiplyAddToExt(ax, bx, tt);
+ SecT409Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat448.Create64();
+ SecT409Field.Reduce(tt, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat448.Create64();
+ SecT409Field.Square(x, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT409FieldElement)x).x, yx = ((SecT409FieldElement)y).x;
+
+ ulong[] tt = Nat.Create64(13);
+ SecT409Field.SquareAddToExt(ax, tt);
+ SecT409Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat448.Create64();
+ SecT409Field.Reduce(tt, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat448.Create64();
+ SecT409Field.SquareN(x, pow, z);
+ return new SecT409FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT409FieldElement(
+ AbstractF2mCurve.Inverse(409, new int[] { 87 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Tpb; }
+ }
+
+ public virtual int M
+ {
+ get { return 409; }
+ }
+
+ public virtual int K1
+ {
+ get { return 87; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT409FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT409FieldElement);
+ }
+
+ public virtual bool Equals(SecT409FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat448.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 4090087 ^ Arrays.GetHashCode(x, 0, 7);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
new file mode 100644
index 000000000..edfe1a293
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
@@ -0,0 +1,194 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT409K1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT409K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT409K1Point m_infinity;
+
+ public SecT409K1Curve()
+ : base(409, 87, 0, 0)
+ {
+ this.m_infinity = new SecT409K1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.Zero);
+ this.m_b = FromBigInteger(BigInteger.One);
+ this.m_order = new BigInteger(1, Hex.Decode("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF"));
+ this.m_cofactor = BigInteger.ValueOf(4);
+
+ this.m_coord = SecT409K1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT409K1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected override ECMultiplier CreateDefaultMultiplier()
+ {
+ return new WTauNafMultiplier();
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 409; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT409FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT409K1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT409K1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return true; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(409, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 409; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 409; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 87; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT409K1Point.cs b/crypto/src/math/ec/custom/sec/SecT409K1Point.cs
new file mode 100644
index 000000000..71adc7af2
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT409K1Point.cs
@@ -0,0 +1,296 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT409K1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT409K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT409K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT409K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT409K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1);
+ if (X3.IsZero)
+ {
+ //return new SecT409K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT409K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT409K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT409K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T;
+ if (Z1IsOne)
+ {
+ T = L1.Square().Add(L1);
+ }
+ else
+ {
+ T = L1.Add(Z1).Multiply(L1);
+ }
+
+ if (T.IsZero)
+ {
+ //return new SecT409K1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT409K1Point(curve, T, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement t1 = L1.Add(X1).Square();
+ ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square();
+ ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+ return new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ // NOTE: TwicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = L1Sq.Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT409K1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT409K1Point(curve, A, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT409K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
new file mode 100644
index 000000000..e679094ad
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT409R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT409R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT409R1Point m_infinity;
+
+ public SecT409R1Curve()
+ : base(409, 87, 0, 0)
+ {
+ this.m_infinity = new SecT409R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.One);
+ this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F")));
+ this.m_order = new BigInteger(1, Hex.Decode("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT409R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT409R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 409; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT409FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT409R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT409R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(409, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 409; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 409; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return true; }
+ }
+
+ public virtual int K1
+ {
+ get { return 87; }
+ }
+
+ public virtual int K2
+ {
+ get { return 0; }
+ }
+
+ public virtual int K3
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT409R1Point.cs b/crypto/src/math/ec/custom/sec/SecT409R1Point.cs
new file mode 100644
index 000000000..af69fe656
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT409R1Point.cs
@@ -0,0 +1,282 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT409R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT409R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT409R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT409R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT409R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ return new SecT409R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ return new SecT409R1Point(curve, X3, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT409R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq);
+ if (T.IsZero)
+ {
+ return new SecT409R1Point(curve, T, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT409R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ return new SecT409R1Point(curve, A, curve.B.Sqrt(), IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT409R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT409R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
new file mode 100644
index 000000000..0711ee4aa
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT571Field
+ {
+ private const ulong M59 = ulong.MaxValue >> 5;
+
+ private const ulong RM = 0xEF7BDEF7BDEF7BDEUL;
+
+ public static void Add(ulong[] x, ulong[] y, ulong[] z)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ z[i] = x[i] ^ y[i];
+ }
+ }
+
+ private static void Add(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ z[zOff + i] = x[xOff + i] ^ y[yOff + i];
+ }
+ }
+
+ private static void AddBothTo(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ z[zOff + i] ^= x[xOff + i] ^ y[yOff + i];
+ }
+ }
+
+ public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz)
+ {
+ for (int i = 0; i < 18; ++i)
+ {
+ zz[i] = xx[i] ^ yy[i];
+ }
+ }
+
+ public static void AddOne(ulong[] x, ulong[] z)
+ {
+ z[0] = x[0] ^ 1UL;
+ for (int i = 1; i < 9; ++i)
+ {
+ z[i] = x[i];
+ }
+ }
+
+ public static ulong[] FromBigInteger(BigInteger x)
+ {
+ ulong[] z = Nat576.FromBigInteger64(x);
+ Reduce5(z, 0);
+ return z;
+ }
+
+ public static void Multiply(ulong[] x, ulong[] y, ulong[] z)
+ {
+ ulong[] tt = Nat576.CreateExt64();
+ ImplMultiply(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ ulong[] tt = Nat576.CreateExt64();
+ ImplMultiply(x, y, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void Reduce(ulong[] xx, ulong[] z)
+ {
+ ulong xx09 = xx[9];
+ ulong u = xx[17], v = xx09;
+
+ xx09 = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
+ v = xx[8] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
+
+ for (int i = 16; i >= 10; --i)
+ {
+ u = xx[i];
+ z[i - 8] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
+ v = xx[i - 9] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
+ }
+
+ u = xx09;
+ z[1] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49);
+ v = xx[0] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15);
+
+ ulong x08 = z[8];
+ ulong t = x08 >> 59;
+ z[0] = v ^ t ^ (t << 2) ^ (t << 5) ^ (t << 10);
+ z[8] = x08 & M59;
+ }
+
+ public static void Reduce5(ulong[] z, int zOff)
+ {
+ ulong z8 = z[zOff + 8], t = z8 >> 59;
+ z[zOff ] ^= t ^ (t << 2) ^ (t << 5) ^ (t << 10);
+ z[zOff + 8] = z8 & M59;
+ }
+
+ public static void Square(ulong[] x, ulong[] z)
+ {
+ ulong[] tt = Nat576.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareAddToExt(ulong[] x, ulong[] zz)
+ {
+ ulong[] tt = Nat576.CreateExt64();
+ ImplSquare(x, tt);
+ AddExt(zz, tt, zz);
+ }
+
+ public static void SquareN(ulong[] x, int n, ulong[] z)
+ {
+ Debug.Assert(n > 0);
+
+ ulong[] tt = Nat576.CreateExt64();
+ ImplSquare(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ ImplSquare(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz)
+ {
+ //for (int i = 0; i < 9; ++i)
+ //{
+ // ImplMulwAcc(x, y[i], zz, i);
+ //}
+
+ /*
+ * Precompute table of all 4-bit products of y
+ */
+ ulong[] T0 = new ulong[9 << 4];
+ Array.Copy(y, 0, T0, 9, 9);
+ // Reduce5(T0, 9);
+ int tOff = 0;
+ for (int i = 7; i > 0; --i)
+ {
+ tOff += 18;
+ Nat.ShiftUpBit64(9, T0, tOff >> 1, 0UL, T0, tOff);
+ Reduce5(T0, tOff);
+ Add(T0, 9, T0, tOff, T0, tOff + 9);
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ ulong[] T1 = new ulong[T0.Length];
+ Nat.ShiftUpBits64(T0.Length, T0, 0, 4, 0L, T1, 0);
+
+ uint MASK = 0xF;
+
+ /*
+ * Lopez-Dahab algorithm
+ */
+
+ for (int k = 56; k >= 0; k -= 8)
+ {
+ for (int j = 1; j < 9; j += 2)
+ {
+ uint aVal = (uint)(x[j] >> k);
+ uint u = aVal & MASK;
+ uint v = (aVal >> 4) & MASK;
+ AddBothTo(T0, (int)(9 * u), T1, (int)(9 * v), zz, j - 1);
+ }
+ Nat.ShiftUpBits64(16, zz, 0, 8, 0L);
+ }
+
+ for (int k = 56; k >= 0; k -= 8)
+ {
+ for (int j = 0; j < 9; j += 2)
+ {
+ uint aVal = (uint)(x[j] >> k);
+ uint u = aVal & MASK;
+ uint v = (aVal >> 4) & MASK;
+ AddBothTo(T0, (int)(9 * u), T1, (int)(9 * v), zz, j);
+ }
+ if (k > 0)
+ {
+ Nat.ShiftUpBits64(18, zz, 0, 8, 0L);
+ }
+ }
+ }
+
+ protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff)
+ {
+ ulong[] u = new ulong[32];
+ // u[0] = 0;
+ u[1] = y;
+ for (int i = 2; i < 32; i += 2)
+ {
+ u[i ] = u[i >> 1] << 1;
+ u[i + 1] = u[i ] ^ y;
+ }
+
+ ulong l = 0;
+ for (int i = 0; i < 9; ++i)
+ {
+ ulong x = xs[i];
+
+ uint j = (uint)x;
+
+ l ^= u[j & 31];
+
+ ulong g, h = 0;
+ int k = 60;
+ do
+ {
+ j = (uint)(x >> k);
+ g = u[j & 31];
+ l ^= (g << k);
+ h ^= (g >> -k);
+ }
+ while ((k -= 5) > 0);
+
+ for (int p = 0; p < 4; ++p)
+ {
+ x = (x & RM) >> 1;
+ h ^= x & (ulong)(((long)y << p) >> 63);
+ }
+
+ z[zOff + i] ^= l;
+
+ l = h;
+ }
+ z[zOff + 9] ^= l;
+ }
+
+ protected static void ImplSquare(ulong[] x, ulong[] zz)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ Interleave.Expand64To128(x[i], zz, i << 1);
+ }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
new file mode 100644
index 000000000..8474c912e
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT571FieldElement
+ : ECFieldElement
+ {
+ protected readonly ulong[] x;
+
+ public SecT571FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0)
+ throw new ArgumentException("value invalid for SecT571FieldElement", "x");
+
+ this.x = SecT571Field.FromBigInteger(x);
+ }
+
+ public SecT571FieldElement()
+ {
+ this.x = Nat576.Create64();
+ }
+
+ protected internal SecT571FieldElement(ulong[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat576.IsOne64(x); }
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat576.IsZero64(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return (x[0] & 1UL) != 0UL;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat576.ToBigInteger64(x);
+ }
+
+ public override String FieldName
+ {
+ get { return "SecT571Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 571; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ ulong[] z = Nat576.Create64();
+ SecT571Field.Add(x, ((SecT571FieldElement)b).x, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ ulong[] z = Nat576.Create64();
+ SecT571Field.AddOne(x, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ // Addition and subtraction are the same in F2m
+ return Add(b);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ ulong[] z = Nat576.Create64();
+ SecT571Field.Multiply(x, ((SecT571FieldElement)b).x, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return MultiplyPlusProduct(b, x, y);
+ }
+
+ public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x, bx = ((SecT571FieldElement)b).x;
+ ulong[] xx = ((SecT571FieldElement)x).x, yx = ((SecT571FieldElement)y).x;
+
+ ulong[] tt = Nat576.CreateExt64();
+ SecT571Field.MultiplyAddToExt(ax, bx, tt);
+ SecT571Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat576.Create64();
+ SecT571Field.Reduce(tt, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ return Multiply(b.Invert());
+ }
+
+ public override ECFieldElement Negate()
+ {
+ return this;
+ }
+
+ public override ECFieldElement Square()
+ {
+ ulong[] z = Nat576.Create64();
+ SecT571Field.Square(x, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return SquarePlusProduct(x, y);
+ }
+
+ public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ ulong[] ax = this.x;
+ ulong[] xx = ((SecT571FieldElement)x).x, yx = ((SecT571FieldElement)y).x;
+
+ ulong[] tt = Nat576.CreateExt64();
+ SecT571Field.SquareAddToExt(ax, tt);
+ SecT571Field.MultiplyAddToExt(xx, yx, tt);
+
+ ulong[] z = Nat576.Create64();
+ SecT571Field.Reduce(tt, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement SquarePow(int pow)
+ {
+ if (pow < 1)
+ return this;
+
+ ulong[] z = Nat576.Create64();
+ SecT571Field.SquareN(x, pow, z);
+ return new SecT571FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ return new SecT571FieldElement(
+ AbstractF2mCurve.Inverse(571, new int[] { 2, 5, 10 }, ToBigInteger()));
+ }
+
+ public override ECFieldElement Sqrt()
+ {
+ return SquarePow(M - 1);
+ }
+
+ public virtual int Representation
+ {
+ get { return F2mFieldElement.Ppb; }
+ }
+
+ public virtual int M
+ {
+ get { return 571; }
+ }
+
+ public virtual int K1
+ {
+ get { return 2; }
+ }
+
+ public virtual int K2
+ {
+ get { return 5; }
+ }
+
+ public virtual int K3
+ {
+ get { return 10; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SecT571FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SecT571FieldElement);
+ }
+
+ public virtual bool Equals(SecT571FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat576.Eq64(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return 5711052 ^ Arrays.GetHashCode(x, 0, 9);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
new file mode 100644
index 000000000..fb136c967
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
@@ -0,0 +1,196 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT571K1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT571K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT571K1Point m_infinity;
+
+ public SecT571K1Curve()
+ : base(571, 2, 5, 10)
+ {
+ this.m_infinity = new SecT571K1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.Zero);
+ this.m_b = FromBigInteger(BigInteger.One);
+ this.m_order = new BigInteger(1, Hex.Decode("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001"));
+ this.m_cofactor = BigInteger.ValueOf(4);
+
+ this.m_coord = SecT571K1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT571K1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected override ECMultiplier CreateDefaultMultiplier()
+ {
+ return new WTauNafMultiplier();
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 571; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT571FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT571K1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT571K1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return true; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ y = B.Sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(571, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 571; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 571; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 2; }
+ }
+
+ public virtual int K2
+ {
+ get { return 5; }
+ }
+
+ public virtual int K3
+ {
+ get { return 10; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT571K1Point.cs b/crypto/src/math/ec/custom/sec/SecT571K1Point.cs
new file mode 100644
index 000000000..62ed7bda0
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT571K1Point.cs
@@ -0,0 +1,296 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT571K1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT571K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT571K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT571K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT571K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ //return new SecT571K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT571K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT571K1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT571K1Point(curve, X3, curve.B, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT571K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T;
+ if (Z1IsOne)
+ {
+ T = L1.Square().Add(L1);
+ }
+ else
+ {
+ T = L1.Add(Z1).Multiply(L1);
+ }
+
+ if (T.IsZero)
+ {
+ //return new SecT571K1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT571K1Point(curve, T, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement t1 = L1.Add(X1).Square();
+ ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square();
+ ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+ return new SecT571K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ // NOTE: TwicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = L1Sq.Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT571K1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT571K1Point(curve, A, curve.B, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT571K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT571K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
new file mode 100644
index 000000000..05d58863e
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
@@ -0,0 +1,193 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT571R1Curve
+ : AbstractF2mCurve
+ {
+ private const int SecT571R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ protected readonly SecT571R1Point m_infinity;
+
+ internal static readonly SecT571FieldElement SecT571R1_B = new SecT571FieldElement(
+ new BigInteger(1, Hex.Decode("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A")));
+ internal static readonly SecT571FieldElement SecT571R1_B_SQRT = (SecT571FieldElement)SecT571R1_B.Sqrt();
+
+ public SecT571R1Curve()
+ : base(571, 2, 5, 10)
+ {
+ this.m_infinity = new SecT571R1Point(this, null, null);
+
+ this.m_a = FromBigInteger(BigInteger.One);
+ this.m_b = SecT571R1_B;
+ this.m_order = new BigInteger(1, Hex.Decode("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47"));
+ this.m_cofactor = BigInteger.Two;
+
+ this.m_coord = SecT571R1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SecT571R1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return 571; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SecT571FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SecT571R1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SecT571R1Point(this, x, y, zs, withCompression);
+ }
+
+ public override bool IsKoblitz
+ {
+ get { return false; }
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = FromBigInteger(X1), y = null;
+ if (x.IsZero)
+ {
+ // y = B.Sqrt();
+ y = SecT571R1_B_SQRT;
+ }
+ else
+ {
+ ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
+ ECFieldElement z = SolveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.Add(x);
+ break;
+ }
+ default:
+ {
+ y = z.Multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return this.CreateRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(571, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < 571; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ return null;
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
+ }
+
+ public virtual int M
+ {
+ get { return 571; }
+ }
+
+ public virtual bool IsTrinomial
+ {
+ get { return false; }
+ }
+
+ public virtual int K1
+ {
+ get { return 2; }
+ }
+
+ public virtual int K2
+ {
+ get { return 5; }
+ }
+
+ public virtual int K3
+ {
+ get { return 10; }
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT571R1Point.cs b/crypto/src/math/ec/custom/sec/SecT571R1Point.cs
new file mode 100644
index 000000000..0cbc98cf3
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT571R1Point.cs
@@ -0,0 +1,286 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+ internal class SecT571R1Point
+ : AbstractF2mPoint
+ {
+ /**
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecT571R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+ */
+ public SecT571R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SecT571R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SecT571R1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECFieldElement YCoord
+ {
+ get
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ if (this.IsInfinity || X.IsZero)
+ return L;
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.Add(X).Multiply(X);
+
+ ECFieldElement Z = RawZCoords[0];
+ if (!Z.IsOne)
+ {
+ Y = Y.Divide(Z);
+ }
+
+ return Y;
+ }
+ }
+
+ protected internal override bool CompressionYTilde
+ {
+ get
+ {
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return false;
+
+ ECFieldElement Y = this.RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ return Y.TestBitZero() != X.TestBitZero();
+ }
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ ECFieldElement X2 = b.RawXCoord;
+
+ if (X1.IsZero)
+ {
+ if (X2.IsZero)
+ return curve.Infinity;
+
+ return b.Add(this);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.Multiply(Z1);
+ S2 = S2.Multiply(Z1);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.Multiply(Z2);
+ S1 = S1.Multiply(Z2);
+ }
+
+ ECFieldElement A = S1.Add(S2);
+ ECFieldElement B = U1.Add(U2);
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return Twice();
+
+ return curve.Infinity;
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.IsZero)
+ {
+ // TODO This can probably be optimized quite a bit
+ ECPoint p = this.Normalize();
+ X1 = p.XCoord;
+ ECFieldElement Y1 = p.YCoord;
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+ //X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+ X3 = L.Square().Add(L).Add(X1).AddOne();
+ if (X3.IsZero)
+ {
+ //return new SecT571R1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT571R1Point(curve, X3, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed);
+ }
+
+ ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+ L3 = Y3.Divide(X3).Add(X3);
+ Z3 = curve.FromBigInteger(BigInteger.One);
+ }
+ else
+ {
+ B = B.Square();
+
+ ECFieldElement AU1 = A.Multiply(U1);
+ ECFieldElement AU2 = A.Multiply(U2);
+
+ X3 = AU1.Multiply(AU2);
+ if (X3.IsZero)
+ {
+ //return new SecT571R1Point(curve, X3, curve.B.sqrt(), IsCompressed);
+ return new SecT571R1Point(curve, X3, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed);
+ }
+
+ ECFieldElement ABZ2 = A.Multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.Multiply(Z2);
+ }
+
+ L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.Multiply(Z1);
+ }
+ }
+
+ return new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return curve.Infinity;
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+ bool Z1IsOne = Z1.IsOne;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+ ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq);
+ if (T.IsZero)
+ {
+ //return new SecT571R1Point(curve, T, curve.B.sqrt(), withCompression);
+ return new SecT571R1Point(curve, T, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed);
+ }
+
+ ECFieldElement X3 = T.Square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+ ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+
+ return new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ ECFieldElement X1 = this.RawXCoord;
+ if (X1.IsZero)
+ {
+ // A point with X == 0 is it's own Additive inverse
+ return b;
+ }
+
+ ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+ if (X2.IsZero || !Z2.IsOne)
+ {
+ return Twice().Add(b);
+ }
+
+ ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ ECFieldElement L2 = b.RawYCoord;
+
+ ECFieldElement X1Sq = X1.Square();
+ ECFieldElement L1Sq = L1.Square();
+ ECFieldElement Z1Sq = Z1.Square();
+ ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+ //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+ ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1);
+ ECFieldElement L2plus1 = L2.AddOne();
+ //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+ if (B.IsZero)
+ {
+ if (A.IsZero)
+ return b.Twice();
+
+ return curve.Infinity;
+ }
+
+ if (A.IsZero)
+ {
+ //return new SecT571R1Point(curve, A, curve.B.sqrt(), withCompression);
+ return new SecT571R1Point(curve, A, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed);
+ }
+
+ ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+ ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+ return new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECFieldElement X = this.RawXCoord;
+ if (X.IsZero)
+ return this;
+
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+ return new SecT571R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+ }
+ }
+}
|