JavaRush /Blog Java /Random-ES /Arquitectura de criptografía Java: primera introducción
Viacheslav
Nivel 3

Arquitectura de criptografía Java: primera introducción

Publicado en el grupo Random-ES
La seguridad del intercambio de datos es una de las propiedades más importantes de las aplicaciones modernas. Desde la antigüedad, la gente ha ideado métodos astutos que, con el desarrollo de la humanidad, se han convertido en toda la ciencia de la criptografía. Naturalmente, Java no se quedó al margen y ofreció a los desarrolladores la arquitectura de criptografía Java (JCA). Esta revisión debería dar una primera idea de cómo funciona.

Prefacio

Propongo viajar en el tiempo. Ante nosotros está la Antigua Roma. Y ante nosotros está Cayo Julio César, quien envía un mensaje a sus comandantes. Veamos qué hay en este mensaje:
Arquitectura de criptografía Java: primera introducción - 2
¿ Qué podría significar esto "ЕСКЕУГЬГМХИФЯ Е УЛП"? Abramos el compilador Java Online, por ejemplo: 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);
    }
  }
}
Ante nosotros está la implementación más simple del cifrado César. Según el trabajo del historiador romano Suetonio titulado "La vida de los doce césares", así es exactamente como César cifraba los mensajes a sus generales. Y esta es una de las referencias más antiguas al uso de algo como la criptografía . La palabra "criptografía" proviene de las palabras griegas antiguas "oculto" y "escribir", es decir es la ciencia de las técnicas de privacidad. Java tiene su propio soporte para criptografía y se llama Java Cryptography Architecture (JCA). La descripción se puede encontrar en la documentación oficial de Oracle: " Java Cryptography Architecture (JCA) ". Te sugiero que mires las oportunidades que tenemos gracias a JCA.
Arquitectura de criptografía Java: primera introducción - 3

J.C.A.

Como aprendimos anteriormente, Java ofrece la arquitectura de criptografía Java (JCA) para trabajar con criptografía. Esta arquitectura contiene una API (es decir, un determinado conjunto de interfaces) y proveedores (que las implementan):
Arquitectura de criptografía Java: primera introducción - 4
Como dice la documentación, " La plataforma Java incluye varios proveedores integrados ". Es decir, la plataforma Java proporciona un conjunto de proveedores integrados que se pueden ampliar si es necesario. Puedes ver esto por ti mismo:
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 un proveedor externo es muy fácil. Por ejemplo: Security.addProvider(new BouncyCastleProvider()); este ejemplo conecta uno de los proveedores más famosos: BouncyCastle . Pero en esta revisión usaremos sólo herramientas básicas, sin bibliotecas de terceros. Nuestro documento principal: " Arquitectura de criptografía Java (JCA) ". Comprender cómo funciona JCA le ayudará a comprender más fácilmente las tecnologías en las que se utiliza activamente este mismo JCA. Por ejemplo: HTTPS (ver " De HTTP a HTTPS ").
Arquitectura de criptografía Java: primera introducción - 5

Resumen del mensaje

Lo primero que se menciona en la documentación de JCA es MessageDigest. En general, Digest en ruso será el mismo: un resumen corresponde en significado a "un resumen". Pero en criptografía, un resumen es una suma hash. También puedes recordar fácilmente que en inglés Digest también se puede traducir como digest. Se pueden encontrar más detalles en la documentación de JCA en la sección " MessageDigest ". Como dice la documentación, MessageDigest genera un resultado de tamaño fijo llamado resumen o hash. El hash es una función unidireccional, es decir si aplicamos un hash a algo, entonces a partir del resultado (es decir, del hash) no podemos obtener la fuente original. Pero si se aplica un hash a objetos idénticos (por ejemplo, cadenas de caracteres idénticos), entonces su hash debe coincidir. Como se indica en la documentación, dicho hash a veces también se denomina "suma de comprobación" o "huella digital" de datos. El hashing se puede realizar utilizando diferentes algoritmos. Los algoritmos disponibles se pueden ver en el documento " Documentación de nombres de algoritmos estándar de arquitectura de criptografía Java para JDK 8 ". Hagamos el hash e imprimamos el hash en la consola:
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);
    }
  }
}
El hash puede resultar útil, por ejemplo, al almacenar contraseñas. Dado que el hash de la contraseña ingresada se puede comparar con un hash guardado previamente. Si los hashes coinciden, la contraseña también coincide. Para un hash aún más seguro, se utiliza un concepto llamado "sal". Salt se puede implementar utilizando la clase SecureRandom . Antes de ejecutar el método de resumen, describamos cómo agregar "sal":
byte[] salt = new byte[16];
SecureRandom.getInstanceStrong().nextBytes(salt);
digester.update(salt);
Pero el hash es una función unidireccional. Pero, ¿qué pasa si quieres poder cifrar y descifrar?
Arquitectura de criptografía Java: primera introducción - 6

