2017-02-24 16 views
0

ローカル証明機関を使用しようとしていて、「ECDHサーバー鍵交換メッセージに無効な署名があります」というエラーが発生し続けます。 この問題の複雑さについて事前にお詫び申し上げます。 あなたは経由githubのからの完全なソースを取得することができます。ECDHサーバー鍵交換メッセージの署名が無効です

git clone git://github.com/ClarkHobbie/ssltest.git 

そして

mvn package 

でそれをコンパイルし

java -cp target\ssl-test-1.0-SNAPSHOT.jar;lib\netty-all-4.1.6.Final.jar SSLTest server 

とし、別のウィンドウを使用してそれを実行

java -cp target\ssl-test-1.0-SNAPSHOT.jar;lib\netty-all-4.1.6.Final.jar SSLTest client 

プログラムを実行しようとすると、プロンプト(「localhost:6789>」のような)に行き、「test」のようなものを試してみます。

私がnetty all(2番目のコードブロックを参照)を使用しないと、うまくいくようです。ここで

は、完全なスタックトレースです:

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLKeyException: Invalid signature on ECDH server key exchange message 
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:442) 
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248) 
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373) 
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359) 
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:351) 
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334) 
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373) 
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359) 
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926) 
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:129) 
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:651) 
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:574) 
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:488) 
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:450) 
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873) 
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.net.ssl.SSLKeyException: Invalid signature on ECDH server key exchange message 
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1434) 
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535) 
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813) 
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781) 
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) 
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1097) 
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:968) 
    at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:902) 
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411) 
    ... 16 more 
Caused by: javax.net.ssl.SSLKeyException: Invalid signature on ECDH server key exchange message 
    at sun.security.ssl.HandshakeMessage$ECDH_ServerKeyExchange.<init>(HandshakeMessage.java:1119) 
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:284) 
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) 
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:919) 
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:916) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1369) 
    at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1123) 
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1008) 
    ... 18 more 
ここ

がネッティーバージョンが(それが例外をスロー)である:

import io.netty.bootstrap.Bootstrap; 
import io.netty.bootstrap.ServerBootstrap; 
import io.netty.buffer.ByteBuf; 
import io.netty.buffer.ByteBufUtil; 
import io.netty.buffer.Unpooled; 
import io.netty.channel.ChannelHandlerContext; 
import io.netty.channel.ChannelInboundHandlerAdapter; 
import io.netty.channel.ChannelInitializer; 
import io.netty.channel.nio.NioEventLoopGroup; 
import io.netty.channel.socket.ServerSocketChannel; 
import io.netty.channel.socket.SocketChannel; 
import io.netty.channel.socket.nio.NioServerSocketChannel; 
import io.netty.channel.socket.nio.NioSocketChannel; 
import io.netty.handler.ssl.SslContext; 
import io.netty.handler.ssl.SslContextBuilder; 
import io.netty.handler.ssl.SslHandler; 

import javax.net.ssl.TrustManagerFactory; 
import java.io.*; 
import java.security.GeneralSecurityException; 
import java.security.KeyStore; 
import java.security.PrivateKey; 
import java.security.cert.Certificate; 
import java.security.cert.X509Certificate; 

/** 
* Created by Clark on 2/27/2017. 
*/ 
public class SSLTest { 
    public static class ServerChannelInitializer extends ChannelInitializer<NioSocketChannel> { 
     private SslContext sslContext; 

     public ServerChannelInitializer (SslContext sslContext) { 
      this.sslContext = sslContext; 
     } 

     public void initChannel (NioSocketChannel serverSocketChannel) { 
      if (null != sslContext) { 
       SslHandler sslHandler = sslContext.newHandler(serverSocketChannel.alloc()); 
       serverSocketChannel.pipeline().addLast(sslHandler); 
      } 

      EchoHandler echoHandler = new EchoHandler(); 
      serverSocketChannel.pipeline().addLast(echoHandler); 
     } 
    } 

    public static class UserInput { 
     private static UserInput ourInstance; 

     private String prompt; 
     private BufferedReader bufferedReader; 

