TLS 1.2+;Java 1.6+;弹跳船舱

TLS 1.2+;Java 1.6+;弹跳船舱,java,ssl,bouncycastle,tls1.2,Java,Ssl,Bouncycastle,Tls1.2,为了支持通过Java 1.6 API到使用TLS 1.2的远程主机的HTTPS连接,我们基于Bouncy Castle库(1.53版)开发了一个定制的TLS SocketConnection工厂 它非常容易使用,只是: String httpsURL = xxxxxxxxxx URL myurl = new URL(httpsURL); HttpsURLConnection con = (HttpsURLConnection )my

为了支持通过Java 1.6 API到使用TLS 1.2的远程主机的HTTPS连接,我们基于Bouncy Castle库(1.53版)开发了一个定制的TLS SocketConnection工厂

它非常容易使用,只是:

        String httpsURL =  xxxxxxxxxx
        URL myurl = new URL(httpsURL);      
        HttpsURLConnection  con = (HttpsURLConnection )myurl.openConnection();
        con.setSSLSocketFactory(new TSLSocketConnectionFactory());   
        InputStream ins = con.getInputStream();
在测试期间,我将不同的web和远程主机连接到

90%的情况下,这一切都很好!但在某些情况下,我们会遇到一个恼人的错误:“内部TLS错误,这可能是一次攻击”。已检查无攻击。这是基于内部BouncyCastle异常处理的常见错误我正在尝试为那些运气不佳的远程主机找到一种常见模式。

更新:

更新一些代码以获取额外信息,我们得到以下结果:

org.bouncycastle.crypto.tls.TlsFatalAlert: illegal_parameter(47)
    at org.bouncycastle.crypto.tls.AbstractTlsClient.checkForUnexpectedServerExtension(AbstractTlsClient.java:56)
    at org.bouncycastle.crypto.tls.AbstractTlsClient.processServerExtensions(AbstractTlsClient.java:207)
    at org.bouncycastle.crypto.tls.TlsClientProtocol.receiveServerHelloMessage(TlsClientProtocol.java:773)
我得到的扩展类型如下:

扩展类型:11 扩展数据:

根据ExtensionType类,“ec点格式”。这会导致“UnexpectedServerExtension”-->“UnexpectedServerExtension”会导致-->TLSFatalert:unliked_参数,最后导致“内部TLS错误,这可能是攻击”

是否建议记录或跟踪此奇怪的TLS错误。。。。????正如我所说,这段代码可以工作90%…但是对于某个远程主机,我得到了这个错误