Criptografía de clave simétrica

El cifrado simétrico es un cifrado que utiliza la misma clave para cifrar y descifrar. Para utilizar el cifrado simétrico necesitamos una clave. Para conseguirlo utilizamos KeyGenerator . Además, necesitaremos una clase que represente un cifrado ( Cipher ). Como se indica en la documentación de JCA en la sección " Creación de un objeto de cifrado ", para crear un cifrado es necesario especificar no solo un algoritmo, sino una "transformación" en la línea. La descripción de la transformación se ve así: "algoritmo/modo/relleno":
  • Algoritmo : aquí nos fijamos en los nombres estándar de los “ algoritmos de cifrado (cifrado) ”. Se recomienda utilizar AES.
  • Modo : modo de cifrado. Por ejemplo: BCE o CBC (hablaremos de esto un poco más adelante)
  • Sangría/División : cada bloque de datos se cifra por separado. Este parámetro determina cuántos datos se cuentan como 1 bloque.
Por ejemplo, tome la siguiente transformación: "AES/ECB/PKCS5Padding". Es decir, el algoritmo de cifrado es AES, el modo de cifrado es ECB (abreviatura de Electronic Codebook), el tamaño del bloque es PKCS5Padding. PKCS5Padding dice que el tamaño de un bloque es de 2 bytes (16 bits). El modo de cifrado del Libro de códigos electrónico implica el cifrado secuencial de cada bloque:
Arquitectura de criptografía Java: primera introducción - 7
Podría verse así en el 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);
  }
}
Si ejecutamos, esperaremos ver una repetición, porque especificamos 32 caracteres. Estos caracteres forman 2 bloques de 16 bits:
Arquitectura de criptografía Java: primera introducción - 8
Para evitar la repetición en este caso, debe utilizar otro modo: Cipher Block Chaining (CBC). Este modo introduce el concepto de vector de inicialización (representado por la clase IvParameterSpec). Y además gracias a este modo, el resultado de generar el último bloque servirá para generar el siguiente:
Arquitectura de criptografía Java: primera introducción - 9
Ahora escribamos esto en 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 vemos, como resultado no vemos bloques de cifrado repetidos. Por esta razón, no se recomienda el modo ECB, porque hace posible ver repeticiones y utilizar este conocimiento para descifrar. Para obtener más información sobre el BCE y el CBC, le aconsejo que lea el material: “ Modo libro de códigos electrónico ”. Pero el cifrado simétrico tiene un problema obvio: de alguna manera es necesario transferir la clave del que cifra al que cifra. Y a lo largo de este camino, esta clave puede ser interceptada y luego será posible interceptar datos. Y el cifrado asimétrico está diseñado para resolver este problema.
Arquitectura de criptografía Java: primera introducción - 10

Cifrado asimétrico

El cifrado asimétrico o criptografía de clave pública es un método de cifrado que utiliza un par de claves: una clave privada (mantenida en secreto para todos) y una clave pública (disponible para el público). Esta separación es necesaria para intercambiar de forma segura la clave pública entre las partes del intercambio de información, manteniendo segura la clave secreta. Al crear un par de claves, KeyGenerator ya no es suficiente para nosotros, necesitamos KeyPairGenerator . Veamos un ejemplo:
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));
  }
}
Es importante comprender aquí que cuando utilizamos cifrado asimétrico, siempre usamos KeyPair para usar una clave para cifrar y otra para descifrar. Pero porque El objetivo del cifrado es que sólo el destinatario puede descifrarlo; se cifra con una clave pública y sólo se descifra con una privada.
Arquitectura de criptografía Java: primer contacto - 11

Firma digital

