gpt4 book ai didi

java - Java 中是否有任何 Java x509certificate ClientHello 解析器?

转载 作者:行者123 更新时间:2023-11-29 04:55:03 29 4
gpt4 key购买 nike

得到一个字节包,是SSL协议(protocol)包的ClientHello

在我开始自己编写代码之前,一段代码遍历所有字节以获取每个字段值,我想知道是否有任何 Java 对象(来自 java.security)用于获取这些字节并解析数据,以便我能够获取 SSL 协议(protocol)字段并使用它们?

最佳答案

据我所知,Java 中的 java.security 包没有提供您所寻找的任何功能。 GitHub 上可能还有其他示例/库。

如果您最终自己这样做,需要注意的关键事项是:

  • SSLv2 对比 SSLv3 对比 TLSv1 ClientHello格式
  • 你的问题标题提到了证书;客户端证书存在ClientHello消息;它们仅在握手过程的后期发送,以响应 CertificateRequest来自服务器的消息。

解码 SSL/TLS 消息通常涉及阅读(并重新阅读)相关的 RFC,并根据每个字节值在数据包中的位置来确定每个字节值的含义。作为二进制协议(protocol)设计,为了提高效率,梳理出你想要的字段可能比你认为必要的更复杂。但了解这些领域是非常值得的。

下面是一些 Java 代码,可能有助于您入门。 请注意它在 Java 中使用字节缓冲区,因为在像这样解码二进制协议(protocol)时需要处理未签名数据类型。

// These values are defined in the IETF TLS cipher suite registry; see:
//
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-3
private static final int RC4_MD5_HEX = 0x0004;
private static final int RC4_SHA_HEX = 0x0005;

private static final short HANDSHAKE_CONTENT_TYPE = 22;
private static final short CLIENTHELLO_MESSAGE_TYPE = 1;

private static final short SSLV2_CLIENTHELLO = 128;
protected boolean doDecode(IoSession session,
IoBufferEx original,
ProtocolDecoderOutput out)
throws Exception {

// Need at least 2 bytes to differentiate between SSLv2 ClientHello
// messages and SSLv3/TLSv1/+ messages.
//
// For SSLv2 ClientHello, we need:
//
// length header (short)
// content type (byte)
//
// For more details, see:
//
// https://datatracker.ietf.org/doc/html/draft-hickman-netscape-ssl-00
//
// Otherwise, we need:
//
// content type (byte)
// version (short)
// length (short)
//
// So wait for at least 5 bytes, to cover either case.

if (original.remaining() < 5) {
return false;
}

// Make a copy, so that we can read things non-destructively
IoBufferEx dup = original.duplicate();

// If not a Handshake record, be done. Note that we have to
// successfully handle SSLv2 ClientHello formats as well.

short contentType = dup.getUnsigned();
if (contentType == HANDSHAKE_CONTENT_TYPE) {
// Skip the ProtocolVersion here; we will get it later
dup.skip(2);

int recordSize = dup.getUnsignedShort();

// Now wait until we have the entire record
if (original.remaining() < (5 + recordSize)) {
// Keep buffering
return false;
}

} else if (contentType == SSLV2_CLIENTHELLO) {
short len = dup.getUnsigned();

// Decode the length
int recordSize = ((contentType & 0x7f) << 8 | len);

// Now wait until we have the entire record
if (original.remaining() < (2 + recordSize)) {
// Keep buffering
return false;
}

} else {
// We're only interested in Handshake records
out.write(original.getSlice(original.remaining()));
return true;
}

// For the format of the ClientHello message, see RFC 5246,
// Section 7.4.1.2.

short messageType = dup.getUnsigned();
if (messageType != CLIENTHELLO_MESSAGE_TYPE) {
// We're only interested in ClientHello messages
out.write(original.getSlice(original.remaining()));
return true;
}

if (contentType == HANDSHAKE_CONTENT_TYPE) {
// If we're not an SSLv2 ClientHello, then skip the ClientHello
// message size.
dup.skip(3);

// Use the ClientHello ProtocolVersion
SslVersion version = SslVersion.decode(dup.getUnsignedShort());

// Skip ClientRandom
dup.skip(32);

// Skip SessionID
int sessionIDSize = dup.getUnsigned();
dup.skip(sessionIDSize);

// Now we get to what we're really after: the ciphersuites supported
// by the client.
int cipherSuiteSize = dup.getUnsignedShort();

// cipherSuiteSize is the number of bytes; each cipher is specified
// using a short (2 bytes). Thus the cipher suite count is the half
// the cipher suite size.
int cipherSuiteCount = cipherSuiteSize / 2;

// Iterate through each of the ciphersuites

for (int i = 0; i < cipherSuiteCount; i++) {
int cipher = dup.getUnsignedShort();

if (cipher == RC4_SHA_HEX) {
ciphers.add(SslCipherSelectionFilter.RC4_SHA);

} else if (cipher == RC4_MD5_HEX) {
ciphers.add(SslCipherSelectionFilter.RC4_MD5);
}
}

} else {
// SSLv2 ClientHello.
// Use the ClientHello ProtocolVersion
SslVersion version = SslVersion.decode(dup.getUnsignedShort());

// Determine cipher specs size
short msb = dup.getUnsigned();
short lsb = dup.getUnsigned();
int cipherSuiteSize = ((msb << 8) | lsb);

// Skip the sessionID size
dup.skip(2);

// Skip the challenge size
dup.skip(2);

// Now we get to what we're really after: the ciphersuites supported
// by the client.

// cipherSuiteSize is the number of bytes; each cipher is specified
// using a medium int (3 bytes).
int cipherSuiteCount = cipherSuiteSize / 3;

// Iterate through each of the ciphersuites, looking for
// SSL_RSA_WITH_RC4_128_MD5. (It's the only one supported in
// SSLv2 ClientHellos).

for (int i = 0; i < cipherSuiteCount; i++) {
int cipherKind = dup.getUnsignedMediumInt();

if (cipherKind == SSLV2_RC4_MD5_HEX) {
appletCiphers.add(SslCipherSelectionFilter.RC4_MD5);
}
}
}

out.write(original.getSlice(original.remaining()));
return true;
}

查看此 SslClientHelloDecoder.java其余代码的文件。

希望这对您有所帮助!

关于java - Java 中是否有任何 Java x509certificate ClientHello 解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34131970/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com