0

iOSでSocketRocketまたはUnitt Webソケットライブラリを使用して安全なWebソケットを実行するのと同じ問題があります。私は Java Web ソケット サーバー (Netty) を制御しており、サーバー側の SSL/TLS データを詳細に観察できます。ソケットにはポート 6970 を使用します。

クライアント wss ソケットが TLS ハンドシェイクで適切に開かれた後、最初のクライアント データ書き込み、つまり Web ソケット ハンドシェイクでサーバー エラーが発生します。クライアントは 202 バイトを書き込み、サーバーは 272 バイトを受信し、メッセージ認証コードはサーバーで失敗します。サーバー トレースにクライアント データが表示されますが、8 バイトのガベージが前に保留されています。

まず、SocketRocket ライブラリを試してみましたが、サーバー上で同じ結果になりました。良好なハンドシェイクの後に不良 MAC が発生しました。私の Android バージョンの Unitt クライアントはうまく機能します。私の JavaScript セキュア Web ソケット コードもうまく機能します。

iOS/XCode では、Unitt/AsyncSocket/doSendBytes の CFWriteStreamWrite(...) までデバッグできます。これは、202 クライアント データ バイトが実際に書き込まれることを報告します。しかし、さらにデバッグする方法については途方に暮れています。どこかで、送信中に iOS TLS フレームワークがクラ​​イアント データを破損していると思います。

4

1 に答える 1

0

iOSと互換性のない特定のエリピカルカーブ暗号スイートを除外することで、JavaNettyサーバーでiOSの安全なWebソケットを実行することができました。これが私のコードです...

/** the enabled SSL cipher suites */
private static String[] enabledCipherSuites;
/** the enabled SSL cipher suites lock */
private static final Object ENABLED_CIPHER_SUITES_LOCK = new Object();
/** the iOS incompatible cipher suites */
private static final List<String> iOSIncompatibleCipherSuites = new ArrayList<>();

/** Configures the SSL engine for client or for the server. Arranges the enabled ciphers to favor the
* most secure over the less secure, and omits the least secure ciphers.  Requires that the SSL server
* authenticate the client.
*
* @param sslEngine the SSL engine
* @param useClientMode the indicator whether the SSL engine is operating in client mode
* @param needClientAuth the indicator whether the server authenticates the client's SSL certificate
*/
public static synchronized void configureSSLEngine(
         final SSLEngine sslEngine,
         final boolean useClientMode,
         final boolean needClientAuth) {
  //Preconditions
  assert sslEngine != null : "sslEngine must not be null";

  if (useClientMode) {
    LOGGER.info("configuring SSL engine for the client side of the connection");
    sslEngine.setUseClientMode(true);
    sslEngine.setNeedClientAuth(false);
  } else {
    if (needClientAuth) {
      LOGGER.info("configuring SSL engine for the server side of the connection with required client authorization");
    } else {
      LOGGER.info("configuring SSL engine for the server side of the connection without required client authorization");
    }
    sslEngine.setUseClientMode(false);
    sslEngine.setNeedClientAuth(needClientAuth);
 }
  synchronized (ENABLED_CIPHER_SUITES_LOCK) {
    if (enabledCipherSuites == null) {
      iOSIncompatibleCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
      iOSIncompatibleCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256");
      iOSIncompatibleCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
      iOSIncompatibleCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");

      // TLS_ECDHE_RSA_WITH_RC4_128_SHA is the negotiated cipher suite for iOS

      // select and arrange the highest security cipher suites and cache the result
      final String[] supportedCipherSuites = sslEngine.getSupportedCipherSuites();
      final List<String> enabledCipherSuitesList = new ArrayList<>(supportedCipherSuites.length);
      // The first pass selects 256 bit ciphers available with the Java Cryptography Extension (JCE)
      // Unlimited Strength Jurisdiction Policy Files, downloaded and installed from http://java.sun.com/javase/downloads/index.jsp .
      for (final String supportedCipherSuite : supportedCipherSuites) {
        if (supportedCipherSuite.contains("_256_") && !supportedCipherSuite.contains("_anon_")) {
          enabledCipherSuitesList.add(supportedCipherSuite);
        }
      }
      // The second pass selects 128 bit ciphers that use SHA hashing - its more secure than MD5 but slower.
      for (final String supportedCipherSuite : supportedCipherSuites) {
        if (supportedCipherSuite.contains("_128_") && !supportedCipherSuite.endsWith("_MD5") && !supportedCipherSuite.contains("_anon_")) {
          enabledCipherSuitesList.add(supportedCipherSuite);
        }
      }
      // The third pass selects 128 bit ciphers that use MD5 hashing.
      for (final String supportedCipherSuite : supportedCipherSuites) {
        if (supportedCipherSuite.contains("_128_") && supportedCipherSuite.endsWith("_MD5") && !supportedCipherSuite.contains("_anon_")) {
          enabledCipherSuitesList.add(supportedCipherSuite);
       }
      }
      // The fourth pass removes the iOS incompatible cipher suites
      enabledCipherSuitesList.removeAll(iOSIncompatibleCipherSuites);

      if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("enabledCipherSuites: " + enabledCipherSuitesList);
      }
      final int enabledCipherSuitesList_size = enabledCipherSuitesList.size();
      enabledCipherSuites = new String[enabledCipherSuitesList_size];
      for (int i = 0; i < enabledCipherSuitesList_size; i++) {
        enabledCipherSuites[i] = enabledCipherSuitesList.get(i);
      }
    }
    sslEngine.setEnabledCipherSuites(enabledCipherSuites);
  }
}
于 2012-06-30T21:06:39.363 に答える