Como vimos anteriormente, conociendo la clave pública, puedes enviar datos para que solo el propietario de la clave privada pueda descifrarlos. Es decir, la esencia del cifrado asimétrico es que cualquiera cifra, pero sólo nosotros leemos. También existe un procedimiento inverso: una firma digital, representada por la clase Firma . Una firma digital puede utilizar los siguientes algoritmos: " Algoritmos de firma ". La documentación de JCA sugiere echar un vistazo más de cerca a estos dos: DSAwithMD5 y RSAwithMD5. ¿Qué es mejor que DSA o RSA y cuál es su diferencia? Puede leer aquí: " ¿ Cuál funciona mejor para transferencias de archivos cifrados: RSA o DSA? ". O lea las discusiones aquí: " RSA vs. DSA para claves de autenticación SSH ". Entonces, firma digital. Necesitaremos, como antes, un KeyPair y una nueva clase Signature. Si hasta ahora ha realizado pruebas en compiladores en línea, el siguiente ejemplo puede resultarles algo complicado. Mi ejemplo solo se ejecutó aquí: rextester.com . Importamos las clases que necesitamos:
import javax.crypto.*;
import java.security.*;
También reescribiremos el 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));
    }
}
Así funciona una firma digital. La firma digital es un tema interesante. Te aconsejo que mires el informe sobre este tema:
Arquitectura de criptografía Java: primer contacto - 12
Arriba vimos cómo las partes intercambian datos. ¿No existe alguna interfaz estándar para esta interacción proporcionada en JCA? Resulta que sí lo hay. Veámoslo.
Arquitectura de criptografía Java: primer conocimiento - 13

Acuerdo clave

La arquitectura de criptografía Java presenta una herramienta importante: el acuerdo clave es un protocolo. Está representado por la clase KeyAgreement . Como se indica en la documentación de la JCA, este protocolo permite que varias partes establezcan la misma clave criptográfica sin compartir ninguna información secreta entre las partes. ¿Suena raro? Entonces veamos un ejemplo:
// 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();

Теперь, у Алисы есть открытый ключ Боба, а у Боба есть открытый ключ Алисы. Qué дальше?
Как сказано в documentoации 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 ejemplo se tomó del ejemplo de documentación de JCA: " Intercambio de claves Diffie-Hellman entre 2 partes ". Así es aproximadamente como se ve el cifrado asimétrico en la arquitectura de criptografía de Java utilizando el protocolo de acuerdo de claves. Para más información sobre el cifrado asimétrico, vídeos recomendados:
Arquitectura de criptografía Java: primer conocimiento - 14

Certificados

Bueno, de postre todavía nos queda algo no menos importante: los certificados. Normalmente, los certificados se generan utilizando la utilidad keytool incluida con el jdk. Puede leer más detalles, por ejemplo, aquí: " Generación de un certificado SSL autofirmado utilizando el comando Java keytool ". También puede leer los manuales de Oracle. Por ejemplo, aquí: " Para utilizar keytool para crear un certificado de servidor ". Por ejemplo, usemos el compilador en línea Tutorialspoint Java :
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, un certificado brinda la posibilidad de proporcionar una clave pública. Este método tiene un inconveniente: utilizamos sun.security, que se considera arriesgado porque... Este paquete no forma parte de la API pública de Java. Por eso durante la compilación es necesario especificar el parámetro - XDignore.symbol.file. Hay otra forma: crear un certificado manualmente. La desventaja es que utiliza una API interna que no está documentada. Sin embargo, es útil saberlo. Como mínimo, porque se ve claramente cómo se utiliza la especificación RFC-2459: “ Infraestructura de clave pública de Internet X.509 ”. He aquí un ejemplo:
// 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, т.е. Nombre того, с чем ассоциирован публичный ключ
// 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);
}
Arquitectura de criptografía Java: primera introducción - 15

Almacén de claves (almacén de claves)

Lo último de lo que me gustaría hablar es del almacén de claves y certificados, que se llama KeyStore. Está claro que generar constantemente certificados y claves es caro y inútil. Por lo tanto, es necesario almacenarlos de forma segura. Existe una herramienta para esto: KeyStore. El almacén de claves se describe en la documentación de JCA en el capítulo " KeyManagement ". La API para trabajar con él es muy clara. He aquí un pequeño ejemplo:
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 puede ver en el ejemplo, se ejecuta primero loadpara KeyStore. Pero en nuestro caso, especificamos el primer atributo como nulo, es decir no hay ninguna fuente para KeyStore. Esto significa que el KeyStore se crea vacío para poder guardarlo más. El segundo parámetro también es nulo, porque Estamos creando un nuevo KeyStore. Si estuviéramos cargando KeyStore desde un archivo, entonces necesitaríamos especificar una contraseña aquí (similar al método KeyStore llamado store).

Línea de fondo

Por eso hemos repasado contigo las acciones más básicas y elementales en el marco de la Arquitectura de Criptografía Java (también conocida como JCA). Vimos qué es el cifrado simétrico y asimétrico y cómo se implementa en JCA. Vimos cómo se crean los certificados y las firmas digitales y cómo se utilizan. Estos son sólo los conceptos básicos, detrás de los cuales hay muchas cosas más complejas e interesantes. Espero que este material de revisión sea útil y le interese seguir estudiando esta área.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION