org.bouncycastle.tls.TlsECCUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of impersonator Show documentation
Show all versions of impersonator Show documentation
Spoof TLS/JA3/JA4 and HTTP/2 fingerprints in Java
package org.bouncycastle.tls;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.bouncycastle.tls.crypto.TlsECConfig;
import org.bouncycastle.util.Arrays;
public class TlsECCUtils
{
public static TlsECConfig createNamedECConfig(TlsContext context, int namedGroup)
throws IOException
{
if (NamedGroup.getCurveBits(namedGroup) < 1)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
return new TlsECConfig(namedGroup);
}
public static int getMinimumCurveBits(int cipherSuite)
{
/*
* NOTE: This mechanism was added to support a minimum bit-size requirement mooted in early
* drafts of RFC 8442. This requirement was removed in later drafts, so this mechanism is
* currently somewhat trivial.
*/
return isECCCipherSuite(cipherSuite) ? 1 : 0;
}
public static boolean isECCCipherSuite(int cipherSuite)
{
switch (TlsUtils.getKeyExchangeAlgorithm(cipherSuite))
{
case KeyExchangeAlgorithm.ECDH_anon:
case KeyExchangeAlgorithm.ECDH_ECDSA:
case KeyExchangeAlgorithm.ECDH_RSA:
case KeyExchangeAlgorithm.ECDHE_ECDSA:
case KeyExchangeAlgorithm.ECDHE_PSK:
case KeyExchangeAlgorithm.ECDHE_RSA:
case KeyExchangeAlgorithm.GOSTR341112_256:
return true;
default:
return false;
}
}
public static void checkPointEncoding(int namedGroup, byte[] encoding) throws IOException
{
if (TlsUtils.isNullOrEmpty(encoding))
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
switch (namedGroup)
{
case NamedGroup.x25519:
case NamedGroup.x448:
return;
}
switch (encoding[0])
{
case 0x04: // uncompressed
return;
case 0x00: // infinity
case 0x02: // compressed
case 0x03: // compressed
case 0x06: // hybrid
case 0x07: // hybrid
default:
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}
public static TlsECConfig receiveECDHConfig(TlsContext context, InputStream input) throws IOException
{
short curveType = TlsUtils.readUint8(input);
if (curveType != ECCurveType.named_curve)
{
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
int namedGroup = TlsUtils.readUint16(input);
if (NamedGroup.refersToAnECDHCurve(namedGroup))
{
int[] clientSupportedGroups = context.getSecurityParametersHandshake().getClientSupportedGroups();
if (null == clientSupportedGroups || Arrays.contains(clientSupportedGroups, namedGroup))
{
return new TlsECConfig(namedGroup);
}
}
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
public static void writeECConfig(TlsECConfig ecConfig, OutputStream output) throws IOException
{
writeNamedECParameters(ecConfig.getNamedGroup(), output);
}
public static void writeNamedECParameters(int namedGroup, OutputStream output) throws IOException
{
if (!NamedGroup.refersToASpecificCurve(namedGroup))
{
/*
* RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
* curve. Values of NamedCurve that indicate support for a class of explicitly defined
* curves are not allowed here [...].
*/
throw new TlsFatalAlert(AlertDescription.internal_error);
}
TlsUtils.writeUint8(ECCurveType.named_curve, output);
TlsUtils.checkUint16(namedGroup);
TlsUtils.writeUint16(namedGroup, output);
}
}