<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />

Sidh

sealed class Sidh
namespace Org.BouncyCastle.Pqc.Crypto.Sike { internal sealed class Sidh { private readonly SikeEngine engine; internal Sidh(SikeEngine engine) { this.engine = engine; } internal void init_basis(ulong[] gen, ulong[][] XP, ulong[][] XQ, ulong[][] XR) { engine.fpx.fpcopy(gen, 0, XP[0]); engine.fpx.fpcopy(gen, engine.param.NWORDS_FIELD, XP[1]); engine.fpx.fpcopy(gen, 2 * engine.param.NWORDS_FIELD, XQ[0]); engine.fpx.fpcopy(gen, 3 * engine.param.NWORDS_FIELD, XQ[1]); engine.fpx.fpcopy(gen, 4 * engine.param.NWORDS_FIELD, XR[0]); engine.fpx.fpcopy(gen, 5 * engine.param.NWORDS_FIELD, XR[1]); } internal void EphemeralKeyGeneration_B(byte[] sk, byte[] pk) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj2 = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj3 = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj4 = new PointProj(engine.param.NWORDS_FIELD); PointProj[] array = new PointProj[engine.param.MAX_INT_POINTS_BOB]; ulong[][] xP = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] xQ = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][][] coeff = SikeUtilities.InitArray(3, 2, engine.param.NWORDS_FIELD); uint num = 0; uint num2 = 0; uint num3 = 0; uint[] array6 = new uint[engine.param.MAX_INT_POINTS_BOB]; ulong[] array7 = new ulong[engine.param.NWORDS_ORDER]; init_basis(engine.param.B_gen, xP, xQ, array2); init_basis(engine.param.A_gen, pointProj2.X, pointProj3.X, pointProj4.X); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj2.Z[0]); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj3.Z[0]); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj4.Z[0]); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array3[0]); engine.fpx.mp2_add(array3, array3, array3); engine.fpx.mp2_add(array3, array3, array4); engine.fpx.mp2_add(array3, array4, array5); engine.fpx.mp2_add(array4, array4, array3); engine.fpx.decode_to_digits(sk, engine.param.MSG_BYTES, array7, engine.param.SECRETKEY_B_BYTES, engine.param.NWORDS_ORDER); engine.isogeny.LADDER3PT(xP, xQ, array2, array7, engine.param.BOB, pointProj, array5); num = 0; for (uint num4 = 1; num4 < engine.param.MAX_Bob; num4++) { uint num7; for (; num < engine.param.MAX_Bob - num4; num += num7) { array[num2] = new PointProj(engine.param.NWORDS_FIELD); engine.fpx.fp2copy(pointProj.X, array[num2].X); engine.fpx.fp2copy(pointProj.Z, array[num2].Z); array6[num2++] = num; num7 = engine.param.strat_Bob[num3++]; engine.isogeny.XTplE(pointProj, pointProj, array4, array3, num7); } engine.isogeny.Get3Isog(pointProj, array4, array3, coeff); for (uint num8 = 0; num8 < num2; num8++) { engine.isogeny.Eval3Isog(array[num8], coeff); } engine.isogeny.Eval3Isog(pointProj2, coeff); engine.isogeny.Eval3Isog(pointProj3, coeff); engine.isogeny.Eval3Isog(pointProj4, coeff); engine.fpx.fp2copy(array[num2 - 1].X, pointProj.X); engine.fpx.fp2copy(array[num2 - 1].Z, pointProj.Z); num = array6[num2 - 1]; num2--; } engine.isogeny.Get3Isog(pointProj, array4, array3, coeff); engine.isogeny.Eval3Isog(pointProj2, coeff); engine.isogeny.Eval3Isog(pointProj3, coeff); engine.isogeny.Eval3Isog(pointProj4, coeff); engine.isogeny.Inv3Way(pointProj2.Z, pointProj3.Z, pointProj4.Z); engine.fpx.fp2mul_mont(pointProj2.X, pointProj2.Z, pointProj2.X); engine.fpx.fp2mul_mont(pointProj3.X, pointProj3.Z, pointProj3.X); engine.fpx.fp2mul_mont(pointProj4.X, pointProj4.Z, pointProj4.X); engine.fpx.fp2_encode(pointProj2.X, pk, 0); engine.fpx.fp2_encode(pointProj3.X, pk, engine.param.FP2_ENCODED_BYTES); engine.fpx.fp2_encode(pointProj4.X, pk, 2 * engine.param.FP2_ENCODED_BYTES); } internal void EphemeralKeyGeneration_A(byte[] ephemeralsk, byte[] ct) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj2 = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj3 = new PointProj(engine.param.NWORDS_FIELD); PointProj pointProj4 = new PointProj(engine.param.NWORDS_FIELD); PointProj[] array = new PointProj[engine.param.MAX_INT_POINTS_ALICE]; ulong[][] xP = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] xQ = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][][] coeff = SikeUtilities.InitArray(3, 2, engine.param.NWORDS_FIELD); uint num = 0; uint num2 = 0; uint num3 = 0; uint[] array6 = new uint[engine.param.MAX_INT_POINTS_ALICE]; ulong[] array7 = new ulong[engine.param.NWORDS_ORDER]; init_basis(engine.param.A_gen, xP, xQ, array2); init_basis(engine.param.B_gen, pointProj2.X, pointProj3.X, pointProj4.X); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj2.Z[0]); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj3.Z[0]); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, pointProj4.Z[0]); engine.fpx.fpcopy(engine.param.Montgomery_one, 0, array3[0]); engine.fpx.mp2_add(array3, array3, array3); engine.fpx.mp2_add(array3, array3, array4); engine.fpx.mp2_add(array3, array4, array5); engine.fpx.mp2_add(array4, array4, array3); engine.fpx.decode_to_digits(ephemeralsk, 0, array7, engine.param.SECRETKEY_A_BYTES, engine.param.NWORDS_ORDER); engine.isogeny.LADDER3PT(xP, xQ, array2, array7, engine.param.ALICE, pointProj, array5); if (engine.param.OALICE_BITS % 2 == 1) { PointProj pointProj5 = new PointProj(engine.param.NWORDS_FIELD); engine.isogeny.XDblE(pointProj, pointProj5, array3, array4, engine.param.OALICE_BITS - 1); engine.isogeny.Get2Isog(pointProj5, array3, array4); engine.isogeny.Eval2Isog(pointProj2, pointProj5); engine.isogeny.Eval2Isog(pointProj3, pointProj5); engine.isogeny.Eval2Isog(pointProj4, pointProj5); engine.isogeny.Eval2Isog(pointProj, pointProj5); } num = 0; for (uint num4 = 1; num4 < engine.param.MAX_Alice; num4++) { uint num7; for (; num < engine.param.MAX_Alice - num4; num += num7) { array[num2] = new PointProj(engine.param.NWORDS_FIELD); engine.fpx.fp2copy(pointProj.X, array[num2].X); engine.fpx.fp2copy(pointProj.Z, array[num2].Z); array6[num2++] = num; num7 = engine.param.strat_Alice[num3++]; engine.isogeny.XDblE(pointProj, pointProj, array3, array4, 2 * num7); } engine.isogeny.Get4Isog(pointProj, array3, array4, coeff); for (uint num8 = 0; num8 < num2; num8++) { engine.isogeny.Eval4Isog(array[num8], coeff); } engine.isogeny.Eval4Isog(pointProj2, coeff); engine.isogeny.Eval4Isog(pointProj3, coeff); engine.isogeny.Eval4Isog(pointProj4, coeff); engine.fpx.fp2copy(array[num2 - 1].X, pointProj.X); engine.fpx.fp2copy(array[num2 - 1].Z, pointProj.Z); num = array6[num2 - 1]; num2--; } engine.isogeny.Get4Isog(pointProj, array3, array4, coeff); engine.isogeny.Eval4Isog(pointProj2, coeff); engine.isogeny.Eval4Isog(pointProj3, coeff); engine.isogeny.Eval4Isog(pointProj4, coeff); engine.isogeny.Inv3Way(pointProj2.Z, pointProj3.Z, pointProj4.Z); engine.fpx.fp2mul_mont(pointProj2.X, pointProj2.Z, pointProj2.X); engine.fpx.fp2mul_mont(pointProj3.X, pointProj3.Z, pointProj3.X); engine.fpx.fp2mul_mont(pointProj4.X, pointProj4.Z, pointProj4.X); engine.fpx.fp2_encode(pointProj2.X, ct, 0); engine.fpx.fp2_encode(pointProj3.X, ct, engine.param.FP2_ENCODED_BYTES); engine.fpx.fp2_encode(pointProj4.X, ct, 2 * engine.param.FP2_ENCODED_BYTES); } internal void EphemeralSecretAgreement_A(byte[] ephemeralsk, byte[] pk, byte[] jinvariant) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); PointProj[] array = new PointProj[engine.param.MAX_INT_POINTS_ALICE]; ulong[][][] array2 = SikeUtilities.InitArray(3, 2, engine.param.NWORDS_FIELD); ulong[][][] coeff = SikeUtilities.InitArray(3, 2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] a = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); uint num = 0; uint num2 = 0; uint num3 = 0; uint num4 = 0; uint num5 = 0; uint num6 = 0; uint[] array6 = new uint[engine.param.MAX_INT_POINTS_ALICE]; ulong[] array7 = new ulong[engine.param.NWORDS_ORDER]; engine.fpx.fp2_decode(pk, array2[0], 0); engine.fpx.fp2_decode(pk, array2[1], engine.param.FP2_ENCODED_BYTES); engine.fpx.fp2_decode(pk, array2[2], 2 * engine.param.FP2_ENCODED_BYTES); engine.isogeny.GetA(array2[0], array2[1], array2[2], a); engine.fpx.mp_add(engine.param.Montgomery_one, engine.param.Montgomery_one, array5[0], engine.param.NWORDS_FIELD); engine.fpx.mp2_add(a, array5, array4); engine.fpx.mp_add(array5[0], array5[0], array5[0], engine.param.NWORDS_FIELD); engine.fpx.decode_to_digits(ephemeralsk, 0, array7, engine.param.SECRETKEY_A_BYTES, engine.param.NWORDS_ORDER); engine.isogeny.LADDER3PT(array2[0], array2[1], array2[2], array7, engine.param.ALICE, pointProj, a); if (engine.param.OALICE_BITS % 2 == 1) { PointProj pointProj2 = new PointProj(engine.param.NWORDS_FIELD); engine.isogeny.XDblE(pointProj, pointProj2, array4, array5, engine.param.OALICE_BITS - 1); engine.isogeny.Get2Isog(pointProj2, array4, array5); engine.isogeny.Eval2Isog(pointProj, pointProj2); } num4 = 0; for (num2 = 1; num2 < engine.param.MAX_Alice; num2++) { for (; num4 < engine.param.MAX_Alice - num2; num4 += num3) { array[num5] = new PointProj(engine.param.NWORDS_FIELD); engine.fpx.fp2copy(pointProj.X, array[num5].X); engine.fpx.fp2copy(pointProj.Z, array[num5].Z); array6[num5++] = num4; num3 = engine.param.strat_Alice[num6++]; engine.isogeny.XDblE(pointProj, pointProj, array4, array5, 2 * num3); } engine.isogeny.Get4Isog(pointProj, array4, array5, coeff); for (num = 0; num < num5; num++) { engine.isogeny.Eval4Isog(array[num], coeff); } engine.fpx.fp2copy(array[num5 - 1].X, pointProj.X); engine.fpx.fp2copy(array[num5 - 1].Z, pointProj.Z); num4 = array6[num5 - 1]; num5--; } engine.isogeny.Get4Isog(pointProj, array4, array5, coeff); engine.fpx.mp2_add(array4, array4, array4); engine.fpx.fp2sub(array4, array5, array4); engine.fpx.fp2add(array4, array4, array4); engine.isogeny.JInv(array4, array5, array3); engine.fpx.fp2_encode(array3, jinvariant, 0); } internal void EphemeralSecretAgreement_B(byte[] sk, byte[] ct, byte[] jinvariant_) { PointProj pointProj = new PointProj(engine.param.NWORDS_FIELD); PointProj[] array = new PointProj[engine.param.MAX_INT_POINTS_BOB]; ulong[][][] coeff = SikeUtilities.InitArray(3, 2, engine.param.NWORDS_FIELD); ulong[][][] array2 = SikeUtilities.InitArray(3, 2, engine.param.NWORDS_FIELD); ulong[][] array3 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array4 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array5 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); ulong[][] array6 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD); uint num = 0; uint num2 = 0; uint num3 = 0; uint[] array7 = new uint[engine.param.MAX_INT_POINTS_BOB]; ulong[] array8 = new ulong[engine.param.NWORDS_ORDER]; engine.fpx.fp2_decode(ct, array2[0], 0); engine.fpx.fp2_decode(ct, array2[1], engine.param.FP2_ENCODED_BYTES); engine.fpx.fp2_decode(ct, array2[2], 2 * engine.param.FP2_ENCODED_BYTES); engine.isogeny.GetA(array2[0], array2[1], array2[2], array6); engine.fpx.mp_add(engine.param.Montgomery_one, engine.param.Montgomery_one, array5[0], engine.param.NWORDS_FIELD); engine.fpx.mp2_add(array6, array5, array4); engine.fpx.mp2_sub_p2(array6, array5, array5); engine.fpx.decode_to_digits(sk, engine.param.MSG_BYTES, array8, engine.param.SECRETKEY_B_BYTES, engine.param.NWORDS_ORDER); engine.isogeny.LADDER3PT(array2[0], array2[1], array2[2], array8, engine.param.BOB, pointProj, array6); num = 0; for (uint num4 = 1; num4 < engine.param.MAX_Bob; num4++) { uint num7; for (; num < engine.param.MAX_Bob - num4; num += num7) { array[num2] = new PointProj(engine.param.NWORDS_FIELD); engine.fpx.fp2copy(pointProj.X, array[num2].X); engine.fpx.fp2copy(pointProj.Z, array[num2].Z); array7[num2++] = num; num7 = engine.param.strat_Bob[num3++]; engine.isogeny.XTplE(pointProj, pointProj, array5, array4, num7); } engine.isogeny.Get3Isog(pointProj, array5, array4, coeff); for (uint num8 = 0; num8 < num2; num8++) { engine.isogeny.Eval3Isog(array[num8], coeff); } engine.fpx.fp2copy(array[num2 - 1].X, pointProj.X); engine.fpx.fp2copy(array[num2 - 1].Z, pointProj.Z); num = array7[num2 - 1]; num2--; } engine.isogeny.Get3Isog(pointProj, array5, array4, coeff); engine.fpx.fp2add(array4, array5, array6); engine.fpx.fp2add(array6, array6, array6); engine.fpx.fp2sub(array4, array5, array4); engine.isogeny.JInv(array6, array4, array3); engine.fpx.fp2_encode(array3, jinvariant_, 0); } } }