KeyTool gera cadeia de certificados e sua aplicação em java e c#

        A maior parte do conteúdo deste artigo foi aprendida na Internet, portanto, retornarei à Internet após resumir. Se você encontrar um erro, ou tiver uma maneira melhor, fique à vontade para comentar ou me enviar uma mensagem.

        A razão para explorar a cadeia de certificados é porque os certificados autoassinados são usados ​​no desenvolvimento da grade mínima . O Simple Grid é um framework de desenvolvimento para pequenas e microempresas que integra o dispositivo e a nuvem. Se você solicitar um certificado da organização toda vez que implantá-lo, será muito problemático primeiro, e o segundo é o custo. Os serviços do Simple Grid são gratuitos, mas o certificado será cobrado. Para resumir, depois de tatear a cadeia de certificados, o certificado raiz é gerado e, em seguida, o certificado de segundo nível é assinado. O certificado de segundo nível é dividido em certificado do servidor e certificado de assinatura do aplicativo. O certificado do servidor e o certificado de assinatura do aplicativo são os certificados de terceiro nível.

        A propósito, um pequeno anúncio, o código comercial do Zhijian Grid foi gradualmente de código aberto, bem-vindo para visitar o Code Cloud ou CSDN para visualizá-lo e também está disponível no GitHub.

Índice

1. Noções básicas

1.1. SSL

1.2. O que é um certificado

1.3. Tipos de certificados

1.4. Geração de certificado

1.5. Conceitos básicos

1.5.1. X.509

1.5.2. Formato de codificação do certificado (DER&PEM)

1.5.3. Extensões relacionadas a certificados

1.6. Ver certificado

1.6.1. janelas

1.6.2. Android

2. Gere um certificado raiz

2.1. Gerar keystore de certificado raiz

2.2. Exporte o certificado raiz do keystore do certificado raiz

3. Gere um certificado secundário

3.1. Gerar um keystore de certificado secundário

3.2. Gere uma solicitação de certificado a partir do keystore do certificado secundário

3.4. Importe o certificado secundário para o keystore

4. Use o certificado secundário para emitir certificados de usuário

4.1. Gerar keystore de certificado de usuário

4.2. Gerando Solicitações de Certificado de Usuário

4.3. Emissão de certificados de usuário com certificados secundários

4.4. Importar certificados de usuário para o keystore

4.5. Ver cadeia de certificados do usuário

4.6. Converter JKS para BKS

5. Uso

5.1. Usando certificados autoassinados em Java

5.1.1. Usando certificados autoassinados no Netty

5.1.2. Usando certificados autoassinados em OkHttp

5.2. Usando certificados autoassinados em C#

5.3. Usando certificados autoassinados no Android

5.4. Usando certificados autoassinados no IE

5.4.1. janelas

6. Resumo


1.  Noções básicas

1.1. SSL

        Os certificados são geralmente usados ​​no protocolo de transporte SSL (Secure Sockets Layer) para implementar a troca de chaves entre o lado do terminal e o lado do servidor. Deveria ser chamado de "TLS" agora, mas devido ao hábito, costuma ser chamado de "SSL". O uso mais comum de SSL é em sites, onde é usado para implementar a transmissão HTTP segura.

        A transmissão do protocolo HTTP não criptografa o conteúdo, de modo que, quando o conteúdo é transmitido, pode ser monitorado por outras pessoas. Em cenários com altos requisitos de segurança, a transmissão deve ser criptografada, por exemplo, o cenário de transmissão de senhas durante o login.

        HTTPS é o protocolo HTTP com criptografia, e a transmissão criptografada de HTTPS é implementada com base em SSL, de modo que mesmo que um nó na rede de transmissão seja monitorado por outros, os dados não vazarão. SSL implementa criptografia e descriptografia na camada inferior do HTTP, e criptografia e descriptografia são transparentes para usuários e desenvolvedores. Em outras palavras, antes da criptografia, como seu servidor é implementado, após a criptografia, não há necessidade de fazer alterações.

        Outro termo é OpenSSL. Simplificando, o SSL é uma especificação e o OpenSSL é uma implementação do SSL, que fornece várias ferramentas poderosas, tão poderosas que não usamos 90%. Teoricamente falando, é difícil quebrar o SSL no nível técnico atual, mas a implementação do SSL pode ter brechas, como o famoso "Heartbleed".

