【发布时间】:2020-01-27 01:49:45
【问题描述】:
我有一个使用双向 TLS 进行加密和身份验证的 gRPC 服务器。因此,连接到此服务器的每个客户端都提供了 SSL 证书,我想拒绝来自 公钥大小小于 2048 位的客户端的连接。似乎还没有直接的方法可以做到这一点。
我可以通过这种方式使用ServerInterceptor 做到这一点
public class SSLInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
try {
SSLSession sslSession = call.getAttributes().get(Grpc.TRANSPORT_ATTR_SSL_SESSION);
RSAPublicKeyImpl pk = (RSAPublicKeyImpl) sslSession.getPeerCertificates()[0].getPublicKey();
if (pk.getModulus().bitLength() < 2048) {
// reject call
}
// proceed with the call
} catch (SSLPeerUnverifiedException e) {
// do something
}
...
}
}
这是一种不好的做法,因为
- 在连接已经完成后进行验证 成立。
- 只有在发出请求/调用时才会触发验证。
- 每次调用都涉及额外的验证开销。
- 在验证失败的情况下,只有调用被拒绝,而不是与客户端的连接。
理想情况下
- 验证在连接建立阶段完成。 (或在客户端和服务器之间创建通道期间的某个时间点)
- 验证失败将阻止创建连接,并且无法设置它并在以后断开连接。
- 每个会话只验证客户端一次,并且在该会话期间进行的所有调用都不会产生任何开销。
我怎样才能做得更好?
【问题讨论】:
-
谁生成客户端证书?如果是您,您可以在证书颁发时知道公钥大小,因此根据您的限制,不要颁发没有使用足够长的密钥的证书。
-
@PatrickMevzek 我想到了这个。是的,我生成了客户端证书,您所说的可以做到。但是,我想知道在我不生成客户端证书但我只是信任生成客户端证书的 CA 的情况下如何做到这一点
-
同意,这是一个有趣的问题。但是由于我对 grpc-java 一无所知,所以我只是想找到另一个解决方案,如果它可以提供帮助的话。让我们等待答案。
-
你能通过设置支持的密码列表来做到这一点吗? java.com/en/configure_crypto.html
-
@EdRandall 是的,我可以更改 jdk 中的
java.security文件以包含此行jdk.certpath.disabledAlgorithms=RSA keySize < 2048并且它按预期工作,但这会在环境级别而不是在应用程序级别改变事情
标签: validation ssl grpc public-key grpc-java