JavaRush /Blogue Java /Random-PT /Arquitetura de criptografia Java: primeira introdução
Viacheslav
Nível 3

Arquitetura de criptografia Java: primeira introdução

Publicado no grupo Random-PT
A segurança da troca de dados é uma das propriedades mais importantes das aplicações modernas. Desde os tempos antigos, as pessoas criaram métodos astutos, que com o desenvolvimento da humanidade se tornaram toda a ciência da criptografia. Naturalmente, Java não ficou de lado e ofereceu aos desenvolvedores a Java Cryptography Architecture (JCA). Esta revisão deve dar uma primeira ideia de como funciona.

Prefácio

Proponho viajar no tempo. Diante de nós está a Roma Antiga. E diante de nós está Caio Júlio César, que envia uma mensagem aos seus comandantes. Vamos ver o que há nesta mensagem:
Arquitetura de criptografia Java: primeira introdução - 2
O que isso poderia significar: "ЕСКЕУГЬГМХИФЯ Е УЛП"? Vamos abrir o Java Online Compiler, por exemplo: repl.it
class Main {
  public static void main(String[] args) {
    String code = "ЕСКЕУГЬГМХИФЯ Е УЛП";
    for (char symbol : code.toCharArray()) {
      if (symbol != ' ') {
        symbol = (char) (symbol - 3);
      }
      System.out.print(symbol);
    }
  }
}
Diante de nós está a implementação mais simples da Cifra de César. De acordo com o trabalho do antigo historiador romano Suetônio, intitulado “As Vidas dos Doze Césares”, foi exatamente assim que César criptografou mensagens para seus generais. E esta é uma das referências mais antigas ao uso de algo como criptografia . A palavra "criptografia" vem das antigas palavras gregas "oculto" e "escrever", ou seja, é a ciência das técnicas de privacidade. Java tem seu próprio suporte para criptografia e é chamado Java Cryptography Architecture (JCA). A descrição pode ser encontrada na documentação oficial da Oracle - " Java Cryptography Architecture (JCA) ". Sugiro que você veja quais oportunidades temos graças à JCA.
Arquitetura de criptografia Java: primeira introdução - 3

JCA

Como aprendemos anteriormente, Java oferece a Java Cryptography Architecture (JCA) para trabalhar com criptografia. Esta arquitetura contém uma API (ou seja, um determinado conjunto de interfaces) e provedores (que as implementam):
Arquitetura de criptografia Java: primeira introdução - 4
Como diz a documentação, “ A plataforma Java inclui vários provedores integrados ”. Ou seja, a plataforma Java fornece um conjunto de provedores integrados que podem ser expandidos se necessário. Você pode ver isso por si mesmo:
import java.security.Provider;
import java.security.Security;
class Main {
  public static void main(String[] args) {
    Provider[] providers = Security.getProviders();
    for (Provider p : providers) {
      System.out.println(p.getName());
    }
  }
}
Registrar um provedor terceirizado é muito fácil. Por exemplo: Security.addProvider(new BouncyCastleProvider()); Este exemplo conecta um dos provedores mais famosos - BouncyCastle . Mas nesta revisão usaremos apenas ferramentas básicas, sem bibliotecas de terceiros. Nosso documento principal: " Java Cryptography Architecture (JCA) ". Compreender como o JCA funciona ajudará você a entender mais facilmente as tecnologias nas quais esse mesmo JCA é usado ativamente. Por exemplo: HTTPS (veja " De HTTP para HTTPS ").
Arquitetura de criptografia Java: primeira introdução - 5

MensagemDigest