1.2.  O que é um certificado

        Os certificados são usados ​​em SSL, então o que é um certificado?

        Um certificado pode ser entendido como um documento que contém informações como informações do emissor, informações do proprietário, chave pública, assinatura gerada pela chave privada do emissor e, claro, outras informações. Verificar se o certificado do usuário é confiável é, na verdade, verificar se o certificado é emitido por uma organização legal. Ao verificar, localize o certificado da organização correspondente por meio das informações estruturais no certificado e use a chave pública no certificado da organização para verificar se a assinatura no certificado do usuário está correta.

        A partir dos métodos de verificação acima, podemos ver que se o certificado é confiável é verificado pelo certificado de seu emissor, e se o certificado da organização é confiável é verificado pelo certificado da organização de nível superior, formando assim uma cadeia de certificados. O certificado da organização de nível superior geralmente é chamado de certificado raiz.

        No cenário do site, o site gera um keystore, registra a chave pública do site, a chave privada e algumas outras informações e, em seguida, solicita um certificado da organização. O certificado gerado inclui informações como a chave pública e também inclui uma cadeia de certificados, que é usada para emitir aos usuários do site. Quando um usuário visita um site, ele primeiro baixa o certificado do site, verifica a cadeia de certificados e, em seguida, usa a chave pública para trocar chaves com o site.

1.3.  Tipos de certificados

        Um é um certificado autoassinado e o outro é um certificado emitido por uma agência.

        Um certificado autoassinado significa que o emissor é ele mesmo e usa sua própria chave privada para assinar as informações do certificado. Um certificado raiz é um certificado autoassinado. O cliente geralmente pré-configura os certificados raiz de organizações conhecidas e confia nos certificados emitidos por esses certificados raiz.

        Emitir certificados é emitir certificados por meio dessas organizações, que podem ser organizações de nível raiz ou organizações secundárias, e usar a chave privada da organização para assinar as informações do certificado. Para proteger o certificado raiz, geralmente a organização permite que as organizações secundárias e terciárias emitam certificados.

1.4.  Geração de certificado

        O certificado e o keystore correspondente ao certificado podem ser gerados por meio da keytool fornecida por openssl ou jdk. Este artigo usa keytool como exemplo. Depois de entender o processo de geração de certificados, é fácil corresponder ao método de geração do openssl.

1.5.  Conceitos básicos

        Basta procurar por certificados TLS e haverá muitas palavras-chave: X.509, p12, pfx, pkcs, pem, csr, cer, crt, jks, crl, etc., tão complicadas que as pessoas podem ir rapidamente de começar a desistir. Então, vamos resolver essas palavras-chave primeiro.

1.5.1. X.509

        X.509 é um padrão de certificado digital amplamente utilizado. Simplificando, ele define quais campos estão contidos em um certificado digital e como armazená-los. Você pode consultar RFC5280. PKCS7 e PKCS12 são dois pacotes envolvidos na especificação X509, incluindo conteúdos diferentes. PKCS7 é usado para assinatura ou criptografia, e não há conteúdo de assinatura ou criptografia nele; PKCS12 contém chave privada, chave pública, proteção por senha e é relativamente seguro.

        Os parâmetros definidos no protocolo X509 são todos codificados em DER (Distinguished Encoding Rules, X.690). A codificação DER pode ser entendida como uma codificação de formato TLV (Tag Length Value), tomando como exemplo o conteúdo de um certificado real:

