Java SSL客户端/服务器随机值
我需要访问SSL/TLS握手过程中交换的SSL服务器/客户端随机数,以便以后在封装协议中使用它们Java SSL客户端/服务器随机值,java,ssl,Java,Ssl,我需要访问SSL/TLS握手过程中交换的SSL服务器/客户端随机数,以便以后在封装协议中使用它们 如何在Java中访问这些值?我已经看过了SSLSocket.getHandshake(),但它似乎没有公开值。JSSE中没有API调用可以让您直接访问它 您可以通过-Djavax.net.debug=ssl(“Client Nonce”)轻松地看到这一点,但这在应用程序中是不可访问的 您可以通过私有成员上的反射来实现这一点,但是这通常是一个坏主意(就像在私有API上使用私有成员的反射一样)。这将非常
如何在Java中访问这些值?我已经看过了
SSLSocket.getHandshake()
,但它似乎没有公开值。JSSE中没有API调用可以让您直接访问它
您可以通过-Djavax.net.debug=ssl
(“Client Nonce
”)轻松地看到这一点,但这在应用程序中是不可访问的
您可以通过私有成员上的反射来实现这一点,但是这通常是一个坏主意(就像在私有API上使用私有成员的反射一样)。这将非常依赖于您正在使用的Java的版本和实现
Field handshakerField = sslSocket.getClass().getDeclaredField(
"handshaker");
handshakerField.setAccessible(true);
Object handShakerObj = handshakerField.get(sslSocket);
System.out.println(handShakerObj);
// Only start the handshake *after* you've got hold of the handshaker object,
// otherwise it will be null.
sslSocket.startHandshake();
Class<?> handshakerClass = Class.forName("sun.security.ssl.Handshaker");
Field clientRandomField = handshakerClass
.getDeclaredField("clnt_random");
clientRandomField.setAccessible(true);
Object clientRandomObj = clientRandomField.get(handShakerObj);
System.out.println(clientRandomObj);
Field randomBytesField = clientRandomObj.getClass().getDeclaredField(
"random_bytes");
randomBytesField.setAccessible(true);
byte[] randomBytesObj = (byte[])randomBytesField.get(clientRandomObj);
Field handshakerField=sslSocket.getClass().getDeclaredField(
“握手者”);
handshakerField.setAccessible(true);
objecthandshakerobj=handshakerField.get(sslSocket);
System.out.println(握手器bj);
//只有在握住握手器对象后才能开始握手,
//否则它将为空。
sslSocket.startHandshake();
Class handshakerClass=Class.forName(“sun.security.ssl.Handshaker”);
字段clientRandomField=握手类
.getDeclaredField(“clnt_随机”);
clientRandomField.setAccessible(true);
Object clientRandomObj=clientRandomField.get(handShakerObj);
System.out.println(clientRandomObj);
Field randomBytesField=clientRandomObj.getClass().getDeclaredField(
“随机_字节”);
randomBytesField.setAccessible(true);
字节[]randomBytesObj=(字节[])randomBytesField.get(clientRandomObj);
我不知道你的封装协议为什么需要这个。这似乎根本不是个好主意。目前还不清楚这意味着要增加什么样的安全性。如果您确实想要某种SSL/TLS通道令牌,那么使用会话ID可能会更好(尽管这也不一定是个好主意)
一般来说,大多数SSL/TLS堆栈都不会让您掌握这一点。它的主要目的是生成
pre_master_secret
和。如果您想知道如何从SSLEngine中提取客户端/服务器随机数,请使用以下类(至少适用于java 8):
包sun.security.ssl;
导入javax.net.ssl.SSLEngine;
导入java.lang.reflect.Field;
公共类SSLEngineInspector{
私有最终对象transportContextObj;
私有对象握手;
专用字节[]clientRandom;
私有字节[]随机;
公共SSLEngine检查员(SSLEngine SSLEngine){
试一试{
Field conContext=sslEngine.getClass().getDeclaredField(“conContext”);
conContext.setAccessible(true);
transportContextObj=concentext.get(sslEngine);
}捕获(NoSuchFieldException | IllegalacessException e){
抛出新的运行时异常(e);
}
}
公共无效captureClientHello(){
试一试{
Class-forName=Class.forName(“sun.security.ssl.TransportContext”);
Field handshakeContext=forName.getDeclaredField(“handshakeContext”);
handshakeContext.setAccessible(true);
handshakeContextObj=handshakeContextObj.get(transportContextObj);
forName=Class.forName(“sun.security.ssl.HandshakeContext”);
字段clientHelloRandom=forName.getDeclaredField(“clientHelloRandom”);
clientHelloRandom.setAccessible(true);
对象clientHelloRandomObj=clientHelloRandom.get(handshakeContextObj);
forName=Class.forName(“sun.security.ssl.RandomCookie”);
Field randomBytes=forName.getDeclaredField(“randomBytes”);
randomBytes.setAccessible(true);
clientRandom=(byte[])randomBytes.get(clientHelloRandomObj);
}捕获(ClassNotFoundException | NoSuchFieldException | IllegalacessException e){
抛出新的运行时异常(e);
}
}
公共无效captureServerHello(){
试一试{
Class-forName=Class.forName(“sun.security.ssl.HandshakeContext”);
字段serverHelloRandom=forName.getDeclaredField(“serverHelloRandom”);
serverHelloRandom.setAccessible(true);
对象serverhellorandombj=serverHelloRandom.get(handshakeContextObj);
forName=Class.forName(“sun.security.ssl.RandomCookie”);
Field randomBytes=forName.getDeclaredField(“randomBytes”);
randomBytes.setAccessible(true);
serverRandom=(byte[])randomBytes.get(serverhellorandombj);
}捕获(ClassNotFoundException | NoSuchFieldException | IllegalacessException e){
抛出新的运行时异常(e);
}
}
}
这看起来是一个合理的问题,尽管答案可能是“你不能那样做”。为什么以后要使用这些值?这看起来像是违反了层分离和气味。原因是我正在实现一个tor协议服务器,并且由于SSL证书未签名(以停止标识攻击),内部tor协议根据协商一致中的签名密钥对TLS会话执行身份验证。这是通过对服务器和客户端随机签名来实现的。此外,如果JSSE不能做到这一点,那么我欢迎关于其他实现的想法,我可以修改这些实现来实现这一点(我宁愿不修改JSSE)。我发现这样做的要点很粗糙:更好的解决方案welcomeBruno-我可以吻你!谢谢你,这正是我想要的!我同意这是一个奇怪的请求,我同意这是一个有点奇怪的做事方式,但不幸的是,这个协议是标准化的,我需要实施它。(也谢谢你关于经前综合症的提示)。老实说,这都是非常狡猾的,无论是t
package sun.security.ssl;
import javax.net.ssl.SSLEngine;
import java.lang.reflect.Field;
public class SSLEngineInspector {
private final Object transportContextObj;
private Object handshakeContextObj;
private byte[] clientRandom;
private byte[] serverRandom;
public SSLEngineInspector(SSLEngine sslEngine) {
try {
Field conContext = sslEngine.getClass().getDeclaredField("conContext");
conContext.setAccessible(true);
transportContextObj = conContext.get(sslEngine);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void captureClientHello() {
try {
Class<?> forName = Class.forName("sun.security.ssl.TransportContext");
Field handshakeContext = forName.getDeclaredField("handshakeContext");
handshakeContext.setAccessible(true);
handshakeContextObj = handshakeContext.get(transportContextObj);
forName = Class.forName("sun.security.ssl.HandshakeContext");
Field clientHelloRandom = forName.getDeclaredField("clientHelloRandom");
clientHelloRandom.setAccessible(true);
Object clientHelloRandomObj = clientHelloRandom.get(handshakeContextObj);
forName = Class.forName("sun.security.ssl.RandomCookie");
Field randomBytes = forName.getDeclaredField("randomBytes");
randomBytes.setAccessible(true);
clientRandom = (byte[]) randomBytes.get(clientHelloRandomObj);
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void captureServerHello() {
try {
Class<?> forName = Class.forName("sun.security.ssl.HandshakeContext");
Field serverHelloRandom = forName.getDeclaredField("serverHelloRandom");
serverHelloRandom.setAccessible(true);
Object serverHelloRandomObj = serverHelloRandom.get(handshakeContextObj);
forName = Class.forName("sun.security.ssl.RandomCookie");
Field randomBytes = forName.getDeclaredField("randomBytes");
randomBytes.setAccessible(true);
serverRandom = (byte[]) randomBytes.get(serverHelloRandomObj);
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}