繁体   English   中英

在握手之前解密从 tls 上的 websocket 客户端收到的字节

[英]Decrypt bytes received from a websocket client on tls before the handshake

我开发了一个与 websockets 兼容的 sockets 服务器来通信用 java 和 web 制作的应用程序。 但是最新的 Chrome 和 Mozilla 更新不再允许与 websockets 的不安全连接。 然后我被迫在继续握手和协议的其余部分之前解密我的服务器收到的字节https://www.rfc-editor.org/rfc/rfc6455

我取得了以下成绩:

  1. 从 CA 签署的证书中获取公钥。 还有我服务器的私钥

  2. 使用 Java 的 Cipher 类,我设法使用这些密钥来加密和解密测试字符串

但是我仍然不能做的是在继续握手之前解密我从 websocket 客户端收到的字节。

我希望你能帮助我。 谢谢

我收到的错误:数据不得超过 256 字节

解决了! 解密委托给 SSLSocket 类。 如果有人想在这里做这些步骤。

将CA颁发的证书和私钥导出到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);
    }

} 

}`

别的,websocket 的连接应该是这样的 wss://your_domain:port 不能在 websocket url 中输入 IP 地址,必须使用 CA 颁发的证书中注册的域来完成

使用解密的字节,我可以继续使用 RFC6455 协议。 这只是我做的测试,显然是针对sockets的应用,另外需要异步处理连接到服务器的客户端。 我用 ExecutorService 类来做这件事,但那是另一个话题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM