Tenho um único rootCA
certificado na resource
pasta (junto com sua chave privada) do meu projeto.
Quando o software inicia, ele inicializa o SSLManager
objeto, que por sua vez:
- Carrega o rootCA em um
x509Certificate
- Carrega a chave privada rootCA
- Gera um par de chaves e certificado do servidor
- Assina o certificado usando o rootCA
Gostaria de armazenar o rootCA e o certificado do servidor em um keystore, que posso usar posteriormente para configurar um SSLContext e para um armazenamento mais seguro.
Eu sei como armazenar um único par de chaves/certificado em um keystore, mas como eu faria isso corretamente para uma cadeia?
Eu presumo:
keyStore.setKeyEntry(ALIAS, privateKey, password.toCharArray, Array(rootCA, serverCert))
Entretanto, se for verdade, qual chave privada devo usar (rootCA vs. servidor)?
Um exemplo completo seria muito apreciado.
Fechar
Use a chave privada do servidor, e o cert-array deve ter o certificado do servidor PRIMEIRO, seguido por seu(s) certificado(s) de cadeia, de preferência em sequência ascendente, mas possivelmente omitindo a raiz.
Isso ocorre porque o JSSE enviará esse cert-array como o cert-chain no handshake SSL/TLS. Os padrões originais exigiam que o cert-chain enviado por um servidor começasse com o cert do servidor, seguido pelos certs da CA da cadeia em sequência ascendente estrita -- "Cada certificado seguinte deve certificar diretamente o que o precede." Na prática, muitos servidores, devido a erros de codificação ou configuração, obtiveram certs após o primeiro fora de ordem e, como eles podem ser classificados, dado que apenas o primeiro está correto, os clientes SSL/TLS foram codificados para tolerar isso; o padrão mais recente, RFC8446 para TLS1.3, agora recomenda suporte para "certificados potencialmente estranhos e ordenações arbitrárias", EXCETO que "o cert[] da entidade final DEVE ser o primeiro".
Além disso, todos os padrões permitiram que o certificado raiz fosse omitido da cadeia transmitida, porque não é necessário; um cliente pode validar com segurança o certificado e a cadeia, e assim a identidade do servidor, usando apenas um certificado raiz (ou possivelmente uma âncora não raiz) já configurada/armazenada localmente para esse cliente (para Java, normalmente em JRE/lib/security/cacerts, para outros softwares de maneiras comparáveis), então fazer o servidor enviar outra cópia é um desperdício de largura de banda -- embora seja bem pequeno. Java
keytool
não gosta de criar um PrivateKeyEntry com uma cadeia que omite a raiz, mas o código que você escreve pode, e o JSSE enviará qualquer um deles com prazer.Para o seu caso simples, isso significa uma matriz de
(servercert, rootcacert)
ou opcionalmente apenas(servercert)