Certificado:

    Dados:

        Versão: 3 (0x2)          //Representado como certificado de versão X509 v3

        Número de série: 1 (0x1)    //Número de série, ao emitir, é necessário garantir que cada certificado do mesmo emissor seja um número de série único

    Algoritmo de assinatura: sha256WithRSAEncryption //Algoritmo de assinatura, primeiro calcule o resumo SHA256 e, em seguida, use a chave privada do emissor para criptografia RSA

        Emissor: C=CN,ST=JS, L=NJ, O=Dreamer, OU=Dreamer, CN=Dreamer //Emissor DN (Nome Distinto), consulte as instruções de acompanhamento

        Validade //Período de validade do certificado

            Não antes: 29 de julho 14:02:13 2018 GMT

            Não depois: 26 de julho 14:02:13 2028 GMT

        Subject: C=CN, ST=JS, O=Dreamer, OU=JM, CN=*.dreamer.com //Proprietário do certificado DN(Nome distinto)

        Subject Public Key Info:  //Certifique as informações da chave pública

            Algoritmo de chave pública: rsaEncryption

                Chave pública: (1024 bits)

                Módulo:

                    00:c5:b8:68:a2:9c:bd:11:0c:83:34:a2:97:a5:8e:

                    72:75:2a:bc:f4:75:fc:d0:a3:47:7d:e4:6b:4f:ed:

                    dd:79:7c:0f:ce:6e:e7:d2:7d:10:cd:e8:07:56:34:

                    58:e3:2b:2e:c9:e3:7f:ae:27:2d:f7:a3:17:6f:dd:

                    65:d7:f8:4f:d0:be:9c:3b:9b:ea:ed:86:d2:19:67:

                    81:60:53:64:c9:d1:be:17:7d:5d:7f:cc:58:1d:b6:

                    e1:51:0d:ba:32:ac:4d:73:a4:fc:8f:6a:79:f9:44:

                    25:03:b6:1c:3e:0f:e9:b8:36:b1:07:07:59:54:40:

                    d7:2c:52:ab:68:fe:ed:e2:6f

                Expoente: 65537 (0x10001)

        Extensões X509v3:  //v3 informações de extensão de versão

            Restrições básicas do X509v3:  

                CA: FALSE   // Indica se o proprietário do certificado é uma organização de CA que pode emitir certificados. Se for True, você também pode adicionar um pathLengthConstraint para exibir o comprimento da cadeia de emissão

            Comentário do Netscape:

                Certificado OpenSSL gerado

            X509v3 Subject Key Identifier: //Certificate owner key ID, esta extensão precisa ser adicionada quando CA: TRUE

                67:30:EE:FB:39:A4:92:56:9C:1A:E8:94:10:A4:3B:EA:EC:2E:04:9E

            X509v3 Authority Key Identifier: //O ID da chave correspondente ao emissor do certificado, usado para encontrar a chave pública do emissor (especialmente quando há várias chaves)

                DirName:/C=CN/ST=JS/L=NJ/O=Sonhador/OU=Sonhador/CN=Sonhador

                serial:A0:09:E3:A9:D2:C1:86:7C

            X509v3 Subject Alternative Name:  //O alias do proprietário do certificado, usado para a emissão de certificados multidomínio

                DNS:*.exemplo.com, DNS:*.jm.com

    Algoritmo de assinatura: sha256WithRSAEncryption //Informações de assinatura do certificado emitido pela autoridade emissora

         91:db:9b:0c:9b:6e:68:24:d3:2f:3a:67:b5:c0:6c:f0:c8:4c:

         f8:87:86:93:eb:fc:dc:ef:dc:7b:2e:2c:0e:7b:52:23:4d:de:

         d9:69:a8:ee:ae:aa:14:04:ca:1a:03:87:fe:11:60:fe:16:8f:

         87:9d:9e:d0:3a:be:33:03:f6:25:8a:10:37:f8:90:9d:67:5c:

         36:a6:1e:3c:59:d9:8f:eb:22:0e:f7:3c:7d:47:10:9b:0b:03:

         f0:8c:70:b0:3c:40:c6:5d:cc:6b:ba:40:ce:89:04:c7:3c:be:

         af:bd:1d:94:6b:83:39:29:74:de:12:fc:63:0d:0f:39:31:3b:

         48:fd