A primeira coisa mencionada na documentação JCA é MessageDigest. Em geral, o Digest em russo será o mesmo - um resumo corresponde em significado a “um resumo”. Mas em criptografia, um resumo é uma soma hash. Você também pode lembrar facilmente que em inglês Digest também pode ser traduzido como resumo. Mais detalhes podem ser encontrados na documentação do JCA na seção " MessageDigest ". Como diz a documentação, MessageDigest gera um resultado de tamanho fixo chamado digest ou hash. Hashing é uma função unilateral, ou seja, se fizermos hash de algo, então a partir do resultado (ou seja, do hash) não poderemos obter a fonte original. Mas se objetos idênticos forem hash (por exemplo, strings de caracteres idênticos), então seu hash deverá corresponder. Conforme declarado na documentação, esse hash às vezes também é chamado de “soma de verificação” ou “impressão digital” de dados. O hash pode ser realizado usando diferentes algoritmos. Os algoritmos disponíveis podem ser visualizados no documento " Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8 ". Vamos fazer o hash e imprimir o hash no console:
import javax.xml.bind.DatatypeConverter;
import java.security.*;
public class Main {
  public static void main(String[] args) {
    try {
      MessageDigest digester = MessageDigest.getInstance("SHA-512");
      byte[] input = "Secret string".getBytes();
      byte[] digest = digester.digest(input);
      System.out.println(DatatypeConverter.printHexBinary(digest));
    } catch (NoSuchAlgorithmException e) {
      throw new IllegalStateException(e);
    }
  }
}
O hash pode ser útil, por exemplo, ao armazenar senhas. Já o hash da senha inserida pode ser verificado em relação a um hash salvo anteriormente. Se os hashes corresponderem, a senha também corresponderá. Para um hashing ainda mais seguro, é usado um conceito chamado “salt”. Salt pode ser implementado usando a classe SecureRandom . Antes de executar o método digest, vamos descrever a adição de "sal":
byte[] salt = new byte[16];
SecureRandom.getInstanceStrong().nextBytes(salt);
digester.update(salt);
Mas hash é uma função unilateral. Mas e se você quiser criptografar e descriptografar?
Arquitetura de criptografia Java: primeira introdução - 6

Criptografia de chave simétrica

A criptografia simétrica é a criptografia que usa a mesma chave para criptografar e descriptografar. Para usar criptografia simétrica, precisamos de uma chave. Para obtê-lo, usamos KeyGenerator . Além disso, precisaremos de uma classe que represente uma cifra ( Cipher ). Conforme declarado na documentação do JCA na seção “ Criando um Objeto Cifra ”, para criar uma Cifra é necessário especificar não apenas um algoritmo, mas uma “transformação” na linha. A descrição da transformação é semelhante a esta: "algoritmo/modo/preenchimento":
  • Algoritmo : aqui vemos os nomes padrão para “ Algoritmos de Cifra (Criptografia) ”. Recomenda-se usar AES.
  • Modo : modo de criptografia. Por exemplo: BCE ou CBC (falaremos sobre isso um pouco mais tarde)
  • Recuo/Divisão : Cada bloco de dados é criptografado separadamente. Este parâmetro determina quantos dados são contados como 1 bloco.