     public static synchronized void initializeClass (String prompt) { 
      if (null == ourInstance) { 
       ourInstance = new UserInput (prompt); 
      } 
     } 

     public static UserInput getInstance() { 
      return ourInstance; 
     } 

     private UserInput (String prompt) { 
      this.prompt = prompt; 

      InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
      this.bufferedReader = new BufferedReader(inputStreamReader); 
     } 

     public String getLine() throws IOException { 
      System.out.print (prompt); 
      return bufferedReader.readLine(); 
     } 
    } 

    public static class ClientInitializer extends ChannelInitializer<SocketChannel> { 
     private SslContext sslContext; 

     public ClientInitializer (SslContext sslContext) { 
      this.sslContext = sslContext; 
     } 

     public void initChannel (SocketChannel socketChannel) { 
      if (null != sslContext) { 
       SslHandler sslHandler = sslContext.newHandler(socketChannel.alloc()); 
       socketChannel.pipeline().addLast(sslHandler); 
      } 

      ClientChannelHandler clientChannelHandler = new ClientChannelHandler(); 
      socketChannel.pipeline().addLast(clientChannelHandler); 
     } 
    } 

    public static class ClientChannelHandler extends ChannelInboundHandlerAdapter { 
     @Override 
     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
      String input = UserInput.getInstance().getLine(); 

      ByteBuf byteBuf = Unpooled.directBuffer(256); 
      ByteBufUtil.writeUtf8(byteBuf, input); 
      ctx.writeAndFlush(byteBuf); 
     } 

     @Override 
     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
      ByteBuf byteBuf = (ByteBuf) msg; 
      byte[] buffer = new byte[byteBuf.readableBytes()]; 
      byteBuf.getBytes(0, buffer); 
      String s = new String(buffer); 

      System.out.println (s); 

      s = UserInput.getInstance().getLine(); 
      if (s.equalsIgnoreCase("quit") || s.equalsIgnoreCase("bye")) { 
       System.out.println ("quiting"); 
       System.exit(0); 
      } 

