Почему не удается установить соединение TLS в Java-приложении?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Почему не удается установить соединение TLS в Java-приложении?

Сообщение Anonymous »

Я создаю клиент-серверное приложение. Я пытаюсь установить связь TLS, но подтверждение TLS не удается. Сервер и клиент находятся на одном компьютере, на одной виртуальной машине. Я уже проверил, что сгенерированный мной сертификат использует не DSA, а sha256WithRSAEncryption. Он основан на сгенерированном мной ключе длиной 3072 бита. Я сгенерировал их оба с помощью команды certtool. Я создал хранилище ключей для сервера и хранилище доверенных сертификатов для клиента на основе этого сертификата и закрытого ключа с помощью команды keytool.
Вот какую ошибку я получаю

Код: Выделить всё

java -jar target/testNio-1.0-SNAPSHOT.jar

Server launched on port 8443
Boss capture thread launches
Server handler launches
Worker thread launches
Thread sending messages launches
Attempted connection detected
TCP connection established with /127.0.0.1:44448
Attempted tls connection detected
NEED_UNWRAP
flag 1
NEED_TASK
NEED_WRAP
flag 2

javax.net.ssl.SSLHandshakeException: No available authentication scheme
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:365)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:312)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateProducer.onProduceCertificate(CertificateMessage.java:975)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateProducer.produce(CertificateMessage.java:964)
at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:437)
at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1245)
at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1181)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:839)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:800)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:393)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:476)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1274)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1260)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1205)
at io.test2.Boss.handleTLSConnection2(Boss.java:169)
at io.test2.Boss.run(Boss.java:218)
Это код класса, отвечающего за установление tls-соединений.

Код: Выделить всё

package io.test2;

import java.io.IOException;
import java.nio.ByteBuffer;
//import java.net.InetSocketAddress;
//import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.net.ssl.*;