Por exemplo, tome a seguinte transformação: "AES/ECB/PKCS5Padding". Ou seja, o algoritmo de criptografia é AES, o modo de criptografia é ECB (abreviação de Electronic Codebook), o tamanho do bloco é PKCS5Padding. PKCS5Padding diz que o tamanho de um bloco é de 2 bytes (16 bits). O modo de criptografia do Electronic Codebook envolve a criptografia sequencial de cada bloco:
Arquitetura de criptografia Java: primeira introdução - 7
Pode ficar assim no código:
import javax.xml.bind.DatatypeConverter;
import javax.crypto.*;
import java.security.Key;
public class Main {
  public static void main(String[] args) throws Exception {
    String text = "secret!!secret!!secret!!secret!!";
    // Generate new key
    KeyGenerator keygen = KeyGenerator.getInstance("AES");
    keygen.init(256);
    Key key = keygen.generateKey();
    // Encrypt with key
    String transformation = "AES/ECB/PKCS5Padding";
    Cipher cipher = Cipher.getInstance(transformation);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] encrypted = cipher.doFinal(text.getBytes());
    System.out.println(DatatypeConverter.printHexBinary(encrypted));
    // Decrypt with key
    cipher.init(Cipher.DECRYPT_MODE, key);
    String result = new String(cipher.doFinal(encrypted));
    System.out.println(result);
  }
}
Se executarmos, esperaremos uma repetição, porque especificamos 32 caracteres. Esses caracteres constituem 2 blocos de 16 bits:
Arquitetura de criptografia Java: primeira introdução - 8
Para evitar a repetição neste caso, você deve usar outro modo - Cipher Block Chaining (CBC). Este modo introduz o conceito de Vetor de Inicialização (representado pela classe IvParameterSpec). E também graças a este modo, o resultado da geração do último bloco será utilizado para gerar o próximo:
Arquitetura de criptografia Java: primeira introdução - 9
Vamos agora escrever isso em código:
import javax.xml.bind.DatatypeConverter;
import javax.crypto.*;
import java.security.*;
import javax.crypto.spec.IvParameterSpec;
public class Main {
  public static void main(String[] args) throws Exception {
    // Initialization Vector
    SecureRandom random = SecureRandom.getInstanceStrong();
    byte[] rnd = new byte[16];
    random.nextBytes(rnd);
    IvParameterSpec ivSpec = new IvParameterSpec(rnd);
    // Prepare key
    KeyGenerator keygen = KeyGenerator.getInstance("AES");
    keygen.init(256);
    Key key = keygen.generateKey();
    // CBC
    String text = "secret!!secret!!secret!!secret!!";
    String transformation = "AES/CBC/PKCS5Padding";
    Cipher cipher = Cipher.getInstance(transformation);
    cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
    byte[] enc = cipher.doFinal(text.getBytes());
    System.out.println(DatatypeConverter.printHexBinary(enc));
    // Decrypt
    cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
    String result = new String(cipher.doFinal(enc));
    System.out.println(result);
  }
}
Como podemos ver, como resultado não vemos blocos de cifras repetidos. Por esta razão, o modo BCE não é recomendado, porque torna possível ver repetições e usar esse conhecimento para descriptografia. Para mais informações sobre BCE e CBC, aconselho a leitura do material: “ Modo livro de código eletrônico ”. Mas a criptografia simétrica tem um problema óbvio - você precisa de alguma forma transferir a chave de quem criptografa para quem criptografa. E nesse caminho essa chave pode ser interceptada e então será possível interceptar dados. E a criptografia assimétrica foi projetada para resolver esse problema.
Arquitetura de criptografia Java: primeira introdução - 10

Criptografia assimétrica

A criptografia assimétrica ou criptografia de chave pública é um método de criptografia que usa um par de chaves: uma chave privada (mantida em segredo de todos) e uma chave pública (disponível ao público). Esta separação é necessária para a troca segura da chave pública entre as partes na troca de informações, mantendo a chave secreta segura. Ao criar um par de chaves, KeyGenerator não é mais suficiente para nós; precisamos de KeyPairGenerator . Vejamos um exemplo:
import javax.crypto.*;
import java.security.*;
public class Main {
  public static void main(String[] args) throws Exception {
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
    generator.initialize(1024);
    KeyPair keyPair = generator.generateKeyPair();
    // Encrypt with PRIVATE KEY
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
    byte[] data = cipher.doFinal("Hello!".getBytes());
    // Decrypt with PUBLIC KEY
    cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
    byte[] result = cipher.doFinal(data);
    System.out.println(new String(result));
  }
}
É importante entender aqui que ao usar criptografia assimétrica, sempre utilizamos KeyPair para usar uma chave para criptografia e outra para descriptografia. Mas porque O objetivo da criptografia é que apenas o destinatário pode descriptografá-la; ela é criptografada com uma chave pública e descriptografada apenas com uma chave privada.
Arquitetura de criptografia Java: primeiro contato - 11

Assinatura digital

