HSM 与 Apache Tomcat 的 HTTPS 用法

HSM usage with Apache Tomcat for HTTPS

我的 HSM(硬件安全模块)存储(或允许使用)私钥,但是,它不支持 PKCS#11 和类似的方法。反过来,Apache Tomcat 可以通过 JKS、PKCS#11 或以编程方式使用证书和密钥。我的目标是在 Web 服务器上启用 HTTPS 支持,但我看不出如何仅通过更改配置文件来实现。

我设想了一个选项,我可以将证书存储在 JKS 中,并通过 HSM 供应商提供的 API 获取与其关联的私钥。为此,如果我是对的,我将需要重新实现 JSSEImplementation 和相应的工厂。同样,我需要实施特定的密钥和信任管理器。

这是解决此类问题的唯一方法吗?

在 Apache Tomcat 的 运行 独立实例中替换 JSSEImplementation 是否安全,例如,在它启动后立即替换。

最后,我仅根据this示例得出了以下解决方案。我将 <Connector> 实例添加到 Tomcat 配置,sslImplementationName 属性 指向自定义 JSSEImplementation class 名称,并扩展 JSSEImplementation使用自定义 JSSESocketFactoryX509KeyManager classes.

Tomcat 配置如下:

<Connector
       protocol="org.apache.coyote.http11.Http11Protocol"
       port="8443" maxThreads="200"
       scheme="https" secure="true" SSLEnabled="true"
       clientAuth="true" sslProtocol="TLS" SSLEnabled="true"
       sslImplementationName="x.y.z.CustomJSSEImplementation"
       keyAlias="alias_of_key_in_HSM_and_cert_in_JKS"
/>

CustomJSSEImplementation class 是:

public class CustomJSSEImplementation extends JSSEImplementation {
   @Override
   public ServerSocketFactory getServerSocketFactory(AbstractEndpoint endpoint) {
      return new CustomSslContextSocketFactory(endpoint);
   }

   @Override
   public SSLUtil getSSLUtil(AbstractEndpoint endpoint) {
      return new CustomSslContextSocketFactory(endpoint);
   }
}

CustomSslContextSocketFactory class 是:

public class CustomSslContextSocketFactory extends JSSESocketFactory {

    public static final AtomicReference<CustomSslContext> customSslContext =
        new AtomicReference<CustomSslContext>();

    public CustomSslContextSocketFactory(AbstractEndpoint endpoint) {
        super(endpoint);
    }

    @Override
    public KeyManager[] getKeyManagers() throws Exception {
        return (customSslContext.get() == null ? super.getKeyManagers() : customSslContext.get().getKeyManagers(this));
    }
}

CustomSslContext界面为:

interface CustomSslContext {
    KeyManager[] getKeyManagers(JSSESocketFactory factory) throws Exception;
}

HsmKeyManagerImpl 通过 keyAlias 属性 引用 HSM 中的私钥,如下所示:

public class HsmKeyManagerImpl implements X509KeyManager {
    ...

    @Override
    public PrivateKey getPrivateKey(String alias) {
        // HSM Vendor specific API calls
    }
}

我没有显示代码如何获取对应于私有的证书,但是使用 <Connector>keyAlias 属性 定义的相同别名来获取来自 JKS.