【问题标题】:Rejecting mutual TLS gRPC connection based on RSA public key size拒绝基于 RSA 公钥大小的双向 TLS gRPC 连接
【发布时间】: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
        }
        ...
    }
}

这是一种不好的做法,因为

  1. 在连接已经完成后进行验证 成立。
  2. 只有在发出请求/调用时才会触发验证。
  3. 每次调用都涉及额外的验证开销。
  4. 在验证失败的情况下,只有调用被拒绝,而不是与客户端的连接。

理想情况下

  1. 验证在连接建立阶段完成。 (或在客户端和服务器之间创建通道期间的某个时间点)
  2. 验证失败将阻止创建连接,并且无法设置它并在以后断开连接。
  3. 每个会话只验证客户端一次,并且在该会话期间进行的所有调用都不会产生任何开销。

我怎样才能做得更好?

【问题讨论】:

  • 谁生成客户端证书?如果是您,您可以在证书颁发时知道公钥大小,因此根据您的限制,不要颁发没有使用足够长的密钥的证书。
  • @PatrickMevzek 我想到了这个。是的,我生成了客户端证书,您所说的可以做到。但是,我想知道在我不生成客户端证书但我只是信任生成客户端证书的 CA 的情况下如何做到这一点
  • 同意,这是一个有趣的问题。但是由于我对 grpc-java 一无所知,所以我只是想找到另一个解决方案,如果它可以提供帮助的话。让我们等待答案。
  • 你能通过设置支持的密码列表来做到这一点吗? java.com/en/configure_crypto.html
  • @EdRandall 是的,我可以更改 jdk 中的 java.security 文件以包含此行 jdk.certpath.disabledAlgorithms=RSA keySize &lt; 2048 并且它按预期工作,但这会在环境级别而不是在应用程序级别改变事情

标签: validation ssl grpc public-key grpc-java


【解决方案1】:

您可以通过向 Netty 的 SslContextBuilder 提供自己的 javax.net.ssl.TrustManagerFactory 来自定义证书检查。您可能希望实现 X509ExtendedTrustManager,进行检查,然后委托给“真实”实现以进行其余的证书链检查。

你可以这样做来获取默认配置TrustManagerFactory

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
// loop through tmf.getTrustManagers() checking for one implementing X509TrustManager

【讨论】:

  • 这看起来比我的方法简单多了!
【解决方案2】:

如果 gRPC 允许您访问 SSLEngine,以下可能会有所帮助:

我使用 SSLEngineSimpleDemo(它是 Oracle jssesamples.zip 的一部分)制作了一个模型来设置自定义 AlgorithmConstraints,它会在其中创建 SSLEngine:

private void createSSLEngines() throws Exception {
    ...
    serverEngine = sslc.createSSLEngine();
    ...
    // Set custom AlgorithmConstraints on the SSL engine
    SSLParameters sslParams = sslc.getSupportedSSLParameters();
    sslParams.setAlgorithmConstraints( new MyAlgorithmConstraints() );
    serverEngine.setSSLParameters(sslParams);

MyAlgorithmConstraints 类看起来像:

import java.security.AlgorithmConstraints;
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
import java.security.Key;
import java.security.interfaces.RSAKey;
import java.util.Set;

public class MyAlgorithmConstraints implements AlgorithmConstraints {


    @Override
    public boolean permits(Set<CryptoPrimitive> primitives, String algorithm, AlgorithmParameters parameters) {
        return true;
    }

    @Override
    public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
        boolean permitted = permittedRSAKey(primitives, key);
        return permitted;
    }

    @Override
    public boolean permits(Set<CryptoPrimitive> primitives, String algorithm, Key key, AlgorithmParameters parameters) {
        boolean permitted = permittedRSAKey(primitives, key);
        return permitted;
    }

    private boolean permittedRSAKey(Set<CryptoPrimitive> primitives, Key key) {
        boolean permitted = true;
        if (primitives.contains(CryptoPrimitive.KEY_AGREEMENT) && key instanceof RSAKey) {
            int length = ((RSAKey)key).getModulus().bitLength();
            if (length < 2040) {
                permitted = false;
                System.out.println("+*+*+* MyConstraints: short RSA key not allowed ["+length+"]");
            }
        }
        return permitted;
    }

}

根据How to get the size of a RSA key in Java 中的警告,在密钥前导零的情况下选择长度 2040,但您也可以将条件反转为 length &gt; 1024 permitted=true

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 2014-04-08
    • 2014-06-17
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    相关资源
    最近更新 更多