public class Boss extends Thread {
public Selector acceptor;
public Selector com;
public ServerSocketChannel serverChannel;
public boolean running;
public ArrayList sessions;
public ArrayList sessionsTemp;
public SSLContext sslContext;

public Boss (Selector acceptor, Selector com, ServerSocketChannel ssc,
ArrayList sessions, SSLContext sslc) throws Exception{
this.acceptor = acceptor;
this.com = com;
this.serverChannel = ssc;
this.sessions = sessions;
running = true;
this.sslContext = sslc;
sessionsTemp = new ArrayList();
}

public void shutdown() {
running = false;
acceptor.wakeup();
}

public void clientClose(TLSConnectionInformation info, SocketChannel client) throws IOException{
for (int i = 0; i < sessionsTemp.size(); i++) {
if (sessions.get(i).id.equals(info.id)) {
sessions.remove(i);
break;
}
}
try {
ByteBuffer dummy = ByteBuffer.allocate(0);
ByteBuffer outBuffer = ByteBuffer.allocate(info.engine.getSession().getPacketBufferSize());
info.engine.wrap(dummy, outBuffer);
info.engine.closeOutbound();
info.engine.closeInbound();
} catch(SSLException e) {
e.printStackTrace();}
client.close();
}

public void handleTCPConnection(ServerSocketChannel ssc, Selector slct) throws IOException {

SocketChannel clientChannel = serverChannel.accept();
System.out.println("TCP connection established with "  + clientChannel.getRemoteAddress());
if (clientChannel != null) {
SSLEngine engine = sslContext.createSSLEngine();
//System.out.println(Arrays.toString(engine.getEnabledCipherSuites()));
engine.setUseClientMode(false); // Mode serveur
clientChannel.configureBlocking(false);
Session s = new Session(clientChannel, engine);
sessionsTemp.add(s);
clientChannel.register(acceptor, SelectionKey.OP_READ, new TLSConnectionInformation(engine, s.id));
engine.beginHandshake();
}
}

public void handleTLSConnection(SelectionKey key) throws IOException {
SocketChannel client = (SocketChannel) key.channel();
TLSConnectionInformation info = (TLSConnectionInformation) key.attachment();
SSLEngine engine = info.engine;
ByteBuffer appBuffer = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize());
ByteBuffer netBuffer = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
int bytesRead = client.read(netBuffer);
if (bytesRead == -1) {
clientClose(info, client);
return;
}
netBuffer.flip();

SSLEngineResult res = engine.unwrap(netBuffer, appBuffer);
//appBuffer.compact();
if (!isTLSHandShake(netBuffer)) {
System.out.println("Non-TLS attempted connection.  Closing connection");
clientClose(info, client);
return;
}
/*
* If some tasks are required to end the establishment of the TLS connection
*/
if (res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
Runnable task;
while ((task = engine.getDelegatedTask()) != null)
task.run();
}
if (res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {
for (int i = 0; i < sessionsTemp.size(); i++) {
if (sessionsTemp.get(i).sc.equals(client)) {
System.out.println("Connection accepted from " + sessionsTemp.get(i).id.toString());
sessions.add(sessionsTemp.get(i));
sessionsTemp.remove(i);
synchronized (com) {
com.wakeup();
client.register(com, SelectionKey.OP_READ, info);
}
break;
}
}
}
}

public boolean isTLSHandShake(ByteBuffer buffer) {

if (buffer.remaining() < 5)
return false;
if (buffer.get(0) == 22 && buffer.get(1) == 3)
return true;
return false;
}

public void handleTLSConnection2(SelectionKey key) throws IOException {
System.out.println("Attempted tls connection detected");
SocketChannel client = (SocketChannel) key.channel();
TLSConnectionInformation info = (TLSConnectionInformation) key.attachment();
SSLEngine engine = info.engine;
ByteBuffer appBuffer = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize());
ByteBuffer netBuffer = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
while (true) {
SSLEngineResult.HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
switch (handshakeStatus) {
case NEED_WRAP:
System.out.println("NEED_WRAP");
netBuffer.clear();
System.out.println("flag 2");
ByteBuffer buf = ByteBuffer.allocate(10);
SSLEngineResult wrapResult = engine.wrap(buf, netBuffer);        //HERE2
System.out.println("flag 3");
if (wrapResult.getStatus() == SSLEngineResult.Status.CLOSED) {
throw new IOException("Handshake failed: Engine closed during wrap");
}
System.out.println("flag 4");
netBuffer.flip();
if (netBuffer.hasRemaining()) {
client.write(netBuffer);
}
System.out.println("flag 5");
break;
case NEED_UNWRAP:
System.out.println("NEED_UNWRAP");
if (client.read(netBuffer) Но если я посмотрел на стандартный вывод, программа не проходит дальше флага 2, который равен //HERE2.
Поэтому моя ошибка может быть связана с вызовом engine.wrap() ; запущенные выполняемые задачи; что-то не так с сертификатом или что-то за пределами моего знания.
Ввод ключа;
[code]keytool -list -v -keystore keystoreServer.jks

Enter keystore password:

Keystore type: PKCS12

Keystore provider: SUN

Your keystore contains 1 entry

Alias name: server

Creation date: 14 janv.  2025

Entry type: trustedCertEntry

Owner: C=France, UID=1.0, CN=server

Issuer: C=France, UID=1.0, CN=server

Serial number: 3

Valid from: Mon Jan 13 22:39:56 CET 2025 until: Mon Jan 20 22:40:02 CET 2025

Certificate fingerprints:

SHA1: 4C:D8:8C:C6:3F:93:AE:F9:BC:A0:E9:B4:D5:1B:14:39:8D:87:B4:A9

SHA256: DD:F2:77:4C:F6:E5:61:3B:D1:6B:22:00:1C:5D:10:EC:F3:A9:9A:5C:FE:6F:FC:B2:8F:0C:0A:47:26:70:9E:DC

Signature algorithm name: SHA256withRSA

Subject Public Key Algorithm: 3072-bit RSA key

Version: 3

Extensions:

#1: ObjectId: 2.5.29.19 Criticality=true

BasicConstraints:[

CA:false

PathLen: undefined

]

#2: ObjectId: 2.5.29.37 Criticality=false

ExtendedKeyUsages [

serverAuth

codeSigning

timeStamping

]

#3: ObjectId: 2.5.29.15 Criticality=true

KeyUsage [

DigitalSignature

Key_Encipherment

Data_Encipherment

]

#4: ObjectId: 2.5.29.17 Criticality=false

SubjectAlternativeName [

DNSName: nio

]

#5: ObjectId: 2.5.29.14 Criticality=false

SubjectKeyIdentifier [

KeyIdentifier [

0000: 87 43 6A 3D 37 5B 8B 88   F1 26 78 5F EF 79 4B 51  .Cj=7[...&x_.yKQ

0010: 91 6A AA CC                                        .j..

]

]

*******************************************

*******************************************
Вот основной класс;

Код: Выделить всё

package io.test2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.ArrayList;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import sun.misc.Signal;
import sun.misc.SignalHandler;
import javax.net.ssl.*;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;

public class Server {
public static boolean running;

public static void main(String[] args) throws IOException, InterruptedException, Exception {

int port = 8443;
running = true;

KeyStore keyStore = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("ressources/keystoreServer.jks");
keyStore.load(fis, "motdepasse".toCharArray());

//SSLContext
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "motdepasse".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(port));
serverSocketChannel.configureBlocking(false);

System.out.println("Server launched on port "+ port);

Selector accept = Selector.open();
serverSocketChannel.register(accept, SelectionKey.OP_ACCEPT);

Selector com = Selector.open();

ArrayList sessions = new ArrayList();
LinkedBlockingQueue listOperationDone = new LinkedBlockingQueue();
LinkedBlockingQueue operationsDone = new LinkedBlockingQueue();
LinkedBlockingQueue  operationsToDo = new LinkedBlockingQueue();

Boss boss = new Boss(accept, com, serverSocketChannel, sessions, sslContext);
Worker worker = new Worker(listOperationDone, operationsToDo, operationsDone);
Receiver reciever = new Receiver(serverSocketChannel, operationsToDo,
sessions, listOperationDone, operationsDone, com);
Sender sender = new Sender(sessions, listOperationDone, operationsDone);

boss.start();
reciever.start();
worker.start();
sender.start();

Signal.handle(new Signal("INT"), new SignalHandler() {
@Override
public void handle(Signal signal) {
running = false;
}
});

while (running) {
Thread.sleep(1000);
}
System.out.println("Shutting down server");
boss.shutdown();
worker.shutdown();
reciever.shutdown();
sender.shutdown();
Thread.sleep(2000);
accept.close();
com.close();
sessions.clear();
listOperationDone.clear();
operationsDone.clear();
operationsToDo.clear();
System.out.println("Server shut down");
return;
}
}
архитектура моего проекта;

Код: Выделить всё

tree -L 6 testNio/

testNio/

├── pom.xml

├── ressources

│   ├── ca-cert.pem

│   ├── ca-key.pem

│   ├── certificateServer.pem

│   ├── key2.pem

│   ├── keystore.p12

│   ├── keystoreServer.jks

│   └── serveur-cert.crt

├── src

│   ├── main

│   │   └── java

│   │       └── io

│   │           ├── App.java

│   │           ├── test1

│   │           │   ├── Boss.java

│   │           │   ├── Operation.java

│   │           │   ├── Sender.java

│   │           │   ├── ServerHandler.java

│   │           │   ├── Server.java

│   │           │   ├── Session.java

│   │           │   └── Worker.java

│   │           └── test2

│   │               ├── Boss.java

│   │               ├── Operation.java

│   │               ├── Receiver.java

│   │               ├── Sender.java

│   │               ├── Server.java

│   │               ├── Session.java

│   │               ├── TLSConnectionInformation.java

│   │               └── Worker.java

│   └── test

│       └── java

│           └── io

│               └── AppTest.java

└── target

├── classes

│   └── io

│       ├── App.class

│       ├── test1

│       │   ├── Boss.class

│       │   ├── Operation.class

│       │   ├── Sender.class

│       │   ├── Server$1.class

│       │   ├── Server.class

│       │   ├── ServerHandler.class

│       │   ├── Session.class

│       │   └── Worker.class

│       └── test2

│           ├── Boss.class

│           ├── Operation.class

│           ├── Receiver.class

│           ├── Sender.class

│           ├── Server$1.class

│           ├── Server.class

│           ├── Session.class

│           ├── TLSConnectionInformation.class

│           └── Worker.class

├── generated-sources

│   └── annotations

├── generated-test-sources

│   └── test-annotations

├── maven-archiver

│   └── pom.properties

├── maven-status

│   └── maven-compiler-plugin

│       ├── compile

│       │   └── default-compile

│       │       ├── createdFiles.lst

│       │       └── inputFiles.lst

│       └── testCompile

│           └── default-testCompile

│               ├── createdFiles.lst

│               └── inputFiles.lst

├── original-testNio-1.0-SNAPSHOT.jar

├── surefire-reports

│   ├── io.AppTest.txt

│   └── TEST-io.AppTest.xml

├── test-classes

│   └── io

│       └── AppTest.class

└── testNio-1.0-SNAPSHOT.jar

Я использую последний сгенерированный мной ключ и сертификат; key2.pem, certificateServer.pem, keystoreServer.jks. Не обращайте внимания на другие ресурсы.
Любая помощь приветствуется.
Спасибо, что уделили время.

Подробнее здесь: https://stackoverflow.com/questions/793 ... pplication
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»