      byteBuf = Unpooled.directBuffer(256); 
      ByteBufUtil.writeUtf8(byteBuf, s); 
      ctx.writeAndFlush(byteBuf); 
     } 

     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
      cause.printStackTrace(); 
      ctx.close(); 
     } 
    } 

    public static class EchoHandler extends ChannelInboundHandlerAdapter { 
     @Override 
     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
      ByteBuf byteBuf = (ByteBuf) msg; 
      byte[] buffer = new byte[byteBuf.readableBytes()]; 
      byteBuf.getBytes(0, buffer); 
      String s = new String(buffer); 

      System.out.println("got " + s); 

      ctx.writeAndFlush(msg); 
     } 
    } 

    public static class CommandLine { 
     private String[] argv; 
     private int argIndex = 0; 
     private String mode = "server"; 
     private boolean useTls = true; 
     private String host = "localhost"; 
     private int port = 6789; 

     public String[] getArgv() { 
      return argv; 
     } 

     public String getArg() { 
      if (argIndex >= argv.length) 
       return null; 

      return argv[argIndex]; 
     } 

     public void advance() { 
      argIndex++; 
     } 

     public String getMode() { 
      return mode; 
     } 

     public void setMode (String mode) { 
      this.mode = mode; 
     } 

     public boolean useTls() { 
      return useTls; 
     } 

     public void setUseTls (boolean useTls) { 
      this.useTls = useTls; 
     } 

     public String getHost() { 
      return host; 
     } 

     public void setHost (String host) { 
      this.host = host; 
     } 

     public int getPort() { 
      return port; 
     } 

     public void setPort (int port) { 
      this.port = port; 
     } 

     public CommandLine (String[] argv) { 
      this.argv = argv; 
      parse(); 
     } 

     public void parse() { 
      if (argv.length < 1) 
       return; 

      if (null != getArg() && getArg().equalsIgnoreCase("nossl")) { 
       System.out.println ("Plaintext mode"); 
       setUseTls(false); 
       advance(); 
      } 

      if (null != getArg()) { 
       setMode(getArg()); 
       advance(); 
      } 

      if (null != getArg()) { 
       setHost(getArg()); 
       advance(); 
      } 

      if (null != getArg()) { 
       int temp = Integer.parseInt(getArg()); 
       setPort(temp); 
       advance(); 
      } 
     } 
    } 

    private CommandLine commandLine; 

    public CommandLine getCommandLine() { 
     return commandLine; 
    } 

    public SSLTest (CommandLine commandLine) { 
     this.commandLine = commandLine; 
    } 

    public static void closeIgnoreExceptions (Reader reader) 
    { 
     if (null != reader) { 
      try { 
       reader.close(); 
      } catch (IOException e) {} 
     } 
    } 

    public static void closeIgnoreExceptions (InputStream inputStream) { 
     if (null != inputStream) { 
      try { 
       inputStream.close(); 
      } catch (IOException e) {} 
     } 
    } 

    public static void closeIfNonNull (PrintWriter printWriter) { 
     if (null != printWriter) { 
      printWriter.close(); 
     } 
    } 

    public static KeyStore getKeyStore (String filename, String password) { 
     KeyStore keyStore = null; 
     FileInputStream fileInputStream = null; 

     try { 
      fileInputStream = new FileInputStream(filename); 
      keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
      keyStore.load (fileInputStream, password.toCharArray()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } finally { 
      closeIgnoreExceptions(fileInputStream); 
     } 

     return keyStore; 
    } 

    public static PrivateKey getPrivateKey (String filename, String password, String alias) { 
     PrivateKey privateKey = null; 
     FileInputStream fileInputStream = null; 

     try { 
      KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
      fileInputStream = new FileInputStream(filename); 
      keyStore.load(fileInputStream, password.toCharArray()); 
      privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 

     return privateKey; 
    } 


    public void server() { 
     try { 
      SslContext sslContext = null; 

      if (getCommandLine().useTls()) { 
       String trustStoreFilename = "truststore"; 
       String trustStorePassword = "whatever"; 
       String trustStoreAlias = "ca"; 

       String keyStoreFilename = "serverkeystore"; 
       String keyStorePassword = "whatever"; 
       String keyStoreAlias = "server"; 

       X509Certificate certificate = getCertificate(trustStoreFilename, trustStorePassword, trustStoreAlias); 
       PrivateKey privateKey = getPrivateKey(keyStoreFilename, keyStorePassword, keyStoreAlias); 
       sslContext = SslContextBuilder 
         .forServer(privateKey, certificate) 
         .build(); 
      } 

      ServerChannelInitializer serverChannelInitializer = new ServerChannelInitializer(sslContext); 

      NioEventLoopGroup workerGroup = new NioEventLoopGroup(); 
      NioEventLoopGroup bossGroup = new NioEventLoopGroup(); 

      ServerBootstrap serverBootstrap = new ServerBootstrap(); 
      serverBootstrap.childHandler(serverChannelInitializer); 
      serverBootstrap.group(bossGroup, workerGroup); 
      serverBootstrap.channel(NioServerSocketChannel.class); 

      System.out.println ("listening on port " + getCommandLine().getPort()); 

      serverBootstrap.bind(getCommandLine().getPort()).sync(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 

    public static X509Certificate getCertificate (String filename, String password, String alias) { 
     KeyStore keyStore = null; 
     FileInputStream fileInputStream = null; 
     Certificate certificate = null; 

     try { 
      fileInputStream = new FileInputStream(filename); 
      keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
      keyStore.load(fileInputStream, password.toCharArray()); 
      certificate = keyStore.getCertificate(alias); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 

     return (X509Certificate) certificate; 
    } 

    public static TrustManagerFactory getTrustManagerFactory (String filename, String password) { 
     TrustManagerFactory trustManagerFactory = null; 

     try { 
      KeyStore keyStore = getKeyStore(filename, password); 
      trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
      trustManagerFactory.init(keyStore); 
     } catch (GeneralSecurityException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 

     return trustManagerFactory; 
    } 

    public void client() { 
     try { 
      String trustStoreFilename = "truststore"; 
      String trustStorePassword = "whatever"; 

      SslContext sslContext = null; 

      if (getCommandLine().useTls()) { 
       TrustManagerFactory trustManagerFactory = getTrustManagerFactory(trustStoreFilename, trustStorePassword); 
       sslContext = SslContextBuilder 
         .forClient() 
         .trustManager(trustManagerFactory) 
         .build(); 
      } 

      NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(); 

      Bootstrap clientBootstrap = new Bootstrap(); 
      clientBootstrap.channel(NioSocketChannel.class); 
      clientBootstrap.group(nioEventLoopGroup); 
      clientBootstrap.handler(new ClientInitializer(sslContext)); 
      clientBootstrap.connect(getCommandLine().getHost(), getCommandLine().getPort()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 

    public static void main (String[] argv) { 
     CommandLine commandLine = new CommandLine(argv); 
     SSLTest sslTest = new SSLTest(commandLine); 

     String prompt = commandLine.getHost() + ":" + commandLine.getPort() + "> "; 
     UserInput.initializeClass(prompt); 

     if (commandLine.getMode().equalsIgnoreCase("server")) 
      sslTest.server(); 
     else if (commandLine.getMode().equalsIgnoreCase("client")) 
      sslTest.client(); 
     else { 
      System.err.println ("unknown mode: " + commandLine.getMode()); 
     } 
    } 
} 

私はあなたのように、スタックオーバーフロー上の文字制限(30,000)ヒット非Nettyバージョンを見るためにGitHubに行く必要があります。私は、Webサービスの前に座っていると、彼らのためにメッセージを記録ツールを開発しています、私は全く暗号化を使用していて、なぜ私は特にローカル認証局を使用しています理由として

https://github.com/ClarkHobbie/ssltest2

。ツールはクラスタ化されているので、どのメッセージ(POST/PUT/DELETE)もインターネットを経由する可能性があります。ノードを識別し、コンテンツを保護するために、暗号化が使用されます。クライアントは、すべてのノード(高価、低速、不便)に対してCERTを取得するか、ローカル認証局を使用することができます。詳細はhttps://ltsllc.blogspot.com/2017/02/the-invalid-signature-problem.htmlを参照してください。

+0

投票を求めるのはここではノーであり、潜在的にはダウンボトムになるので、私はその文を削除しました。また、コードを提供していないので、誰もあなたを助けることができない可能性があります。スタックトレースにはコード内にフレームが含まれていないようですので、何が起きているのかは分かりません。私はあなたが問題を幾分絞り込む必要があると思います。 –

+0

Jimはあなたの指針と提案に感謝します。私は質問にソースファイルを追加しました。また、javax.net.ssl.trustStoreプロパティとjavax.net.ssl.trustStorePasswordプロパティを設定しようとしました。システムはそれらを使用します(存在しないファイルを使用するとFileNotFoundExceptionが発生します)が、無効な署名の例外が表示されます。 –

+0

"netty"プログラムを追加しました。 –

答えて

0

この問題が発生した場合は、コアJavaとMinaで試してみてください。あなたのプロジェクトがそれらのいずれかで動作する場合は、そのうちの1つを使用してください。

私はこれが理想的な解決策ではないと言う最初です。何がいいだろうか "オハイオ州のオプションxyzを使用して、それは動作する"の行に沿って何かされていただろうが、この問題に対して私の頭を叩いて2週間後、スタックオーバーフローで1週間続いて、 Nettyの人々と一緒に、私は何か他のものを使う準備ができています。

私はGitHub(ssltest、ssltest2、およびssltest3)で利用できる3つのテストプログラムを作成し、プログラムがNettyで動作しない間に、コアJavaまたはMinaで動作したことに注意してください。最終的な結果はまだ「これはバグではありません」でした。

この時点で、私のプロジェクトはMinaと連携していると思われます。他人のために:あなたがこの問題に遭遇しなければ、是非Nettyを使用してください。あなたがこの問題にぶつかったら、私は何か他のものでそれを試してみることを提案し、それがうまくいくならそれを使ってみることを勧めます。