【问题标题】:Can Android 4.4 support cipher with SHA256?Android 4.4 可以支持 SHA256 密码吗?
【发布时间】:2017-08-27 18:22:12
【问题描述】:

我正在使用运行 Android 4.4(API 级别 19)的设备。但我需要开发一个连接到仅支持 TLSv1.2 和 SHA256 密码的服务器的应用程序。我尝试使用旧的 apache 库和更新的 apache 4.4.1.2 (cz.msebera.android) 创建 SSL 上下文。创建上下文并获得支持的密码后,它们都不包含 SHA256。该程序在其他 Android 5.0+ 设备上运行良好。

我的问题是,我可以通过什么方式在 Android 4.4 设备上支持 TLSv1.2 和密码 SHA256?

谢谢。

【问题讨论】:

    标签: android ssl encryption sha256


    【解决方案1】:

    ...运行 Android 4.4(API 级别 19)

    根据documentation of SSLSocket,任何使用 SHA-256 作为 HMAC 的密码都只能从 API 级别 20 开始使用。

    【讨论】:

      【解决方案2】:

      最后,我通过创建自己的 SSL 工厂解决了这个问题:

      package com.bbpos.www.payment_gp.webservice; 
      
      public class NoSSLv3SocketFactory extends SSLSocketFactory {
      private final SSLSocketFactory delegate;
      
      public NoSSLv3SocketFactory() {
          this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
      }
      
      public NoSSLv3SocketFactory(SSLSocketFactory delegate) {
          this.delegate = delegate;
      }
      
      @Override
      public String[] getDefaultCipherSuites() {
          return delegate.getDefaultCipherSuites();
      }
      
      @Override
      public String[] getSupportedCipherSuites() {
          return delegate.getSupportedCipherSuites();
      }
      
      private Socket makeSocketSafe(Socket socket) {
          if (socket instanceof SSLSocket) {
              String[] protocols = {
                      "TLSv1.1",
                      "TLSv1.2"
              };
              ((SSLSocket) socket).setEnabledProtocols(protocols);
          }
          return socket;
      }
      
      @Override
      public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
          return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));
      }
      
      @Override
      public Socket createSocket(String host, int port) throws IOException {
          return makeSocketSafe(delegate.createSocket(host, port));
      }
      
      @Override
      public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
          return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));
      }
      
      @Override
      public Socket createSocket(InetAddress host, int port) throws IOException {
          return makeSocketSafe(delegate.createSocket(host, port));
      }
      
      @Override
      public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
          return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));
      }
      
      }
      

      然后在程序开始时初始化工厂:

      TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
      
              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                  return new java.security.cert.X509Certificate[0];
              }
      
              public void checkClientTrusted(java.security.cert.X509Certificate[] certs,
                                             String authType) {
              }
      
              public void checkServerTrusted(java.security.cert.X509Certificate[] certs,
                                             String authType) {
              }
          }};
          try {
              SSLContext sc;
              sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sc.getSocketFactory());
              HttpsURLConnection
                      .setDefaultSSLSocketFactory(NoSSLv3Factory);
              HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                  @Override
                  public boolean verify(String hostname, SSLSession session) {
                      return true;
                  }
              });
      
          } catch (Exception e)
          {
      
          }
      

      【讨论】:

      • 这如何解决您的问题?您所做的只是启用 TLS 1.1 和 1.2,但您将 get*CipherSuites() 委托给默认 SSL 套接字工厂,它仍将仅返回 SHA1 密码,这是您最初的问题
      • 我也不明白这是如何解决问题的。所需的密码仍然不可用。
      猜你喜欢
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 2017-09-28
      • 1970-01-01
      • 2016-07-24
      相关资源
      最近更新 更多