2

我有一些 java 8 应用程序,使用gRPC进行网络通信。为了确保这一点,我使用 TLS 和客户端身份验证。现在,我尝试从软件密钥切换到智能卡,持有用于客户端身份验证的私钥和证书(链)。我在 gRPC 中使用 sun pkcs#11 提供程序制作 netty 的代码如下所示:

static NettyChannelBuilder getChannel(final String host, final int port, 
  final File trustAnchorsFile) throws Exception{
  String configName = "pkcs11.cfg"; // FIXME


  SunPKCS11 sunpkcs11 = new SunPKCS11(configName);
  Security.addProvider(sunpkcs11);
  KeyStore.Builder scBuilder = KeyStore.Builder.newInstance("PKCS11", sunpkcs11,
        new KeyStore.PasswordProtection("11111111".toCharArray())); //FIXME

  KeyManagerFactory factory = KeyManagerFactory.getInstance("NewSunX509");  
  KeyStoreBuilderParameters param = new KeyStoreBuilderParameters(scBuilder);
  factory.init(param);
  SslContextBuilder builder = GrpcSslContexts.forClient(); 

  builder = builder.trustManager(trustAnchorsFile)
                 .keyManager(factory)
                 .clientAuth(ClientAuth.REQUIRE);

  return NettyChannelBuilder.forAddress(host, port).sslContext(builder.build());
}

测试我看到的代码,它对智能卡进行身份验证(提供一些错误的 PIN(而不是“11111111”)会减少卡上相应的重试计数器。此外,使用 pkcs11 dll 的调试版本,由sun pkcs11 提供程序,我看到,sun 提供程序进行身份验证,列出所有密钥,读取所有证书等(经常),但不尝试执行一些私钥操作。此外,提供-Djava.security.debug=sunpkcs11 到 JVM 并没有提供任何进一步的内部信息(我偶然发现在SSL 客户端身份验证中使用智能卡在 Java 6 中工作但在 Java 7 中失败)。

使用wireshark查看它看起来的TLS协议握手,客户端尝试省略客户端身份验证部分,这使得服务器关闭连接。这会导致客户端出现一些异常:

io.grpc.StatusRuntimeException:不可用:在 io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:208) 的 io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:227) 执行协议协商时通道关闭.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:141)

从智能卡提供与 PEM 文件相同的密钥和证书SslContextBuilder确实会导致工作连接,因此我得出结论,证书和密钥本身不会形成问题,但可能/可能是 sunpkcs11 的某些配置?

有人成功使用带有 PKCS#15 智能卡/PKCS#11 令牌的 gRPC 吗?有没有人有进一步的建议,如何轻松理解,这里有什么失败?

4

0 回答 0