Além das instruções nos comentários, os seguintes pontos precisam ser adicionados:

  • Tanto o Assunto quanto o Emissor estão no formato DN, e os formatos comuns são: C=país, ST=província, L=distrito, O=organização, OU=unidade organizacional, CN=nome comum;
  • DN é a chave para a busca da cadeia de certificados. Durante a verificação, o certificado da organização será correspondido de acordo com o DN do Emissor. O método de correspondência específico é comparar o número de DNs e o valor de cada parâmetro DN;
  • O nome comum de CN em DN é geralmente um nome de domínio.Se você precisar oferecer suporte a nomes de subdomínio, como server.com e bcd.server.com, poderá usar o formulário de nome de domínio genérico *.server.com;
  • O campo de extensão Subject Alternative Name pode ser usado para certificados de vários domínios.

1.5.2.  Formato de codificação do certificado (DER&PEM)

        De acordo com a declaração geral na Internet, o X.509 tem dois formatos de armazenamento: DER e PEM (Privacy Enhanced Mail).Na verdade, essa afirmação é um tanto inadequada.Na verdade, esses dois formatos de codificação não estão no mesmo nível. Como mencionado acima, o DER é um protocolo de codificação binária no formato TLV. X.509 afirma que a codificação de cada campo do certificado pode ser codificada no formato DER. No entanto, o PEM não entende os parâmetros internos do X.509. Em vez disso, após o X.509 ser codificado por DER, ele executa a codificação BASE64 nos dados binários e, em seguida, adiciona o cabeçalho e o final do arquivo, conforme mostrado abaixo:

-----BEGIN CERTIFICATE-----
MIICMTCCAZoCCQCgCeOp0sGGfDANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJD
TjELMAkGA1UECAwCSlMxCzAJBgNVBAcMAk5KMRAwDgYDVQQKDAdEcmVhbWVyMRAw
DgYDVQQLDAdEcmVhbWVyMRAwDgYDVQQDDAdEcmVhbWVyMB4XDTE4MDcyODE1NTEx
NFoXDTI4MDcyNTE1NTExNFowXTELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkpTMQsw
CQYDVQQHDAJOSjEQMA4GA1UECgwHRHJlYW1lcjEQMA4GA1UECwwHRHJlYW1lcjEQ
MA4GA1UEAwwHRHJlYW1lcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwjDr
aM8SubYIN/dqmJLCHYWBet7yQ80H3VPcbeYPja2Fq1VPb0vKMXzfd8BdaJ3roown
ZCJlfxCFPqN/z8/a0BS+ukmknOcYeYoN+vpVg9Oq3fH0iy+TRg+ydOVwmyAXJk0D
GS7WFjHv6DYRlH/xgKXuHGXwytNpQHZdDzq6bV0CAwEAATANBgkqhkiG9w0BAQsF
AAOBgQCaoAdYiWpGKcvc89ZPwL/Zd0KgSLnAln/38a69N5LqtDgWD9a6PDjHHmTF
/cN/p8hJ3LdEXfPGtFj06+KaG6OVOAo5RSqOHc5DcMs1nAImqIAuLt2rOCmsY+li
T9tweI2raih6OMTKAeIW5m46T28oPlNgeEMy2Uj2CevS6tCaLQ==
-----END CERTIFICATE-----

        O método para distinguir entre DER e PEM é muito simples: abra aquele com caracteres distorcidos no formato DER e abra aquele semelhante ao formato acima no formato PEM. De um modo geral, a extensão do arquivo que armazena o DER é ".cer", que é um dado binário, enquanto a extensão do arquivo que armazena o PEM é ".crt", que é um arquivo de texto ASCII.

        Os arquivos DER/PEM podem ser visualizados com o seguinte comando:

openssl x509 -in certificate.der -inform der -text -noout
openssl x509 -in certificate.pem -text -noout

1.5.3.  Extensões relacionadas a certificados

        A extensão tem maior probabilidade de enganar as pessoas. Além do sufixo .der ou .pem, existem os seguintes sufixos comuns:

crt

Deve ser a abreviação de certificado, que é comum em sistemas * nix, principalmente codificação PEM, e também pode ser codificação DER

cer

Solicitação de assinatura de certificado, comum em sistemas Windows, principalmente codificação DER, também pode ser codificação PEM

chave

