java JSSE中有DTLS实现吗

kx7yvsdv  于 2023-03-28  发布在  Java
关注(0)|答案(4)|浏览(235)

我想在Java中实现一个DTLS 1.0客户端,在谷歌搜索了一下之后,我发现JSSERefGuide说:
JSSE API能够支持SSL 2.0和3.0版本以及TLS 1.0版本。这些安全协议封装了一个普通的双向流套接字,JSSE API增加了对身份验证、加密和完整性保护的透明支持。**JDK附带的JSSE实现支持SSL 3.0、TLS(1.0、1.1和1.2)和DTLS(版本1.0和1.2)。**它不实现SSL 2.0。
所以我想我可以用纯Java实现它,而不需要使用任何库(例如BouncyCastle)
但是当我尝试运行时(以及其他一些,如DTLSv1.2,DTLSv1...):

final SSLContext sslContext = SSLContext.getInstance("DTLSv1.0", "SunJSSE");

它抛出:

Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: DTLSv1.0 for provider SunJSSE
at sun.security.jca.GetInstance.getService(GetInstance.java:87)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at javax.net.ssl.SSLContext.getInstance(SSLContext.java:199)

而例如以下工作:

final SSLContext sslContext = SSLContext.getInstance("TLSv1.2", "SunJSSE");

列出所有安全提供程序,我发现根本没有DTLS的东西。
那么,实际上有DTLS实现吗?如果有,你应该如何使用它?

kmpatx3s

kmpatx3s1#

您可以使用https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java(或https://github.com/twosigma/OpenJDK/blob/master/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java,相同)
对于因为链接而杀死我之前答案的人:即使链接中断,这也没有问题--因为查看链接时,你会很容易地看到DTLSOverDatagram是官方open-jdk 11测试的一部分--所以即使链接消失,你也可以很容易地找到其他来源。
虽然这些测试是针对DTLS实现的,但只要稍加重构,就可以用作基于udp-数据报的DTLS的基础。对于客户端和服务器端-实际上,它们几乎是相同的。

3pmvbmvn

3pmvbmvn2#

文档是正确的,您会得到一个异常,因为没有DTLS协议:https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
在创建套接字时选择DTLS,因为它将是TCP或数据报类型之一。开始时,它看起来像:

DatagramSocket s = new DatagramSocket();
...

final SSLContext sslContext = SSLContext.getInstance("TLSv1.0", "SunJSSE");
sslContext.init(null, yourSSLTrustManager, null);

SSLSocketFactory factory = (SSLSocketFactory)sslContext.getSocketFactory();
SSLSocket daSocket = (SSLSocket) factory.createSocket(s, host, port, false);
7fhtutme

7fhtutme3#

DTLS在JavaSE 9中存在:SSLContext算法名称

zphenhs4

zphenhs44#

基于JDK的示例和许多尝试和错误,我编写了以下代码,在我的用例中工作:

public static final int      MAXIMUM_PACKET_SIZE = 1500;
private final DatagramSocket socket;
private final SSLEngine      engine;

public DtlsSocket( @Nonnull DatagramSocket socket, KeyManager km, TrustManager tm, boolean isClient ) {
    try {
        this.socket = socket;

        SSLContext sslCtx = SSLContext.getInstance( "DTLS" );
        KeyManager[] kms = { km };
        TrustManager[] tms = { tm };
        sslCtx.init( kms, tms, null );
        engine = sslCtx.createSSLEngine();
        engine.setNeedClientAuth( true );

        engine.setUseClientMode( isClient );
        SSLParameters paras = engine.getSSLParameters();
        paras.setMaximumPacketSize( MAXIMUM_PACKET_SIZE );
        engine.setSSLParameters( paras );

        engine.beginHandshake();

        byte[] receiveBytes = new byte[MAXIMUM_PACKET_SIZE];
        DatagramPacket receivePacket = new DatagramPacket( receiveBytes, 0, MAXIMUM_PACKET_SIZE );
        ByteBuffer receiveBuffer = ByteBuffer.wrap( receiveBytes );
        receiveBuffer.limit( 0 );

        ByteBuffer emptyBuffer = ByteBuffer.allocate( 0 );

        byte[] sendData = new byte[32768];
        DatagramPacket sendPacket = new DatagramPacket( sendData, 0, 32768 );
        ByteBuffer sendBuffer = ByteBuffer.wrap( sendData );

        while( true ) {
            SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
            switch( hs ) {
                case NEED_UNWRAP:
                case NEED_UNWRAP_AGAIN:
                    if( !receiveBuffer.hasRemaining() && hs != SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN ) {
                        socket.receive( receivePacket );
                        receiveBuffer.position( 0 );
                        receiveBuffer.limit( receivePacket.getLength() );
                    }
                    checkStatus( engine.unwrap( receiveBuffer, emptyBuffer ) );
                    break;
                case NEED_WRAP:
                    checkStatus( engine.wrap( emptyBuffer, sendBuffer.clear() ) );
                    sendPacket.setLength( sendBuffer.position() );
                    socket.send( sendPacket );
                    break;
                case NEED_TASK:
                    Runnable runnable;
                    while( (runnable = engine.getDelegatedTask()) != null ) {
                        runnable.run();
                    }
                    break;
                case NOT_HANDSHAKING:
                    return;
                default:
                    // should never occur
                    throw new SSLException( "handshake error " + hs );
            }
        }
    } catch( Exception ex ) {
        throw ErrorCode.throwAny( ex );
    }
}

private void checkStatus( SSLEngineResult engineResult ) throws IOException {
    if( engineResult.getStatus() != SSLEngineResult.Status.OK ) {
        throw new SSLException( "handshake error " + engineResult.getStatus() + " with handshake state " + engineResult.getHandshakeStatus() );
    }
}

相关问题