- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
得到一个字节包,是SSL协议(protocol)包的ClientHello
在我开始自己编写代码之前,一段代码遍历所有字节以获取每个字段值,我想知道是否有任何 Java 对象(来自 java.security)用于获取这些字节并解析数据,以便我能够获取 SSL 协议(protocol)字段并使用它们?
最佳答案
据我所知,Java 中的 java.security
包没有提供您所寻找的任何功能。 GitHub 上可能还有其他示例/库。
如果您最终自己这样做,需要注意的关键事项是:
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/
我们想在应用商店中发布一个应用。为我们构建它的第 3 方需要我们通过苹果开发门户创建的证书和配置文件。根据文档,创建证书的方法是使用 mac 的钥匙串(keychain)应用程序,然后选择“从证书颁发
我正在尝试使用 Java Http 客户端连接到服务器以进行 Web 服务调用。如果我用下面的代码打开网络调试.. System.setProperty("javax.net.debug", "all
我在尝试推送我的更改时才开始收到此错误。我不知道我的系统发生了什么变化,并且在这方面不应该有任何自签名证书。 Git 已卸载并重新安装。 Git 似乎使用了正确的包: http.sslcainfo=C
除非我设置以下内容,否则我会收到上述错误: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 这是不安全的,违背了 SSL 的目的。 我已经从 http
我有一个基于 Linux 的 Docker 容器,如果我这样做: curl https://google.com ...然后我得到一个错误: curl: (60) SSL certificate pr
我想在我的 Linux 计算机上安装 nvm。(我的 Debian 版本是 10,Git 版本是 2.27。OPENSSL 版本是 1.1.1d 2019 年 9 月 10 日) 我阅读了这份文件 h
我正在使用 Symfony 5,我需要使用 composer 安装 'knplabs/knp-snappy-bundle' 但我有这个消息: [Composer\Downloader\Transpor
我已经通过 VSTS 部署我的应用程序一段时间了,然后突然出现此错误: 无法访问 SSL 证书问题:(url) 证书链中的自签名证书。 为什么突然发生这种情况,我该如何解决? 更新:我注意到我有一个新
我正在尝试使用安全性配置 WCF 服务。我生成了 2 个存储在 LocalComputer\Personal Certificates 中的证书(用于服务器和客户端)。我的配置是: 服务器:
我正在创建连接到的 Azure 函数来执行 PnP 命令。我已经创建了 docs 中提到的证书。我总是收到Cannot findcertificate with this指纹在证书存储中。Except
美好的一天,我是服务器设置的新手。我目前正在使用 laravel 5.4 来集成我的 quickbooks app在我的实时服务器上 http://qb.dagnum.com/connect但我继续收
我正在尝试从 Github 克隆一个项目但我无法克隆它,因为我有这个错误 无法访问:SSL 证书问题:证书链中的自签名证书 我可以从我的网络访问并且我有证书。 我的Android Studio有什么问
我正在尝试使用 AWS-CLI 检索 aws elasticbeanstalk 详细信息,但出现以下错误。 错误信息: C:\abdul>aws elasticbeanstalk describe-e
我实际上正在阅读有关证书和证书链的内容。我了解证书是由实体的私钥签名的一段数据,只能使用给定实体(例如根 CA)的公钥解密。 但是,我在几个地方看到“证书签署另一个证书”(例如:Microsoft I
我想默认“接受”新证书。我尝试了以下方法。 $ dpkg-reconfigure -f noninteractive ca-certificates 它运行,但没有添加 CA。 如果不行,直接修改/e
有人通过AWS Certificate Manager为他们的域名购买了通配符证书,我需要将其转移到Heroku,以获取使用域名子域名的应用程序。 无论是通过AWS控制台还是通过其CLI,我都找不到如
我可以通过重新启动我的 Windows 7 来运行 selenium 服务器。但是,如果我终止服务器并再次启动它,我将收到此错误。有时执行 webdriver-manager update--igno
我在 IE9 中遇到安全证书问题。 然后我去我得到的特定地址 There is a problem with this website's security certificate. 如何避免出现此窗
应用签名证书和上传证书有什么区别? 我在将 Google Play 游戏与我的应用程序集成时遇到了问题(我将此作为另一个问题发布),我注意到用于在 Google API 控制台上自动生成的客户端 ID
我正在尝试在 Mac 上使用 Heroku CLI。 当我尝试使用 Heroku login 登录 Heroku 并提供我的凭据时,出现以下错误: Error: self signed certifi
我是一名优秀的程序员,十分优秀!