Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SSL客户端/服务器随机值_Java_Ssl - Fatal编程技术网

Java SSL客户端/服务器随机值

Java SSL客户端/服务器随机值,java,ssl,Java,Ssl,我需要访问SSL/TLS握手过程中交换的SSL服务器/客户端随机数,以便以后在封装协议中使用它们 如何在Java中访问这些值?我已经看过了SSLSocket.getHandshake(),但它似乎没有公开值。JSSE中没有API调用可以让您直接访问它 您可以通过-Djavax.net.debug=ssl(“Client Nonce”)轻松地看到这一点,但这在应用程序中是不可访问的 您可以通过私有成员上的反射来实现这一点,但是这通常是一个坏主意(就像在私有API上使用私有成员的反射一样)。这将非常

我需要访问SSL/TLS握手过程中交换的SSL服务器/客户端随机数,以便以后在封装协议中使用它们


如何在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);
        }
    }
}