A informação-chave armazenada pelo usuário pode ser codificada em DER ou codificada em PEM. Você pode consultar PKCS#1 (RFC8017) para visualizar seus campos e definições específicos; no entanto, o método de armazenamento de texto simples da chave é perigoso. Geralmente, o formato PKCS#8 (RFC5958) é usado para armazenamento criptografado, ou seja, uma chave de extração é definida

RSC

A solicitação de emissão de certificado é realmente semelhante ao conteúdo do certificado, mas não contém as informações do emissor. O emissor gera um arquivo de certificado com base no csr e adiciona suas próprias informações de emissão. Para obter detalhes, consulte (PKCS#10 RFC2314)

pfx/p12

Empacote o certificado e a chave privada em um arquivo e defina "extrair senha";

[Nota] PKCS12 não suporta a configuração da senha de entrada do keystore, que é a mesma senha do keystore por padrão

jks

armazenamento de chaves

armazenamento confiável

jks (Java Key Storage) é comumente usado em aplicativos relacionados a JAVA. Na verdade, é semelhante ao PKCS12. Ele empacota o certificado e a chave privada juntos e define a "senha de extração". Quanto a keystore e truststore, é apenas uma diferença conceitual. Keystore geralmente representa um certificado de usuário ou servidor, enquanto truststore geralmente representa um certificado de CA.

        Se você quiser estudar em profundidade, você pode dar uma olhada na família de protocolos PKCS.A chave mencionada acima, csr, pfx/p12, etc., são todas extensões definidas na família de protocolos.

1.6.  Ver certificado

1.6.1. janelas

        No menu Iniciar, digite certlm.msc para gerenciar certificados para o computador local ou certmgr.msc para gerenciar certificados para o usuário atual.

1.6.2. Android

        Tome Honor como exemplo, outros tipos de telefones celulares operam de forma semelhante. Procure por "Certificado" nas configurações, você pode encontrar "Instalar certificado" e "Credenciais confiáveis". Em Credenciais confiáveis, você pode ver os certificados de "sistema" e "usuário atual", e os certificados correspondentes podem ser ativados ou desativados nas duas listas.

        Você pode instalar seus próprios certificados em Instalar certificados. Esta operação é difícil e não é recomendável permitir que os usuários façam isso sozinhos.

2.  Gere um certificado raiz

2.1.  Gerar keystore de certificado raiz

        O certificado raiz é um certificado autoassinado e o usuário e o emissor são eles mesmos. Use o seguinte comando para gerar o keystore do certificado raiz (se o caminho do arquivo keystore não for especificado, ele será armazenado em .keystore no diretório do usuário por padrão), insira a senha do keystore e preencha as informações do certificado raiz.

keytool -genkeypair -validity 36500 -keyalg EC -keypass xxxxxx -storepass xxxxxx -dname "CN=njhx,C=CN,OU=njhx" -alias rootca -keystore root.jks

        Este comando usa o algoritmo secp256r1 da curva elíptica para gerar um par de chaves EC de 256 bits e salvá-lo em njhx_root.jks. Use o seguinte comando para visualizar as informações do keystore e você descobrirá que tanto o publicador quanto o proprietário são njhx:

keytool -list -keystore root.jks -keypass xxxxxx -storepass xxxxxx -v

2.2.  Exporte o certificado raiz do keystore do certificado raiz

Use a função de exportação de keytool para exportar o certificado raiz do keystore, digite a senha do keystore e o arquivo de certificado exportado é rootca.cer. O comando é o seguinte:

keytool -exportcert -validity 36500 -alias rootca -file root.cer -keystore root.jks -keypass xxxxxx -storepass xxxxxx

Neste momento, tanto o emissor quanto o usuário são njhx

3.  Gere um certificado secundário

3.1.  Gerar um keystore de certificado secundário

O certificado secundário precisa ser assinado pelo certificado raiz.

  • Primeiro use o keytool para gerar o keystore do certificado secundário, mas ainda é autoassinado neste momento, precisamos gerar uma solicitação de certificado secundário (que contém a chave pública do certificado secundário);
  • Em seguida, envie a solicitação de certificado para o rootca emitir o certificado secundário;
  • Por fim, importamos o certificado secundário emitido pelo rootca para o keystore do certificado para concluir a geração do certificado secundário.

        O seguinte comando é para gerar um keystore de certificado secundário. O nome do keystore é subca. No momento, ele ainda é autoassinado e o emissor do certificado e o usuário são eles mesmos:

keytool -genkeypair -validity 36500 -keyalg EC -keypass yyyyyy -storepass yyyyyy -dname "CN=njhx.com,C=CN,OU=njhx" -alias subca -keystore sub.jks

3.2.  Gere uma solicitação de certificado a partir do keystore do certificado secundário

        Exporte a solicitação de certificado do keystore CA secundário, o seguinte é o comando para exportar a solicitação de certificado, subca é o nome do keystore CA secundário gerado acima e, finalmente, exporte o arquivo de solicitação de certificado como subca.csr:

keytool -certreq -alias subca -file sub.csr -keystore sub.jks -keypass yyyyyy -storepass yyyyyy

3.3.  Use o certificado raiz para emitir um certificado

Usando a função de emissão de certificado da ferramenta keytool, use o rootca para emitir um certificado secundário para a solicitação de certificado secundário (subca.csr). O comando é o seguinte, alias especifica o emissor do certificado, infile especifica o arquivo de solicitação de certificado e outfile é o nome do arquivo do certificado secundário:

keytool -gencert -validity 36500 -alias rootca -infile sub.csr -outfile sub.cer -keystore root.jks -keypass xxxxxx -storepass xxxxxx

        Você pode ver que o emissor do certificado já é njhx e o usuário é njhx.com

3.4.  Importe o certificado secundário para o keystore

        Como o armazenamento de chaves gerado localmente ainda é autoassinado, você precisa importar o certificado secundário emitido pelo certificado raiz para o armazenamento de chaves neste momento. Antes de importar, você deve primeiro importar o certificado raiz autoassinado para o armazenamento de chaves. Isso é muito importante, caso contrário, ele informará "Falha ao criar uma cadeia a partir da resposta", o comando é o seguinte:

keytool -importcert -alias rootca -file root.cer -keystore sub.jks -storepass yyyyyy -keypass yyyyyy

        Em seguida, sub.cer pode ser importado para o keystore. alias subca é o alias do par de chaves usado para gerar o keystore ou a solicitação de certificado:

keytool -importcert -alias subca -file sub.cer -keystore sub.jks -storepass yyyyyy -keypass yyyyyy

        Neste ponto, verifique se o emissor do certificado do par de chaves subca no keystore é njhx em rootca.

keytool -list -alias subca -v -keystore sub.jks -storepass yyyyyy 

4.  Use o certificado secundário para emitir certificados de usuário

        O processo de emissão de uma CA de usuário é igual ao de geração de uma CA secundária. Em seguida, geramos o CA do usuário usuário, alteramos o rootca na operação de geração do certificado secundário para o subca do certificado secundário e alteramos o alias para usuário.

4.1.  Gerar keystore de certificado de usuário

        Primeiro gere o keystore do userca, o comando é o seguinte:

keytool -genkeypair -alias userca -keyalg EC -validity 36500 -keystore user.jks -keypass zzzzzz -storepass zzzzzz -dname "CN=*.mesh.njhx.com,C=CN,OU=njhx"

4.2.  Gerar solicitação de certificado de usuário

keytool -certreq -alias userca -file user.csr -keystore user.jks -keypass zzzzzz -storepass zzzzzz

4.3.  Emissão de certificados de usuário com certificados secundários

keytool -gencert -alias subca -infile user.csr -outfile user.cer -keystore sub.jks -keypass yyyyyy -storepass yyyyyy

4.4.  Importe o certificado do usuário para o keystore

        Ao importar o certificado do usuário, você também precisa importar o rootca , caso contrário, quando o cliente o usar, a verificação falhará.

keytool -importcert -alias userca -file user.cer -keystore user.jks -storepass zzzzzz
keytool -importcert -alias rootca -file root.cer -keystore user.jks -storepass zzzzzz

        Ao visualizar o keystore, ele mostra que o comprimento da cadeia de certificados é 3.

4.5.  Ver cadeia de certificados do usuário

        Você precisa primeiro instalar o certificado raiz e o certificado secundário no armazenamento confiável de certificados do computador local e clicar duas vezes em user.cer para ver se o certificado já é confiável e você pode ver o relacionamento da cadeia de certificados.

4.6.  Converter JKS para BKS

        Como o JKS não é suportado no Android (o BouncyCastle é usado na camada inferior do Android), é necessário converter o arquivo jks para BKS. Antes de converter, você precisa baixar o pacote jar do BouncyCastle, como baixar "bcprov-jdk18on-1.71.1.jar", especificar o provedor e o caminho do pacote jar no keytool e usar o seguinte comando para converter:

keytool -importkeystore -alias userca -srckeystore user.jks -destkeystore user.bks -srcstoretype JKS -deststoretype BKS -srcstorepass zzzzzz -srckeypass zzzzzz -deststorepass zzzzzz -destkeypass zzzzzz -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath path_to_bcprov-jdk18on-1.71.1.jar

        Use o seguinte comando para visualizar o certificado user.bks e confirme se o comprimento da cadeia de certificados é 3:

keytool -list -v -keystore user.bks -storepass zzzzzz -keypass zzzzzz -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath path_to_bcprov-jdk18on-1.71.1.jar

5.  usar

5.1.  Usando certificados autoassinados em Java

5.1.1.  Usando certificados autoassinados no Netty

        A primeira é criar o SSLContext com o keystore do usuário:

private SSLContext createSslContext() {
    try (InputStream inputStream = new FileInputStream(“path to user.jks”)) {
        ks = KeyStore.getInstance(“JKS”);
        //加载keytool生成的密钥库,其中包括证书链
        ks.load(inputStream, “zzzzzz”.toCharArray());
    } catch(Exception e) {
        LOG.warn("Fail to load keystore,can't support https", e);
        return null;
    }

    SSLContext sslContext = null;
    try {
        sslContext = SSLContext.getInstance("TLS");
        KeyManagerFactory kmf =         KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(this.serverKeyStore.keystore, this.serverKeyStore.keypass);
        sslContext.init(kmf.getKeyManagers(), null, null);
    } catch(Exception e) {
        LOG.error("Fail to create ssl context", e);
    }

    return sslContext;
}

Então, quando netty for inicializado, adicione SslHandler na primeira posição

SSLContext sslContext = createSslContext();
if(sslContext != null) {
    SSLEngine sslEngine = sslContext .createSSLEngine();
    sslEngine.setUseClientMode(false);
    pl.addLast("ssl", new SslHandler(sslEngine));
}

        Atenção especial deve ser dada, se BouncyCastle for utilizado no projeto, ao adicionar o Provider, ele precisa ser adicionado ao final, caso contrário ele irá avisar que a senha está errada, embora a senha esteja certa.

Security.insertProviderAt(new BouncyCastleProvider(), Security.getProviders().length + 1);

5.1.2.  Usando certificados autoassinados em OkHttp

        Se você não deseja confiar no certificado raiz, pode importar user.cer para KeyStore; ao mesmo tempo, pode confiar no nome de domínio definido em user.cer em hostnameVerifier.

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
try(InputStream certificate = new FileInputStream("path to user.cer")) {
    keyStore.setCertificateEntry("userca", certificateFactory.generateCertificate(certificate));
}
//使用包含自签证书信息的keyStore构建一个X509TrustManager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
    KeyManagerFactory.getDefaultAlgorithm()
);

keyManagerFactory.init(keyStore, null);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm()
);

trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
    throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}

        Crie um trustmanager e confie apenas no keystore autocriado

SSLContext sslContext = SSLContext.getInstance("TLS");
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
OkHttpClient.Builder builder = new OkHttpClient.Builder()
    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager)trustManagers[0])
    .hostnameVerifier((hostname, session) -> {
        try {
            Certificate[] certs = session.getPeerCertificates();
            if(certs != null && certs.length > 0) {
                X509Certificate cert = (X509Certificate)certs[0];
                String peer = cert.getSubjectX500Principal().getName();
                if(peer.contains(".mesh.njhx.com")) {
                    return true;
                }

                LOG.error("Fail to verify cert host name {}", peer);
            }
        } catch (SSLPeerUnverifiedException e) {
            LOG.error("Fail to get cert host name", e);
        }

        return false;
    });

        A implementação recomendada é confiar no certificado raiz root.cer. Nesse caso, você mesmo precisa implementar o X509TrustManager:

private static class RootTruster implements X509TrustManager {
    private final X509Certificate certificate;

    public RootTruster(X509Certificate certificate) {
        this.certificate = certificate;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // 双向认证才会用到
    }

    // 校验服务端证书是否合法
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        if (chain == null || chain.length == 0) {
            throw new IllegalArgumentException("checkServerTrusted:x509Certificate array isnull");
        }
        X509Certificate c = chain[chain.length - 1]; //最后一个就是根证书
        if(c.equals(rootCer)) {
            return; //信任链的根证书就是预置的根证书,则不必抛出异常
        }
        throw new CertificateException("Root not supported,chain.length=" + chain.length);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[] {certificate};
    }
}

        Em seguida, coloque RootTruster na lista TrustManager

// 加载根证书
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(“stream ofroot.cer”);
TrustManager[] trustManagers;
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init((KeyStore) null);

trustManagers = new TrustManager[tmf.getTrustManagers().length + 1];
// 创建一个trustmanager,只信任自建的keystore
trustManagers[0] = new RootTruster(certificate);
int i = 1;
for (TrustManager trustManager : tmf.getTrustManagers()) {
    trustManagers[i++] = trustManager;
}

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, SecureUtil.getRandom());
builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0]);

5.2.  Usando certificados autoassinados em C#

        Como o cliente Windows no projeto é implementado usando C#, é necessário confiar no certificado raiz autoconstruído em C#. Ao sobrecarregar ServerCertificateValidationCallback, pode-se julgar que o certificado raiz é root, cer.

//受.net版本限制,此处最高只支持TLS1.2版本
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
WebRequestHandler handler = new WebRequestHandler();
X509Certificate2 rootCert = new X509Certificate2(“path to root.cer”); //本地根证书对象
handler.ServerCertificateValidationCallback += (sender, cert, chain, error) => {
    if (error == SslPolicyErrors.None) {
        return true;
    }

    if (!cert.Subject.Contains(CERT_DOMAIN)) {
        return false;
    }

    //最后一个证书是根证书
    X509Certificate2 lastCert = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
    //与本地根证书比较
    if (rootCert.Equals(lastCert)) {
        return true;
    }

    return false;
};

5.3.  Usando certificados autoassinados no Android

        No Android, seja como servidor ou cliente, a implementação é a mesma do Java. A única diferença é que quando o servidor carrega server.jks, ele precisa ser convertido em server.bks.

5.4.  Usando certificados autoassinados no IE

5.4.1. janelas

        Clique duas vezes no certificado raiz, selecione o certificado de instalação no pop-up e selecione "Autoridades de certificação raiz confiáveis" na página de armazenamento. Depois que a importação for bem-sucedida, sub.cer será exibido normalmente, caso contrário, haverá um ponto de exclamação.

        No final, o teste não foi bem-sucedido, porque nenhum navegador foi usado desta vez e nenhuma outra tentativa foi feita. A abertura no navegador Edge é sempre rejeitada devido a problemas de segurança.

6.  Resumo

        Todo o processo de exploração durou cerca de uma semana, depois de fazer novamente, tive uma compreensão mais abrangente do certificado. Projetos típicos não usarão o conteúdo descrito neste artigo.

        Ao explorar o conteúdo deste artigo, você precisa ter uma compreensão básica dos algoritmos RSA e EC e ter uma compreensão clara do conhecimento relacionado a TLS/SSL, especialmente o processo de troca de chaves. Caso contrário, você ficará sobrecarregado ao se deparar com tantas opções.

Acho que você gosta

Origin blog.csdn.net/flyinmind/article/details/126861506
Recomendado
Clasificación