我有一些java 8应用程序,使用 gRPC 进行网络通信。为了确保这一点,我使用TLS进行客户端身份验证。现在,我尝试从软件密钥切换到智能卡,持有私钥和证书(链)进行客户端身份验证。我在gRPC内部使用 netty 的代码使用sun pkcs#11提供程序,如下所示:
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 Client Authentication with smart card works in Java 6 but fails in Java 7时偶然发现了accros)。
使用wireshark查看它看起来的TLS协议握手,客户端尝试省略使服务器关闭连接的客户端身份验证部分。这导致客户端出现一些异常:
io.grpc.StatusRuntimeException:UNAVAILABLE:频道关闭时 执行协议谈判 io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:227) 在io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:208)at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:141)
从智能卡提供与SslContextBuilder
的PEM文件完全相同的密钥和证书确实会导致工作连接,因此我得出结论,证书和密钥本身不会形成问题,但也许/可能是sunpkcs11的一些配置?
有没有人成功使用gRPC和PKCS#15智能卡/ PKCS#11令牌? 有没有人有进一步的建议,如何轻松理解,什么在这里失败?