Como vimos acima, conhecendo a chave pública, você pode enviar dados para que somente o dono da chave privada possa descriptografá-los. Ou seja, a essência da criptografia assimétrica é que qualquer um criptografa, mas apenas nós lemos. Existe também um procedimento inverso - uma assinatura digital, representada pela classe Signature . Uma assinatura digital pode usar os seguintes algoritmos: “ Algoritmos de Assinatura ”. A documentação do JCA sugere dar uma olhada nesses dois: DSAwithMD5 e RSAwithMD5 O que é melhor que DSA ou RSA e qual a diferença deles você pode ler aqui: "Qual funciona melhor para transferências de arquivos criptografados - RSA ou DSA? ". Ou leia as discussões aqui: " RSA vs. DSA para chaves de autenticação SSH ". Então, assinatura digital. Precisaremos, como antes, de um KeyPair e de uma nova classe Signature. Se você já testou em compiladores online, o exemplo a seguir pode ser um pouco difícil para eles. Meu exemplo só foi executado aqui: rextester.com . Importamos as classes que precisamos:
import javax.crypto.*;
import java.security.*;
Também reescreveremos o método principal:
public static void main(String[] args) throws Exception {
    // Generate keys
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
    SecureRandom random = SecureRandom.getInstanceStrong();
    generator.initialize(2048, random);
    KeyPair keyPair = generator.generateKeyPair();
    // Digital Signature
    Signature dsa = Signature.getInstance("SHA256withRSA");
    dsa.initSign(keyPair.getPrivate());
    // Update and sign the data
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
    byte[] data = cipher.doFinal("Hello!".getBytes());
    dsa.update(data);
    byte[] signature = dsa.sign();
    // Verify signature
    dsa.initVerify(keyPair.getPublic());
    dsa.update(data);
    boolean verifies = dsa.verify(signature);
    System.out.println("Signature is ok: " + verifies);
    // Decrypt if signature is correct
    if (verifies) {
      cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
      byte[] result = cipher.doFinal(data);
      System.out.println(new String(result));
    }
}
É assim que funciona uma assinatura digital. A assinatura digital é um tema interessante. Aconselho você a dar uma olhada no relatório sobre este assunto:
Arquitetura de criptografia Java: primeiro contato - 12
Acima vimos como as partes trocam dados. Não existe alguma interface padrão para esta interação fornecida no JCA? Acontece que existe. Vamos dar uma olhada nisso.
Arquitetura de criptografia Java: primeiro contato - 13

Acordo-chave

A arquitetura de criptografia Java apresenta uma ferramenta importante - o acordo de chave é um protocolo. É representado pela classe KeyAgreement . Conforme declarado na documentação da JCA, este protocolo permite que várias partes definam a mesma chave criptográfica sem compartilhar qualquer informação secreta entre as partes. Soa estranho? Então vejamos um exemplo:
// 1. Одна из сторон (Алиса) генерирует пару ключей. Encoded публичный ключ отдаёт.
KeyPairGenerator generator = KeyPairGenerator.getInstance("DH");
KeyPair aliceKeyPair = generator.generateKeyPair();
byte[] alicePubKeyEncoded = aliceKeyPair.getPublic().getEncoded();

// 2. Другая сторона (например, Боб) получает открытый ключ Алисы
KeyFactory bobKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(alicePubKeyEncoded);
PublicKey alicePubKey = bobKeyFactory.generatePublic(x509KeySpec);
// Параметры, которые использовала Алиса при генерации ключей
DHParameterSpec dhParamFromAlicePubKey = ((DHPublicKey)alicePubKey).getParams();
// Создаёт свою пару ключей. Отдаёт свой Encoded открытый ключ
KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
bobKpairGen.initialize(dhParamFromAlicePubKey);
KeyPair bobKeyPair = bobKpairGen.generateKeyPair();
byte[] bobPubKeyEncoded = bobKeyPair.getPublic().getEncoded();

Теперь, у Алисы есть открытый ключ Боба, а у Боба есть открытый ключ Алисы. What дальше?
Как сказано в documentации JCA, у нас есть инструмент KeyAgreement, https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#KeyAgreement который позволяет установить одинаковые ключи шифрования без необходимости обмениваться секретной информацией (т.е. без обмена private key). Соглашение выглядит следующим образом:
// 3. Соглашение по протоколу Диффи-Хеллмана (Diffie–Hellman, DH)
KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
aliceKeyAgree.init(aliceKeyPair.getPrivate());
// Алиса на основе ключа боба и своего private key создаёт общий shared ключ
KeyFactory aliceKeyFactory = KeyFactory.getInstance("DH");
x509KeySpec = new X509EncodedKeySpec(bobPubKeyEncoded);
PublicKey bobPubKey = aliceKeyFactory.generatePublic(x509KeySpec);
aliceKeyAgree.doPhase(bobPubKey, true);
byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
SecretKeySpec aliceAesKey = new SecretKeySpec(aliceSharedSecret, 0, 16, "AES");
// Боб на основе ключа Алисы и своего private key создаёт общий shared ключ
KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
bobKeyAgree.init(bobKeyPair.getPrivate());
bobKeyAgree.doPhase(alicePubKey, true);
byte[] bobSharedSecret = bobKeyAgree.generateSecret();
SecretKeySpec bobAesKey = new SecretKeySpec(bobSharedSecret, 0, 16, "AES");
// Общий ключ у Алисы и Боба одинаков
System.out.println("Shared keys are equals: " + Arrays.equals(aliceSharedSecret, bobSharedSecret));