诀窍在于覆盖StartAndShake以使用Bouncy的TLSClientProtocol:

  • 重写ClientExtensions以包括“主机”扩展类型。只需ExtensionType.server\u名称(可能还有更多要包含的扩展名?)
  • 创建TLS身份验证以在套接字上包含remoteCerts peerCertificate。还可以选择检查远程证书是否在 默认密钥库(cacerts等)
  • 我共享TLSSocketConnectionFactory的代码:

    public class TLSSocketConnectionFactory extends SSLSocketFactory {  
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Adding Custom BouncyCastleProvider
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
        static {
            if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
                Security.addProvider(new BouncyCastleProvider());
            }
        }   
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //SECURE RANDOM
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
        private SecureRandom _secureRandom = new SecureRandom();
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Adding Custom BouncyCastleProvider
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
        @Override
        public Socket createSocket(Socket socket, final String host, int port, boolean arg3)
                throws IOException {
            if (socket == null) {
                socket = new Socket();
            }
            if (!socket.isConnected()) {
                socket.connect(new InetSocketAddress(host, port));
            }
    
            final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), _secureRandom);       
    
            return _createSSLSocket(host, tlsClientProtocol);
    
        }
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // SOCKET FACTORY  METHODS  
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
    
        @Override
        public String[] getDefaultCipherSuites() {
            return null;
        }
    
        @Override
        public String[] getSupportedCipherSuites(){
            return null;
        }
    
        @Override
        public Socket createSocket( String host,
                                    int port) throws IOException,UnknownHostException{
            return null;
        }
    
        @Override
        public Socket createSocket( InetAddress host,
                                    int port) throws IOException {
            return null;
        }
    
        @Override
        public Socket createSocket( String host, 
                                    int port, 
                                    InetAddress localHost,
                                    int localPort) throws IOException, UnknownHostException {
            return null;
        }
    
        @Override
        public Socket createSocket( InetAddress address,
                                    int port,
                                    InetAddress localAddress,
                                    int localPort) throws IOException{
            return null;
        }
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //SOCKET CREATION
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
        private SSLSocket _createSSLSocket(final String host , final TlsClientProtocol tlsClientProtocol) {
            return new SSLSocket() {
                private java.security.cert.Certificate[] peertCerts;
    
                @Override
                public InputStream getInputStream() throws IOException {
                    return tlsClientProtocol.getInputStream();
                }
    
                @Override
                public OutputStream getOutputStream() throws IOException {
                    return tlsClientProtocol.getOutputStream();
                }
    
                @Override
                public synchronized void close() throws IOException {
                    Log.to("util").info("\\\n::::::Close Socket");
                    tlsClientProtocol.close();
                }
    
                @Override
                public void addHandshakeCompletedListener(HandshakeCompletedListener arg0) {
    
                }
    
                @Override
                public boolean getEnableSessionCreation() {
                    return false;
                }
    
                @Override
                public String[] getEnabledCipherSuites() {
                    return null;
                }
    
                @Override
                public String[] getEnabledProtocols() {
                    return null;
                }
    
                @Override
                public boolean getNeedClientAuth(){
                    return false;
                }
    
                @Override
                public SSLSession getSession() {
                    return new SSLSession() {
    
                        @Override
                        public int getApplicationBufferSize() {
                            return 0;
                        }
    
                        @Override
                        public String getCipherSuite() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public long getCreationTime() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public byte[] getId() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public long getLastAccessedTime() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public java.security.cert.Certificate[] getLocalCertificates() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public Principal getLocalPrincipal() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public int getPacketBufferSize() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public X509Certificate[] getPeerCertificateChain()
                                throws SSLPeerUnverifiedException {
                            return null;
                        }
    
                        @Override
                        public java.security.cert.Certificate[] getPeerCertificates()throws SSLPeerUnverifiedException {
                            return peertCerts;
                        }
    
                        @Override
                        public String getPeerHost() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public int getPeerPort() {
                            return 0;
                        }
    
                        @Override
                        public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
                            return null;
                            //throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public String getProtocol() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public SSLSessionContext getSessionContext() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public Object getValue(String arg0) {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public String[] getValueNames() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public void invalidate() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public boolean isValid() {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public void putValue(String arg0, Object arg1) {
                            throw new UnsupportedOperationException();
                        }
    
                        @Override
                        public void removeValue(String arg0) {
                            throw new UnsupportedOperationException();
                        }
    
                    };
                }
    
    
                @Override
                public String[] getSupportedProtocols() {
                    return null;
                }
    
                @Override
                public boolean getUseClientMode() {
                    return false;
                }
    
                @Override
                public boolean getWantClientAuth() {
                    return false;
                }
    
                @Override
                public void removeHandshakeCompletedListener(HandshakeCompletedListener arg0) {
    
                }
    
                @Override
                public void setEnableSessionCreation(boolean arg0) {
    
                }
    
                @Override
                public void setEnabledCipherSuites(String[] arg0) {
    
                }
    
                @Override
                public void setEnabledProtocols(String[] arg0) {
    
                }
    
                @Override
                public void setNeedClientAuth(boolean arg0) {
    
                }
    
                @Override
                public void setUseClientMode(boolean arg0) {
    
                }
    
                @Override
                public void setWantClientAuth(boolean arg0) {
    
                }
    
                @Override
                public String[] getSupportedCipherSuites() {
                    return null;
                }
                @Override
                public void startHandshake() throws IOException {
    
                    Log.to("util").info("TSLSocketConnectionFactory:startHandshake()");
                    tlsClientProtocol.connect(new DefaultTlsClient() {
                        @SuppressWarnings("unchecked")
                        @Override
                        public Hashtable<Integer, byte[]> getClientExtensions() throws IOException {
                            Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions();
                            if (clientExtensions == null) {
                                clientExtensions = new Hashtable<Integer, byte[]>();
                            }
    
                            //Add host_name
                            byte[] host_name = host.getBytes();
    
                            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            final DataOutputStream dos = new DataOutputStream(baos);
                            dos.writeShort(host_name.length + 3);
                            dos.writeByte(0); // 
                            dos.writeShort(host_name.length);
                            dos.write(host_name);
                            dos.close();
                            clientExtensions.put(ExtensionType.server_name, baos.toByteArray());
                            return clientExtensions;
                        }
    
                        @Override
                        public TlsAuthentication getAuthentication()
                                throws IOException {
                            return new TlsAuthentication() {
    
                                @Override
                                public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
    
                                    try {
                                        KeyStore ks = _loadKeyStore();
                                        Log.to("util").info(">>>>>>>> KeyStore : "+ks.size());
    
                                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                                        List<java.security.cert.Certificate> certs = new LinkedList<java.security.cert.Certificate>();
                                        boolean trustedCertificate = false;
                                        for ( org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCertificateList()) {
                                            java.security.cert.Certificate cert = cf.generateCertificate(new ByteArrayInputStream(c.getEncoded()));
                                            certs.add(cert);
    
                                            String alias = ks.getCertificateAlias(cert);
                                            if(alias != null) {
                                                Log.to("util").info(">>> Trusted cert\n" + c.getSubject().toString());
                                                if (cert instanceof java.security.cert.X509Certificate) {
                                                    try {
                                                        ( (java.security.cert.X509Certificate) cert).checkValidity();
                                                        trustedCertificate = true;
                                                        Log.to("util").info("Certificate is active for current date\n"+cert);
                                                    } catch(CertificateExpiredException cee) {
                                                        R01FLog.to("r01f.util").info("Certificate is expired...");
                                                    }
                                                }
                                            } else {
                                            Log.to("util").info(">>> Unknown cert " + c.getSubject().toString());
                                                Log.to("util").fine(""+cert);
                                            }
    
                                        }
                                        if (!trustedCertificate) {
                                            throw new CertificateException("Unknown cert " + serverCertificate);
                                        }
                                        peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
                                    } catch (Exception ex) {
                                        ex.printStackTrace();
                                        throw new IOException(ex);
                                    }
    
                                }
    
                                @Override
                                public TlsCredentials getClientCredentials(CertificateRequest arg0)
                                        throws IOException {
                                    return null;
                                }
    
                                /**
                                 * Private method to load keyStore with system or default properties.
                                 * @return
                                 * @throws Exception
                                 */
                                private KeyStore _loadKeyStore() throws Exception {
                                    FileInputStream trustStoreFis = null;
                                    try {
                                        String sysTrustStore = null;
                                        File trustStoreFile = null;
    
                                        KeyStore localKeyStore = null;
    
                                        sysTrustStore = System.getProperty("javax.net.ssl.trustStore");
                                        String javaHome;
                                        if (!"NONE".equals(sysTrustStore)) {
                                            if (sysTrustStore != null) {
                                                trustStoreFile = new File(sysTrustStore);
                                                trustStoreFis = _getFileInputStream(trustStoreFile);
                                            } else {
                                                javaHome = System.getProperty("java.home");
                                                trustStoreFile = new File(javaHome + File.separator + "lib" + File.separator + "security" + File.separator + "jssecacerts");
    
                                                if ((trustStoreFis = _getFileInputStream(trustStoreFile)) == null) {
                                                    trustStoreFile = new File(javaHome + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts");
                                                    trustStoreFis = _getFileInputStream(trustStoreFile);
                                                }
                                            }
    
                                            if (trustStoreFis != null) {
                                                sysTrustStore = trustStoreFile.getPath();
                                            } else {
                                                sysTrustStore = "No File Available, using empty keystore.";
                                            }
                                        }
    
                                        String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType")!=null?System.getProperty("javax.net.ssl.trustStoreType"):KeyStore.getDefaultType();
                                        String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider")!=null?System.getProperty("javax.net.ssl.trustStoreProvider"):"";
    
                                        if (trustStoreType.length() != 0) {
                                            if (trustStoreProvider.length() == 0) {
                                                localKeyStore = KeyStore.getInstance(trustStoreType);
                                            } else {
                                                localKeyStore = KeyStore.getInstance(trustStoreType, trustStoreProvider);
                                            }
    
                                            char[] keyStorePass = null;
                                            String str5 = System.getProperty("javax.net.ssl.trustStorePassword")!=null?System.getProperty("javax.net.ssl.trustStorePassword"):"";
    
                                            if (str5.length() != 0) {
                                                keyStorePass = str5.toCharArray();
                                            }
    
                                            localKeyStore.load(trustStoreFis, (char[]) keyStorePass);
    
                                            if (keyStorePass != null) {
                                                for (int i = 0; i < keyStorePass.length; i++) {
                                                    keyStorePass[i] = 0;
                                                }
                                            }
                                        }
                                        return (KeyStore)localKeyStore;
                                    } finally {
                                        if (trustStoreFis != null) {
                                            trustStoreFis.close();
                                        }
                                    }
                                }
    
                                private FileInputStream _getFileInputStream(File paramFile) throws Exception {
                                    if (paramFile.exists()) {
                                        return new FileInputStream(paramFile);
                                    }
                                    return null;
                                }
    
                            };
    
                        }
    
                    });
    
                }
    
            };//Socket
    
        }
    
    }
    
    公共类TLSSocketConnectionFactory扩展SSLSocketFactory{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //添加自定义BouncyCastleProvider
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    静止的{
    if(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)==null){
    addProvider(新的BouncyCastleProvider());
    }
    }   
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //安全随机
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    private SecureRandom_SecureRandom=new SecureRandom();
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //添加自定义BouncyCastleProvider
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    @凌驾
    公共套接字createSocket(套接字套接字,最终字符串主机,int端口,布尔arg3)
    抛出IOException{
    if(套接字==null){
    套接字=新套接字();
    }
    如果(!socket.isConnected()){
    connect(新的InetSocketAddress(主机、端口));
    }
    最终TlsClientProtocol TlsClientProtocol=新的TlsClientProtocol(socket.getInputStream(),socket.getOutputStream(),_secureRandom);
    返回_createSSLSocket(主机,tlsClientProtocol);
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //插座工厂方法
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
    @凌驾
    公共字符串[]GetDefaultCipherSuite(){
    返回null;
    }
    @凌驾
    公共字符串[]GetSupportedCipherSuite(){
    返回null;
    }
    @凌驾
    公共套接字createSocket(字符串主机,
    int端口)引发IOException,UnknownHostException{
    返回null;
    }
    @凌驾
    公共套接字createSocket(InetAddress主机,
    int端口)引发IOException{
    返回null;
    }
    @凌驾
    公共套接字createSocket(字符串主机,
    国际港口,
    InetAddress本地主机,
    int localPort)引发IOException,UnknownHostException{
    返回null;
    }
    @凌驾
    公共套接字createSocket(InetAddress地址,
    国际港口,
    InetAddress本地地址,
    int localPort)引发IOException{
    返回null;
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //套接字创建
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    专用SSLSocket\u创建SSLSocket(最终字符串主机,最终TlsClientProtocol TlsClientProtocol){
    返回新的SSLSocket(){
    私有java.security.cert.Certificate[]peertCerts;
    @凌驾
    公共InputStream getInputStream()引发IOException{
    返回tlsClientProtocol.getInputStream();
    }
    @凌驾
    public OutputStream getOutputStream()引发IOException{
    返回tlsClientProtocol.getOutputStream();
    }
    @凌驾
    public synchronized void close()引发IOException{
    Log.to(“util”).info(\\\n:Close Socket);
    tlsClientProtocol.close();
    }
    @凌驾
    public void addHandshakeCompletedListener(HandshakeCompletedListener arg0){
    }
    @凌驾
    公共布尔getEnableSessionCreation(){
    
    protected boolean allowUnexpectedServerExtension(Integer extensionType, byte[] extensionData)
        throws IOException
    {
        switch (extensionType.intValue())
        {
        case ExtensionType.ec_point_formats:
            /*
             * Exception added based on field reports that some servers send Supported
             * Point Format Extension even when not negotiating an ECC cipher suite.
             * If present, we still require that it is a valid ECPointFormatList.
             */
            TlsECCUtils.readSupportedPointFormatsExtension(extensionData);
            return true;
        default:
            return super.allowUnexpectedServerExtension(extensionType, extensionData);
        }
    }