Расшифровывать байты, полученные от клиента websocket на tls перед рукопожатием - PullRequest
0 голосов
/ 22 июня 2019

Я разработал сервер сокетов, совместимый с веб-сокетами, для связи приложений, созданных на Java и в Интернете.Но последние обновления Chrome и Mozilla больше не разрешают небезопасные соединения с веб-сокетами.Затем я вынужден расшифровать байты, которые получает мой сервер, прежде чем продолжить рукопожатие, а остальная часть протокола https://tools.ietf.org/html/rfc6455

Я достиг следующего:

  1. Получите открытый ключ из сертификата, подписанного центром сертификации.И закрытый ключ моего сервера

  2. С классом Java Cipher мне удалось использовать эти ключи для шифрования и дешифрования тестовой строки

Но я до сих пор не могу расшифровать байты, которые я получаю от клиента websocket, прежде чем продолжить рукопожатие.

Надеюсь, вы мне поможете.Спасибо

Полученная ошибка: данные не должны быть длиннее 256 байт

1 Ответ

0 голосов
/ 24 июня 2019

Решено!Расшифровка была поручена классу SSLSocket.Если кто-то захочет сделать это, выполните следующие действия.

Экспортируйте сертификаты, выданные ЦС, и закрытый ключ в файл p12

openssl pkcs12 -export -in certificate/path/certificate.crt -inkey /path/privatekey/private.key -out filep12.p12 -name your_domain -CAfile /path/ca.crt -caname your_ca

Хранилище ключей Java

keytool -genkey -alias your_alias -keyalg RSA -keystore name_store.jks -keysize 2048

После ввода пароля (your_password) и подтверждения

keytool -importkeystore -srckeystore name_store.jks -destkeystore name_store.jks -deststoretype pkcs12 -srcstorepass your_password

keytool -delete -alias your_alias -keystore name_store.jks -storepass your_password

keytool -importkeystore -deststorepass your_password -destkeypass your_password -destkeystore name_store.jks -srckeystore filep12.p12 -srcstoretype PKCS12 -srcstorepass your_password -alias your_domain

your_alias не должен быть таким же или похожим на your_domain, пароль должен вводиться (your_password) на каждом шаге, который всегдатак же, чтобы при расшифровке не было ошибок заполнения

Класс в java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;


public class SServidor {   


public SServidor(){
    try {
        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        File keystrorefile = new File("/path/name_store.jks");
        System.out.println(keystrorefile.getAbsolutePath());
        InputStream keystoreStream = new FileInputStream(keystrorefile);
        char[] passphrase="your_password".toCharArray();            

        keystore.load(keystoreStream, passphrase);
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keystore, passphrase);
        makeSSLSocketFactory(keystore, keyManagerFactory);

    } catch (KeyStoreException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (CertificateException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (UnrecoverableKeyException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private void log(Object msj){
    System.out.println(msj.toString());
}

public void makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManagerFactory key){

    try {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(loadedKeyStore);
        SSLContext ctx = SSLContext.getInstance("TLS");            
        ctx.init(key.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        SSLServerSocketFactory sslssf = ctx.getServerSocketFactory();
        ServerSocket conexion = sslssf.createServerSocket(your_port);
        SSLSocket cliente=(SSLSocket) conexion.accept();

        cliente.startHandshake();
        InputStream in = cliente.getInputStream();            
        OutputStream out = cliente.getOutputStream();
        int byte_recibido=-1;   

        while(cliente.isConnected() && (byte_recibido=in.read())>-1){
            Integer n=byte_recibido & 0xFF;  
            String s=new String(String.valueOf(Character.toChars(n)));
            log(s);
        }

            out.close();                        
            bin.close();
                    in.close();
            cliente.close();
            conexion.close();


    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (KeyStoreException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (KeyManagementException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(SServidor.class.getName()).log(Level.SEVERE, null, ex);
    }

} 

}`

Что-то еще, соединение с веб-сокетом должно быть примерно таким: wss:// your_domain: port IP-адрес не должен быть введен в URL веб-сокета, это должно быть сделано с доменом, зарегистрированным в сертификате, выданном CA

С расшифрованными байтами я могу продолжить сПротокол RFC6455.Это только тест, который я сделал, очевидно, для приложения сокетов, кроме того, необходимо асинхронно обрабатывать клиентов, которые подключаются к серверу.Я делаю это с помощью класса ExecutorService, но это уже другая тема

...