Далее Боб и Алиса, используя общий ключ, про который больше никто не знает, обмениваются зашифрованными данными:
// 4. Боб шифрует сообщение для Алисы
Cipher bobCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
bobCipher.init(Cipher.ENCRYPT_MODE, bobAesKey);
byte[] ciphertext = bobCipher.doFinal("Hello, Alice!".getBytes());
// Передаёт Алисе параметры, с которыми выполнялась шифровка
byte[] encodedParamsFromBob = bobCipher.getParameters().getEncoded();

// 5. Алиса принимает сообщение и расшифровывает его
AlgorithmParameters aesParams = AlgorithmParameters.getInstance("AES");
aesParams.init(encodedParamsFromBob);
Cipher aliceCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aliceCipher.init(Cipher.DECRYPT_MODE, aliceAesKey, aesParams);
byte[] recovered = aliceCipher.doFinal(ciphertext);
System.out.println(new String(recovered));
Este exemplo foi retirado do exemplo de documentação JCA: " Diffie-Hellman Key Exchange entre 2 partes ". Esta é aproximadamente a aparência da criptografia assimétrica na arquitetura de criptografia Java usando o protocolo de acordo de chave. Para mais informações sobre criptografia assimétrica, vídeos recomendados:
Arquitetura de criptografia Java: primeiro contato - 14

Certificados

Pois bem, de sobremesa ainda temos algo não menos importante - os certificados. Normalmente, os certificados são gerados usando o utilitário keytool incluído no jdk. Você pode ler mais detalhes, por exemplo, aqui: " Gerando um certificado SSL autoassinado usando o comando Java keytool ". Você também pode ler os manuais da Oracle. Por exemplo, aqui: " Para usar o keytool para criar um certificado de servidor ". Por exemplo, vamos usar o Tutorialspoint Java Online Compiler :
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.*;
import java.security.cert.*;
import java.security.*;
// Compiler args: -XDignore.symbol.file
public class Main {
  public static void main(String[] args) throws Exception {
    CertAndKeyGen certGen = new CertAndKeyGen("RSA", "SHA256WithRSA", null);
    // generate it with 2048 bits
    certGen.generate(2048);
    PrivateKey privateKey = certGen.getPrivateKey();
    X509Key publicKey = certGen.getPublicKey();
    // prepare the validity of the certificate
    long validSecs = (long) 365 * 24 * 60 * 60; // valid for one year
    // enter your details according to your application
    X500Name principal = new X500Name("CN=My Application,O=My Organisation,L=My City,C=DE");
    // add the certificate information, currently only valid for one year.
    X509Certificate cert = certGen.getSelfCertificate(principal, validSecs);
    // Public Key from Cert equals Public Key from generator
    PublicKey publicKeyFromCert = cert.getPublicKey();
    System.out.println(publicKeyFromCert.equals(publicKey));
  }
}
Como podemos ver, um certificado oferece a capacidade de fornecer uma chave pública. Este método tem uma desvantagem - usamos sun.security, o que é considerado arriscado, porque... este pacote não faz parte da API Java pública. É por isso que durante a compilação é necessário especificar o parâmetro - XDignore.symbol.file. Existe outra maneira - criar um certificado manualmente. A desvantagem é que ele usa uma API interna que não está documentada. No entanto, é útil saber sobre isso. No mínimo, porque é claramente visível como a especificação RFC-2459 é utilizada: “ Internet X.509 Public Key Infrastructure ”. Aqui está um exemplo:
// 1. Генерируем пару ключей
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(4096);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 2. Определяем данные сертификата
// Определяем срок действия сертификата
Date from = new Date();
Date to = new Date(from.getTime() + 365 * 1000L * 24L * 60L * 60L);
CertificateValidity interval = new CertificateValidity(from, to);
// Определяем subject name, т.е. Name того, с чем ассоциирован публичный ключ
// CN = Common Name. Через точку с запятой могут быть указаны также другие атрибуты
// См. https://docs.oracle.com/cd/E24191_01/common/tutorials/authz_cert_attributes.html
X500Name owner = new X500Name("cn=Unknown");
// Уникальный в пределах CA, т.е. Certificate Authority (тот, кто выдаёт сертификат) номер
BigInteger number = new BigInteger(64, new SecureRandom());
CertificateSerialNumber serialNumber = new CertificateSerialNumber(number);
// Определяем алгоритм подписи сертификата
AlgorithmId algorithmId = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
CertificateAlgorithmId certificateAlgorithmId = new CertificateAlgorithmId(algorithmId);
// 3. По подготовленной информации создаём сертификат
X509CertInfo info = new X509CertInfo();
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER, serialNumber);
info.set(X509CertInfo.SUBJECT, owner);
info.set(X509CertInfo.ISSUER, owner);
info.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic()));
info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
info.set(X509CertInfo.ALGORITHM_ID, certificateAlgorithmId);
// 4. Подписываем сертификат
X509CertImpl certificate = new X509CertImpl(info);
certificate.sign(keyPair.getPrivate(), "SHA256withRSA");
// 5. Проверка сертификата
try {
	// В случае ошибки здесь будет брошено исключение. Например: java.security.SignatureException
	certificate.verify(keyPair.getPublic());
} catch (Exception e) {
	throw new IllegalStateException(e);
}
Arquitetura de criptografia Java: primeira introdução - 15

