- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在我创建 SSLEngine 之前,我需要在第一个 SSL 客户端问候的扩展中使用 SNI 服务器名称(当然如果它存在的话)。我在这里查看 ClientHello 类...(尽管我现在使用的是 jdk 8)。
有谁知道如何更轻松地从 ByteBuffer 转到数据结构以获取 SNI 服务器名? (字节缓冲区将包含一个等于或大于所需大小的大小,因为我已经检查了 SSL 数据包的大小并等待我拥有完整的 ssl hello 数据包)。
此外,这篇文章对于让起始部分到位非常有效 Is there any Java x509certificate ClientHello parser in Java?
谢谢,院长
最佳答案
供其他人重复使用,但这是我的第一次尝试,它的工作原理使我可以在握手开始之前获取 sniServerName...
public class ClientHelloParser {
private static final short HANDSHAKE_CONTENT_TYPE = 22;
private static final short CLIENTHELLO_MESSAGE_TYPE = 1;
private static final short SSLV2_CLIENTHELLO = 128;
private static final int SERVER_NAME_EXTENSION_TYPE = 0;
private static final short HOST_NAME_TYPE = 0;
private ByteBuffer cachedBuffer;
private BufferPool pool;
public ClientHelloParser(BufferPool pool) {
this.pool = pool;
}
/**
* Returns null if we still need more data
*
* @param b
* @return
*/
ParseResult fetchServerNamesIfEntirePacketAvailable(ByteBuffer b) {
if(cachedBuffer != null) {
//prefix cachedBuffer in front of b and assign to b as the packet that is coming in
ByteBuffer newBuf = pool.nextBuffer(cachedBuffer.remaining()+b.remaining());
newBuf.put(cachedBuffer);
newBuf.put(b);
newBuf.flip();
pool.releaseBuffer(b); //release b that is now in the newBuf
pool.releaseBuffer(cachedBuffer); //release cached buffer that is now in newBuf
b = newBuf;
}
if(b.remaining() < 5) {
cachedBuffer = b;
return null; //wait for more data
}
int recordSize = 0;
ByteBuffer duplicate = b.duplicate();
short contentType = getUnsignedByte(duplicate);
if(contentType == HANDSHAKE_CONTENT_TYPE) {
getUnsignedByte(duplicate);
getUnsignedByte(duplicate);
recordSize = getUnsignedShort(duplicate);
// Now wait until we have the entire record
if (b.remaining() < (5 + recordSize)) {
// Keep buffering
return null;
}
} else if (contentType == SSLV2_CLIENTHELLO) {
short len = getUnsignedByte(duplicate);
// Decode the length
recordSize = ((contentType & 0x7f) << 8 | len);
// Now wait until we have the entire record
if (b.remaining() < (2 + recordSize)) {
// Keep buffering
return null;
}
} else {
throw new IllegalStateException("contentType="+contentType+" not supported in ssl hello handshake packet");
}
short messageType = getUnsignedByte(duplicate);
if (messageType != CLIENTHELLO_MESSAGE_TYPE) {
throw new IllegalStateException("something came before ClientHello :( messageType="+messageType);
}
if (contentType == HANDSHAKE_CONTENT_TYPE) {
// If we're not an SSLv2 ClientHello, then skip the ClientHello
// message size.
duplicate.get(new byte[3]);
// Use the ClientHello ProtocolVersion
getUnsignedShort(duplicate);
// Skip ClientRandom
duplicate.get(new byte[32]);
// Skip SessionID
int sessionIDSize = getUnsignedByte(duplicate);
duplicate.get(new byte[sessionIDSize]);
//read in and discard cipherSuite...
int cipherSuiteSize = getUnsignedShort(duplicate);
duplicate.get(new byte[cipherSuiteSize]);
//read in compression methods size and discard..
short compressionMethodsLen = getUnsignedByte(duplicate);
duplicate.get(new byte[compressionMethodsLen]);
int extensionLen = getUnsignedShort(duplicate);
List<String> names = readInExtensionServerNames(duplicate, extensionLen);
return new ParseResult(b, names);
} else {
// SSLv2 ClientHello.
// Use the ClientHello ProtocolVersion
//SslVersion version = SslVersion.decode(getUnsignedByte(duplicate));
throw new UnsupportedOperationException("not supported yet");
}
}
private List<String> readInExtensionServerNames(ByteBuffer duplicate, int len) {
List<String> serverNames = new ArrayList<>();
int byteCount = 0;
while(byteCount < len) {
byteCount += 4; //reading in 4 bytes so add them in
if(duplicate.remaining() < 4)
throw new IllegalStateException("Corrupt packet with incorrect format");
int type = getUnsignedShort(duplicate);
int extLen = getUnsignedShort(duplicate);
if(duplicate.remaining() < extLen)
throw new IllegalStateException("Corrupt packet with incorrect format as len didn't match");
if(type == SERVER_NAME_EXTENSION_TYPE) {
String name = readServerNames(duplicate, extLen);
serverNames.add(name);
} else
duplicate.get(new byte[extLen]);
byteCount += extLen;
}
return serverNames;
}
private String readServerNames(ByteBuffer duplicate, int extLen) {
int byteCount = 0;
byteCount += 2; //for listLen 2 bytes
int listLen = getUnsignedShort(duplicate);
if(listLen + 2 != extLen)
throw new RuntimeException("we have something we need to fix here as listLen is only two less bytes then extensionLength");
byteCount += 1; //for serverNameType
short serverNameType = getUnsignedByte(duplicate);
if(serverNameType != HOST_NAME_TYPE)
throw new IllegalStateException("Server name type="+serverNameType+" not supported yet");
byteCount += 2; //for serverNameLen
int serverNameLen = getUnsignedShort(duplicate);
byteCount += serverNameLen;
if(byteCount != extLen)
throw new UnsupportedOperationException("bytes read in servernames extension does not match extLen(we need to loop here then)");
byte[] data = new byte[serverNameLen];
duplicate.get(data);
String serverName = new String(data);
return serverName;
}
public short getUnsignedByte(ByteBuffer bb) {
return ((short)(bb.get() & 0xff));
}
public int getUnsignedShort (ByteBuffer bb)
{
return (bb.getShort() & 0xffff);
}
}
关于java - 如何将第一个 hello SSL 消息转换为 jdk ClientHello.java 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37290053/
我在客户端使用 openJdk 11.28 版。在调用通过 https 部署的 Web 服务时,我遇到握手失败。 Web 服务的 Nmap 命令提供以下结果: 我在我的 java 中启用了 ssl,h
我们正在运行一个 gradle + java + spring boot 后端,通过 SOAP 与外部服务器进行通信。它最初是使用 Java 8 构建的。 最近服务器已将其接受的密码套件列表更新为 E
我是 OpenSSL 的新手,正在尝试扩展 API。我想创建尽可能自定义的 ClientHello,以便查看我的服务器如何对其作出 react 。 我的问题是:如何从库外部(在我的程序中)设置 Cli
我需要连接到 SSL 服务器。当我使用 OpenSSL 1.0.1r 连接时,它工作正常: CONNECTED(00000304) write to 0x6e13e8 [0x730a98] (297
我正在尝试使用带有 WolfSSL 的 tls1.2 将嵌入式设备连接到 smtp.gmail.com:465。该库创建并发送以下 clientHello 消息并收到握手失败消息。 16 03 03
编辑:我将把它作为调试 SSL 的一个很好的例子。 最终分析:我们遇到了一个网络问题,其中一台路由器针对完全不同的应用程序进行了错误配置,导致该路由器在 CPU 使用率上处于临界状态。前几次握手没有固
我有一个在 OSX 10.12.3 上运行的 Java 8 HTTPS 客户端,它在握手过程的早期就失败了。这是我在启用 SSL 调试信息时看到的错误: trigger seeding of Secu
我正在开发一个需要管理不同 SSL 服务的服务器应用程序。每个服务都有自己的证书(当然有不同的 CN)。我想用 SNI提供正确的证书,但在对流进行身份验证之前,我正在努力阅读 ClientHello(
我正在使用与 UDP 不同的网络传输协议(protocol)构建 DTLS 服务器和客户端设置。但是这个协议(protocol)也是不可靠的,所以需要 DTLS。该协议(protocol)使用 rad
我一直在尝试使用 OpenSSL 编写 DTLS 服务器/客户端,但我遇到了 DTLSv1_listen 的问题。失败,因为 ClientHello消息是零散的(我读过这是因为 DTLSv1_list
SSL3.0 specification/page22 提供了以下结构描述: The structure of the client hello is as follows. struct {
我有这段代码 public static void main(String...args) { System.setProperty("javax.net.debug", "all")
得到一个字节包,是SSL协议(protocol)包的ClientHello 在我开始自己编写代码之前,一段代码遍历所有字节以获取每个字段值,我想知道是否有任何 Java 对象(来自 java.secu
我将使用 Scapy 模拟 DTLS 初始握手。由于 Scapy 不支持 DTLS,我不得不使用 scapy-ssl_tls 来构建 DTLS 数据包。我首先尝试使用 TLS 并发送了一个 Clien
我正在使用 OpenSSL 为 NodeJS 编写 native DTLS 模块。它使用内存 BIO,因此节点自己的套接字可用于控制数据流。一切似乎都正常,但我在 DOS 缓解方面遇到了一些问题。 根
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this q
我在 java1.8 中工作并通过 OKHTTP 连接到 APNS (api.push.apple.com)。 症状是 SSL 握手失败:javax.net.ssl.SSLHandshakeExcep
在我创建 SSLEngine 之前,我需要在第一个 SSL 客户端问候的扩展中使用 SNI 服务器名称(当然如果它存在的话)。我在这里查看 ClientHello 类...(尽管我现在使用的是 jdk
在我正在运行的服务器上(使用 OpenSSL 1.1.1d),我尝试使用以下回调从 ClientHello 消息中提取服务器名称 (SNI) 扩展名 API通过: 使用 TLSEXT_TYPE_ser
https://en.wikipedia.org/wiki/Transport_Layer_Security#Protocol_details 我正在研究 SSL/TSL 握手的工作原理,虽然我了解了
我是一名优秀的程序员,十分优秀!