Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Crypto/Tls/TlsEccUtilities.cs
2025-10-09 09:57:24 +09:00

606 lines
16 KiB
C#

using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.EC;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math.Field;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class TlsEccUtilities
{
private static readonly string[] CurveNames = new string[28]
{
"sect163k1", "sect163r1", "sect163r2", "sect193r1", "sect193r2", "sect233k1", "sect233r1", "sect239k1", "sect283k1", "sect283r1",
"sect409k1", "sect409r1", "sect571k1", "sect571r1", "secp160k1", "secp160r1", "secp160r2", "secp192k1", "secp192r1", "secp224k1",
"secp224r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1", "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"
};
public static void AddSupportedEllipticCurvesExtension(IDictionary extensions, int[] namedCurves)
{
extensions[10] = CreateSupportedEllipticCurvesExtension(namedCurves);
}
public static void AddSupportedPointFormatsExtension(IDictionary extensions, byte[] ecPointFormats)
{
extensions[11] = CreateSupportedPointFormatsExtension(ecPointFormats);
}
public static int[] GetSupportedEllipticCurvesExtension(IDictionary extensions)
{
byte[] extensionData = TlsUtilities.GetExtensionData(extensions, 10);
if (extensionData != null)
{
return ReadSupportedEllipticCurvesExtension(extensionData);
}
return null;
}
public static byte[] GetSupportedPointFormatsExtension(IDictionary extensions)
{
byte[] extensionData = TlsUtilities.GetExtensionData(extensions, 11);
if (extensionData != null)
{
return ReadSupportedPointFormatsExtension(extensionData);
}
return null;
}
public static byte[] CreateSupportedEllipticCurvesExtension(int[] namedCurves)
{
if (namedCurves == null || namedCurves.Length < 1)
{
throw new TlsFatalAlert(80);
}
return TlsUtilities.EncodeUint16ArrayWithUint16Length(namedCurves);
}
public static byte[] CreateSupportedPointFormatsExtension(byte[] ecPointFormats)
{
if (ecPointFormats == null || !Arrays.Contains(ecPointFormats, 0))
{
ecPointFormats = Arrays.Append(ecPointFormats, 0);
}
return TlsUtilities.EncodeUint8ArrayWithUint8Length(ecPointFormats);
}
public static int[] ReadSupportedEllipticCurvesExtension(byte[] extensionData)
{
if (extensionData == null)
{
throw new ArgumentNullException("extensionData");
}
MemoryStream memoryStream = new MemoryStream(extensionData, writable: false);
int num = TlsUtilities.ReadUint16(memoryStream);
if (num < 2 || (num & 1) != 0)
{
throw new TlsFatalAlert(50);
}
int[] result = TlsUtilities.ReadUint16Array(num / 2, memoryStream);
TlsProtocol.AssertEmpty(memoryStream);
return result;
}
public static byte[] ReadSupportedPointFormatsExtension(byte[] extensionData)
{
byte[] array = TlsUtilities.DecodeUint8ArrayWithUint8Length(extensionData);
if (!Arrays.Contains(array, 0))
{
throw new TlsFatalAlert(47);
}
return array;
}
public static string GetNameOfNamedCurve(int namedCurve)
{
if (!IsSupportedNamedCurve(namedCurve))
{
return null;
}
return CurveNames[namedCurve - 1];
}
public static ECDomainParameters GetParametersForNamedCurve(int namedCurve)
{
string nameOfNamedCurve = GetNameOfNamedCurve(namedCurve);
if (nameOfNamedCurve == null)
{
return null;
}
X9ECParameters byName = CustomNamedCurves.GetByName(nameOfNamedCurve);
if (byName == null)
{
byName = ECNamedCurveTable.GetByName(nameOfNamedCurve);
if (byName == null)
{
return null;
}
}
return new ECDomainParameters(byName.Curve, byName.G, byName.N, byName.H, byName.GetSeed());
}
public static bool HasAnySupportedNamedCurves()
{
return CurveNames.Length > 0;
}
public static bool ContainsEccCipherSuites(int[] cipherSuites)
{
for (int i = 0; i < cipherSuites.Length; i++)
{
if (IsEccCipherSuite(cipherSuites[i]))
{
return true;
}
}
return false;
}
public static bool IsEccCipherSuite(int cipherSuite)
{
switch (cipherSuite)
{
case 49153:
case 49154:
case 49155:
case 49156:
case 49157:
case 49158:
case 49159:
case 49160:
case 49161:
case 49162:
case 49163:
case 49164:
case 49165:
case 49166:
case 49167:
case 49168:
case 49169:
case 49170:
case 49171:
case 49172:
case 49173:
case 49174:
case 49175:
case 49176:
case 49177:
case 49187:
case 49188:
case 49189:
case 49190:
case 49191:
case 49192:
case 49193:
case 49194:
case 49195:
case 49196:
case 49197:
case 49198:
case 49199:
case 49200:
case 49201:
case 49202:
case 49203:
case 49204:
case 49205:
case 49206:
case 49207:
case 49208:
case 49209:
case 49210:
case 49211:
case 49266:
case 49267:
case 49268:
case 49269:
case 49270:
case 49271:
case 49272:
case 49273:
case 49286:
case 49287:
case 49288:
case 49289:
case 49290:
case 49291:
case 49292:
case 49293:
case 49306:
case 49307:
case 49324:
case 49325:
case 49326:
case 49327:
case 52392:
case 52393:
case 52396:
case 65282:
case 65283:
case 65284:
case 65285:
case 65300:
case 65301:
return true;
default:
return false;
}
}
public static bool AreOnSameCurve(ECDomainParameters a, ECDomainParameters b)
{
return a?.Equals(b) ?? false;
}
public static bool IsSupportedNamedCurve(int namedCurve)
{
if (namedCurve > 0)
{
return namedCurve <= CurveNames.Length;
}
return false;
}
public static bool IsCompressionPreferred(byte[] ecPointFormats, byte compressionFormat)
{
if (ecPointFormats == null)
{
return false;
}
foreach (byte b in ecPointFormats)
{
if (b == 0)
{
return false;
}
if (b == compressionFormat)
{
return true;
}
}
return false;
}
public static byte[] SerializeECFieldElement(int fieldSize, BigInteger x)
{
return BigIntegers.AsUnsignedByteArray((fieldSize + 7) / 8, x);
}
public static byte[] SerializeECPoint(byte[] ecPointFormats, ECPoint point)
{
ECCurve curve = point.Curve;
bool compressed = false;
if (ECAlgorithms.IsFpCurve(curve))
{
compressed = IsCompressionPreferred(ecPointFormats, 1);
}
else if (ECAlgorithms.IsF2mCurve(curve))
{
compressed = IsCompressionPreferred(ecPointFormats, 2);
}
return point.GetEncoded(compressed);
}
public static byte[] SerializeECPublicKey(byte[] ecPointFormats, ECPublicKeyParameters keyParameters)
{
return SerializeECPoint(ecPointFormats, keyParameters.Q);
}
public static BigInteger DeserializeECFieldElement(int fieldSize, byte[] encoding)
{
int num = (fieldSize + 7) / 8;
if (encoding.Length != num)
{
throw new TlsFatalAlert(50);
}
return new BigInteger(1, encoding);
}
public static ECPoint DeserializeECPoint(byte[] ecPointFormats, ECCurve curve, byte[] encoding)
{
if (encoding == null || encoding.Length < 1)
{
throw new TlsFatalAlert(47);
}
byte b;
switch (encoding[0])
{
case 2:
case 3:
if (ECAlgorithms.IsF2mCurve(curve))
{
b = 2;
break;
}
if (ECAlgorithms.IsFpCurve(curve))
{
b = 1;
break;
}
throw new TlsFatalAlert(47);
case 4:
b = 0;
break;
default:
throw new TlsFatalAlert(47);
}
if (b != 0 && (ecPointFormats == null || !Arrays.Contains(ecPointFormats, b)))
{
throw new TlsFatalAlert(47);
}
return curve.DecodePoint(encoding);
}
public static ECPublicKeyParameters DeserializeECPublicKey(byte[] ecPointFormats, ECDomainParameters curve_params, byte[] encoding)
{
try
{
ECPoint q = DeserializeECPoint(ecPointFormats, curve_params.Curve, encoding);
return new ECPublicKeyParameters(q, curve_params);
}
catch (Exception alertCause)
{
throw new TlsFatalAlert(47, alertCause);
}
}
public static byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
{
ECDHBasicAgreement eCDHBasicAgreement = new ECDHBasicAgreement();
eCDHBasicAgreement.Init(privateKey);
BigInteger n = eCDHBasicAgreement.CalculateAgreement(publicKey);
return BigIntegers.AsUnsignedByteArray(eCDHBasicAgreement.GetFieldSize(), n);
}
public static AsymmetricCipherKeyPair GenerateECKeyPair(SecureRandom random, ECDomainParameters ecParams)
{
ECKeyPairGenerator eCKeyPairGenerator = new ECKeyPairGenerator();
eCKeyPairGenerator.Init(new ECKeyGenerationParameters(ecParams, random));
return eCKeyPairGenerator.GenerateKeyPair();
}
public static ECPrivateKeyParameters GenerateEphemeralClientKeyExchange(SecureRandom random, byte[] ecPointFormats, ECDomainParameters ecParams, Stream output)
{
AsymmetricCipherKeyPair asymmetricCipherKeyPair = GenerateECKeyPair(random, ecParams);
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)asymmetricCipherKeyPair.Public;
WriteECPoint(ecPointFormats, eCPublicKeyParameters.Q, output);
return (ECPrivateKeyParameters)asymmetricCipherKeyPair.Private;
}
internal static ECPrivateKeyParameters GenerateEphemeralServerKeyExchange(SecureRandom random, int[] namedCurves, byte[] ecPointFormats, Stream output)
{
int num = -1;
if (namedCurves == null)
{
num = 23;
}
else
{
foreach (int num2 in namedCurves)
{
if (NamedCurve.IsValid(num2) && IsSupportedNamedCurve(num2))
{
num = num2;
break;
}
}
}
ECDomainParameters eCDomainParameters = null;
if (num >= 0)
{
eCDomainParameters = GetParametersForNamedCurve(num);
}
else if (Arrays.Contains(namedCurves, 65281))
{
eCDomainParameters = GetParametersForNamedCurve(23);
}
else if (Arrays.Contains(namedCurves, 65282))
{
eCDomainParameters = GetParametersForNamedCurve(10);
}
if (eCDomainParameters == null)
{
throw new TlsFatalAlert(80);
}
if (num < 0)
{
WriteExplicitECParameters(ecPointFormats, eCDomainParameters, output);
}
else
{
WriteNamedECParameters(num, output);
}
return GenerateEphemeralClientKeyExchange(random, ecPointFormats, eCDomainParameters, output);
}
public static ECPublicKeyParameters ValidateECPublicKey(ECPublicKeyParameters key)
{
return key;
}
public static int ReadECExponent(int fieldSize, Stream input)
{
BigInteger bigInteger = ReadECParameter(input);
if (bigInteger.BitLength < 32)
{
int intValue = bigInteger.IntValue;
if (intValue > 0 && intValue < fieldSize)
{
return intValue;
}
}
throw new TlsFatalAlert(47);
}
public static BigInteger ReadECFieldElement(int fieldSize, Stream input)
{
return DeserializeECFieldElement(fieldSize, TlsUtilities.ReadOpaque8(input));
}
public static BigInteger ReadECParameter(Stream input)
{
return new BigInteger(1, TlsUtilities.ReadOpaque8(input));
}
public static ECDomainParameters ReadECParameters(int[] namedCurves, byte[] ecPointFormats, Stream input)
{
try
{
switch (TlsUtilities.ReadUint8(input))
{
case 1:
{
CheckNamedCurve(namedCurves, 65281);
BigInteger bigInteger3 = ReadECParameter(input);
BigInteger a2 = ReadECFieldElement(bigInteger3.BitLength, input);
BigInteger b3 = ReadECFieldElement(bigInteger3.BitLength, input);
byte[] encoding2 = TlsUtilities.ReadOpaque8(input);
BigInteger bigInteger4 = ReadECParameter(input);
BigInteger bigInteger5 = ReadECParameter(input);
ECCurve curve2 = new FpCurve(bigInteger3, a2, b3, bigInteger4, bigInteger5);
ECPoint g2 = DeserializeECPoint(ecPointFormats, curve2, encoding2);
return new ECDomainParameters(curve2, g2, bigInteger4, bigInteger5);
}
case 2:
{
CheckNamedCurve(namedCurves, 65282);
int num = TlsUtilities.ReadUint16(input);
byte b = TlsUtilities.ReadUint8(input);
if (!ECBasisType.IsValid(b))
{
throw new TlsFatalAlert(47);
}
int num2 = ReadECExponent(num, input);
int k = -1;
int k2 = -1;
if (b == 2)
{
k = ReadECExponent(num, input);
k2 = ReadECExponent(num, input);
}
BigInteger a = ReadECFieldElement(num, input);
BigInteger b2 = ReadECFieldElement(num, input);
byte[] encoding = TlsUtilities.ReadOpaque8(input);
BigInteger bigInteger = ReadECParameter(input);
BigInteger bigInteger2 = ReadECParameter(input);
ECCurve curve = ((b == 2) ? new F2mCurve(num, num2, k, k2, a, b2, bigInteger, bigInteger2) : new F2mCurve(num, num2, a, b2, bigInteger, bigInteger2));
ECPoint g = DeserializeECPoint(ecPointFormats, curve, encoding);
return new ECDomainParameters(curve, g, bigInteger, bigInteger2);
}
case 3:
{
int namedCurve = TlsUtilities.ReadUint16(input);
if (!NamedCurve.RefersToASpecificNamedCurve(namedCurve))
{
throw new TlsFatalAlert(47);
}
CheckNamedCurve(namedCurves, namedCurve);
return GetParametersForNamedCurve(namedCurve);
}
default:
throw new TlsFatalAlert(47);
}
}
catch (Exception alertCause)
{
throw new TlsFatalAlert(47, alertCause);
}
}
private static void CheckNamedCurve(int[] namedCurves, int namedCurve)
{
if (namedCurves != null && !Arrays.Contains(namedCurves, namedCurve))
{
throw new TlsFatalAlert(47);
}
}
public static void WriteECExponent(int k, Stream output)
{
BigInteger x = BigInteger.ValueOf(k);
WriteECParameter(x, output);
}
public static void WriteECFieldElement(ECFieldElement x, Stream output)
{
TlsUtilities.WriteOpaque8(x.GetEncoded(), output);
}
public static void WriteECFieldElement(int fieldSize, BigInteger x, Stream output)
{
TlsUtilities.WriteOpaque8(SerializeECFieldElement(fieldSize, x), output);
}
public static void WriteECParameter(BigInteger x, Stream output)
{
TlsUtilities.WriteOpaque8(BigIntegers.AsUnsignedByteArray(x), output);
}
public static void WriteExplicitECParameters(byte[] ecPointFormats, ECDomainParameters ecParameters, Stream output)
{
ECCurve curve = ecParameters.Curve;
if (ECAlgorithms.IsFpCurve(curve))
{
TlsUtilities.WriteUint8(1, output);
WriteECParameter(curve.Field.Characteristic, output);
}
else
{
if (!ECAlgorithms.IsF2mCurve(curve))
{
throw new ArgumentException("'ecParameters' not a known curve type");
}
IPolynomialExtensionField polynomialExtensionField = (IPolynomialExtensionField)curve.Field;
int[] exponentsPresent = polynomialExtensionField.MinimalPolynomial.GetExponentsPresent();
TlsUtilities.WriteUint8(2, output);
int i = exponentsPresent[^1];
TlsUtilities.CheckUint16(i);
TlsUtilities.WriteUint16(i, output);
if (exponentsPresent.Length == 3)
{
TlsUtilities.WriteUint8(1, output);
WriteECExponent(exponentsPresent[1], output);
}
else
{
if (exponentsPresent.Length != 5)
{
throw new ArgumentException("Only trinomial and pentomial curves are supported");
}
TlsUtilities.WriteUint8(2, output);
WriteECExponent(exponentsPresent[1], output);
WriteECExponent(exponentsPresent[2], output);
WriteECExponent(exponentsPresent[3], output);
}
}
WriteECFieldElement(curve.A, output);
WriteECFieldElement(curve.B, output);
TlsUtilities.WriteOpaque8(SerializeECPoint(ecPointFormats, ecParameters.G), output);
WriteECParameter(ecParameters.N, output);
WriteECParameter(ecParameters.H, output);
}
public static void WriteECPoint(byte[] ecPointFormats, ECPoint point, Stream output)
{
TlsUtilities.WriteOpaque8(SerializeECPoint(ecPointFormats, point), output);
}
public static void WriteNamedECParameters(int namedCurve, Stream output)
{
if (!NamedCurve.RefersToASpecificNamedCurve(namedCurve))
{
throw new TlsFatalAlert(80);
}
TlsUtilities.WriteUint8(3, output);
TlsUtilities.CheckUint16(namedCurve);
TlsUtilities.WriteUint16(namedCurve, output);
}
}