Armazenamento de chaves (KeyStore)

A última coisa sobre a qual gostaria de falar é o armazenamento de chaves e certificados, chamado KeyStore. É claro que a geração constante de certificados e chaves é cara e inútil. Portanto, eles precisam ser armazenados de forma segura. Existe uma ferramenta para isso - KeyStore. O armazenamento de chaves é descrito na documentação JCA no capítulo " KeyManagement ". A API para trabalhar com isso é muito clara. Aqui está um pequeno exemplo:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
String alias = "EntityAlias";
java.security.cert.Certificate[] chain = {certificate};
keyStore.setKeyEntry(alias, keyPair.getPrivate(), "keyPassword".toCharArray(), chain);
// Загрузка содержимого (Private Key + Certificate)
Key key = keyStore.getKey(alias, "keyPassword".toCharArray());
Certificate[] certificateChain = keyStore.getCertificateChain(alias);
// Сохранение KeyStore на диск
File file = File.createTempFile("security_", ".ks");
System.out.println(file.getAbsolutePath());
try (FileOutputStream fos = new FileOutputStream(file)) {
	keyStore.store(fos, "keyStorePassword".toCharArray());
}
Como você pode ver no exemplo, ele é executado primeiro loadpara o KeyStore. Mas no nosso caso, especificamos o primeiro atributo como nulo, ou seja, não há fonte para KeyStore. Isso significa que o KeyStore é criado vazio para salvá-lo ainda mais. O segundo parâmetro também é nulo, porque estamos criando um novo KeyStore. Se estivéssemos carregando o KeyStore de um arquivo, precisaríamos especificar uma senha aqui (semelhante ao método KeyStore chamado store).

Resultado final

Por isso, revisamos com você as ações mais básicas e elementares dentro da estrutura da Arquitetura de Criptografia Java (também conhecida como JCA). Vimos o que é criptografia simétrica e assimétrica e como ela é implementada no JCA. Vimos como os certificados e assinaturas digitais são criados e como são usados. Tudo isso é apenas o básico, por trás do qual existem muitas coisas mais complexas e interessantes. Espero que este material de revisão seja útil e lhe interesse em estudos mais aprofundados nesta área.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION