JDK1.6支持TLS1.2

引入

最近工作的部分是重构一个系统的部分代码,并做一些安全性的升级,其中就牵扯到了 TLS 1.2 。但是在我查到 JDK 1.6 不支持 TLS 1.2 之后,就开始漫长的解决方法寻找之旅。


解决方案

  1. 升级JDK
    升级JDK 1.6 到 121 版本之后就会支持 TLS 1.2 。
    JDK1.6 121版本是需要收费的!!!

  2. 引入外部包
    需要引入的包名为 bcprov-jdk15on 。并且需要根据引入的 jar 包继承实现 SSLSocketFactory 类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    import org.bouncycastle.crypto.tls.*;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;

    import javax.net.ssl.*;
    import javax.security.cert.X509Certificate;
    import java.io.*;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.security.KeyStore;
    import java.security.Principal;
    import java.security.SecureRandom;
    import java.security.Security;
    import java.security.cert.CertificateExpiredException;
    import java.security.cert.CertificateFactory;
    import java.util.Hashtable;
    import java.util.LinkedList;
    import java.util.List;

    public class TLSSocketConnectionFactory extends SSLSocketFactory {

    static {
    if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
    Security.addProvider(new 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(), new SecureRandom());

    return _createSSLSocket(host, tlsClientProtocol);
    }

    @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; }

    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 { 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() { return null; }
    @Override public long getCreationTime() { return 0; }
    @Override public byte[] getId() { return null; }
    @Override public long getLastAccessedTime() { return 0; }
    @Override public java.security.cert.Certificate[] getLocalCertificates() { return null; }
    @Override public Principal getLocalPrincipal() { return null; }
    @Override public int getPacketBufferSize() { return 0; }
    @Override public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { return null; }
    @Override public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { return peertCerts; }
    @Override public String getPeerHost() { return null; }
    @Override public int getPeerPort() { return 0; }
    @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { return null; }
    @Override public String getProtocol() { return null; }
    @Override public SSLSessionContext getSessionContext() { return null; }
    @Override public Object getValue(String arg0) { return null; }
    @Override public String[] getValueNames() { return null; }
    @Override public void invalidate() { return; }
    @Override public boolean isValid() { return true; }
    @Override public void putValue(String arg0, Object arg1) { return; }
    @Override
    public void removeValue(String arg0) {
    return;
    }
    };
    }

    @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 {
    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[]>();
    }

    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();

    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) {
    if (cert instanceof java.security.cert.X509Certificate) {
    try {
    ( (java.security.cert.X509Certificate) cert).checkValidity();
    trustedCertificate = true;
    } catch(CertificateExpiredException cee) {

    }
    }
    } else {

    }
    }
    if (!trustedCertificate) {

    }
    peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
    } catch (Exception ex) {
    ex.printStackTrace();
    throw new IOException(ex);
    }
    }

    @Override
    public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
    return null;
    }

    private KeyStore _loadKeyStore() throws Exception {
    FileInputStream trustStoreFis = null;
    try {
    KeyStore localKeyStore = null;

    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, keyStorePass);

    if (keyStorePass != null) {
    for (int i = 0; i < keyStorePass.length; i++) {
    keyStorePass[i] = 0;
    }
    }
    }
    return localKeyStore;
    } finally {
    if (trustStoreFis != null) {
    trustStoreFis.close();
    }
    }
    }
    };
    }

    });
    }
    };
    }
    }

成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
HttpsURLConnection con = null;
try {
con = (HttpsURLConnection) myurl.openConnection();
con.setSSLSocketFactory(new TLSSocketConnectionFactory());

con.setRequestMethod("POST");
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setInstanceFollowRedirects(true);
con.setRequestProperty("Content-type", "application/json;charset=utf-8");
con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
con.connect();

out = con.getOutputStream();
out.write(signData.getBytes("utf-8"));
out.flush();
out.close();

log.info("ResponseCode: " + con.getResponseCode());
} catch (IOException e1) {
e1.printStackTrace();;
} catch(Exception e){
e.printStackTrace();
} finally {

}

问题

  1. host name wrong

    1
    2
    3
    4
    5
    6
    7
    /*用于解决host name wrong问题,重写主机验证方法,如果请求正常可以去掉*/
    con.setHostnameVerifier(new HostnameVerifier(){
    @Override
    public boolean verify(String hostname, SSLSession session) {
    return true;
    }
    });
  2. Internal TLS error, this could be an attack
    你可以在这里找到对应的解决办法

  3. Could not generate DH keypair

  • 调整https使用的dhparam 指定1024位
  • 修改服务器使用1024位dhparam
    解决来源

个人备注

此博客内容均为作者学习所做笔记,侵删!
若转作其他用途,请注明来源!