JavaRush /Java блог /Random UA /Java Cryptography Architecture: Перше знайомство
Viacheslav
3 рівень

Java Cryptography Architecture: Перше знайомство

Стаття з групи Random UA
Безпека обміну даними - одна з найважливіших властивостей сучасних програм. З давніх-давен люди вигадували хитрі способи, які з розвитком людства стали цілою наукою Криптографією. Звичайно, Java не залишилася осторонь і запропонувала розробникам Java Cryptography Architecture (JCA). Цей огляд повинен дати перші уявлення про те, як це працює.
Java Cryptography Architecture: Перше знайомство - 1
Зміст:

Передмова

Пропоную перенестися на якийсь час у минуле. Перед нами Стародавній Рим. І перед нами Гай Юлій Цезар, який відправляє своїм полководцям послання. Давайте подивимося, що в цьому повідомленні:
Java Cryptography Architecture: Перше знайомство - 2
Що може це значить: "ЕСКЕУГЬГМХИФЯ Е УЛП"? Давайте відкриємо Java Online Compiler, наприклад: 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);
    }
  }
}
Перед нами найпростіша реалізація "Шифра Цезаря" (Caesar Cipher). Згідно з працею давньоримського історика Светонія під назвою "Життя дванадцяти цезарів" саме так Цезар шифрував послання до своїх полководців. І це - одна з найдавніших згадок про використання такої речі, як Криптографія . Слово " криптографія " походить від давньогрецьких слів " прихований " і " пишу " , тобто. це наука про методи забезпечення конфіденційності. У Java є своя підтримка криптографії і називається вона – Java Cryptography Architecture (JCA). Опис можна знайти в офіційній документації від Oracle - " Java Cryptography Architecture (JCA) ". Пропоную подивитись, які можливості ми отримуємо завдяки JCA.
Java Cryptography Architecture: Перше знайомство - 3

JCA

Як ми вже раніше дізналися, Java для роботи з криптографією пропонує Java Cryptography Architecture (JCA). Ця архітектура містить API (тобто деякий набір інтерфейсів) та провайдери (які їх реалізують):
Java Cryptography Architecture: Перше знайомство - 4
Як сказано в документації, " The Java platform включає в себе номер built-in providers ". Тобто платформа Java надає набір вбудованих провайдерів, які можна доповнити. Це можна побачити самим:
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());
    }
  }
}
Зареєструвати сторонній провайдер дуже просто. Наприклад: Security.addProvider(new BouncyCastleProvider()); Цей приклад включає один з найвідоміших провайдерів - BouncyCastle . Але в цьому огляді ми користуватимемося лише базовими засобами, без сторонніх бібліотек. Наш основний документ: " Java Cryptography Architecture (JCA) ". Розуміння роботи JCA допоможе простіше зрозуміти технології, в рамках яких активно використовується цей JCA. Наприклад: HTTPS (див. " Від HTTP до HTTPS ").
Java Cryptography Architecture: Перше знайомство - 5

MessageDigest

Перше, про що згадується в документації JCA - це MessageDigest. Взагалі Digest російською буде так само - дайджест і відповідає за змістом "короткий виклад". Але в криптографії дайджестом називається хеш-сума. А ще можна легко запам'ятати, що англійською Digest можна перекласти ще як перетравлювати. Докладніше можна прочитати в документації JCA у розділі " MessageDigestЯк сказано в документації, MessageDigest генерує фіксованого розміру результат, званий digest або hash. першоджерело Але якщо хешується однакові об'єкти (наприклад, рядки з однакових символів), то їх хеш повинен збігатися. даних.Хешування може виконуватися використовуючи різні алгоритми.Доступні алгоритми можна подивитися в документі " Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8 ". Давайте виконаємо хешування і виведемо хеш в консоль:
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);
    }
  }
}
Хешування може бути корисним, наприклад, при зберіганні паролів. Оскільки хеш пароля, що вводиться, можна звірити з раніше збереженим хеш. Якщо хеші збіглися, значить і пароль теж збігся. Для ще безпечнішого хешування використовують таке поняття, як "сіль" (salt). Сіль можна реалізувати за допомогою класу SecureRandom . Перед виконанням методу digest опишемо додавання "солі":
byte[] salt = new byte[16];
SecureRandom.getInstanceStrong().nextBytes(salt);
digester.update(salt);
Але хеш – функція одностороння. А що робити, якщо хочеться мати можливість зашифрувати та розшифрувати?
Java Cryptography Architecture: Перше знайомство - 6

Симетричне шифрування (symmetric key cryptography)

Симетричне шифрування - це шифрування, при якому для шифрування та дешифрування використовується той самий ключ. Для того, щоб використовувати симетричне шифрування, нам потрібен ключ. Щоб його отримати використовуємо KeyGenerator . Крім того, нам знадобиться клас, що є шифром ( Cipher ). Як сказано в документації JCA у розділі " Creating a Cipher Object ", щоб створити Cipher потрібно вказати у рядку не просто алгоритм, а "трансформацію". Опис трансформації виглядає наступним чином: "algorithm/mode/padding":
  • Алгоритм : тут дивимося в стандартних іменах для " Cipher (Encryption) Algorithms ". Рекомендується використовувати AES.
  • Режим : режим шифрування. Наприклад: ECB або CBC (про це ми поговоримо трохи далі)
  • Відступ/розбивка : кожен блок даних шифрується окремо. Цей параметр визначає, який обсяг даних рахувати за 1 блок.
Наприклад, візьмемо таку трансформацію: "AES/ECB/PKCS5Padding". Тобто алгоритм шифрування – AES, режим шифрування ECB (скорочення для Electronic Codebook), розмір блоку – PKCS5Padding. PKCS5Padding каже, що розмір одного блоку – 2 байти (16 біт). Режим шифрування Electronic Codebook передбачає послідовне шифрування кожного блоку:
Java Cryptography Architecture: Перше знайомство - 7
Виглядати в коді це може так:
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);
  }
}
Якщо ми здійснимо, то очікувано побачимо повтор, т.к. ми вказали 32 символи. Ці символи становлять 2 блоки по 16 біт:
Java Cryptography Architecture: Перше знайомство - 8
Щоб уникнути у такому разі повтору, слід використовувати інший режим — Cipher Block Chaining (CBC). Цей режим вводить поняття Initialization Vector (представлений класом IvParameterSpec). А також завдяки цьому режиму результат генерації минулого блоку буде використаний для генерації наступного:
Java Cryptography Architecture: Перше знайомство - 9
Напишемо тепер це в коді:
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);
  }
}
Як ми бачимо — в результаті ми не бачимо блоків шифру, що повторюються. Тому режим ECB не рекомендується, т.к. дає можливість побачити повтори та використовувати це знання для дешифрування. Детальніше про ECB та CBC раджу прочитати матеріал: " Режим електронної кодової книги ". Але симетричне шифрування має очевидну проблему – треба якось передати ключ від того, хто шифрує, тому хто шифрує. І на цьому шляху цей ключ можна перехопити, і тоді буде можливість перехоплювати дані. І цю проблему має вирішити асиметричне шифрування.
Java Cryptography Architecture: Перше знайомство - 10

Асиметричне шифрування (asymmetric cryptography)

Асиметричне шифрування або Public-key cryptography - це такий спосіб шифрування, при якому використовується пара ключів: private key (зберігається від усіх у секреті) і public key (доступний публічно). Такий поділ потрібний для того, щоб безпечно обмінюватися відкритим ключем між сторонами обміну інформацією, зберігаючи секретний ключ у безпеці. У створенні пари ключів нам недостатньо KeyGenerator, нам потрібен KeyPairGenerator . Подивимося на приклад:
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));
  }
}
Тут важливо розуміти, що використовуючи асиметричне шифрування, ми завжди з KeyPair використовуємо один ключ для шифрування, а інший для дешифрування. Але т.к. сенс шифрування у цьому, щоб розшифрувати зміг лише одержувач, то шифрується громадським ключем, а розшифровується лише приватним.
Java Cryptography Architecture: Перше знайомство - 11

Цифровий підпис

Як ми бачабо вище, знаючи public key можна надсилати дані так, щоб їх розшифрував тільки власник private key. Тобто суть асиметричного шифрування в тому, що шифрує будь-хто, а читаємо тільки ми. Є і зворотна процедура – ​​цифровий підпис, представлений класом Signature . Цифровий підпис може використовувати такі алгоритми: " Signature Algorithms ". Документація по JCA пропонує придивитися до цих двох: DSAwithMD5 і RSAwithMD5 Що краще DSA або RSA і в чому їх відмінність можна прочитати тут: "Which Works Best for Encrypted File Transfers - RSA or DSA? ". Або почитати обговорення тут: " RSA vs. DSA for SSH authentication keysОтже, цифровий підпис. Нам знадобиться, як і раніше, пара ключів KeyPair та новий клас Signature. Якщо Ви досі тестували в онлайн компіляторах, то наступний приклад може для них виявитися дещо важким. У мене приклад виконався тільки тут: rextester .com Імпортуємо необхідні нам класи:
import javax.crypto.*;
import java.security.*;
А також перепишемо main метод:
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));
    }
}
Ось таким чином працює цифровий підпис. Цифровий підпис – цікава тема. Раджу подивитись на цю тему доповідь:
Java Cryptography Architecture: Перше знайомство - 12
Вище ми побачабо, як сторони обмінюються даними. Чи немає якогось стандартного інтерфейсу для цієї взаємодії, передбаченої JCA? Виявляється – є. Давайте розглянемо його.
Java Cryptography Architecture: Перше знайомство - 13

KeyAgreement

Java Cryptography Architecture вводить важливий інструмент - Key agreement is a protocol. Представлений він класом KeyAgreement . Як зазначено в документації JCA, цей протокол дозволяє встановити однаковий криптографічний ключ для кількох сторін, при цьому жодної секретної інформації між сторонами не передається. Звучить дивно? Тоді давайте подивимося на приклад:
// 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();

Теперь, у Алисы есть открытый ключ Боба, а у Боба есть открытый ключ Алисы. Що дальше?
Как сказано в документации 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));
Цей приклад було взято з прикладом документації JCA: " Diffie-Hellman Key Exchange між 2 Parties ". Приблизно так виглядає робота асиметричного шифрування у виконанні Java Cryptography Architecture із використанням Key agreement protocol'а. Докладніше про асиметричне шифрування рекомендуються відео:
Java Cryptography Architecture: Перше знайомство - 14

Сертифікати

Ну і на солодке у нас залишилося не менш важливе сертифікати. Зазвичай сертифікати генеруються за допомогою утиліти keytool, що входить до постачання jdk. Докладніше можна прочитати, наприклад, тут: " Generating a self-signed SSL certificate using the Java keytool command " . Також можна прочитати в посібниках від Oracle. Наприклад, тут: " To Use keytool to Create a Server Certificate ". Для прикладу скористаємося 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));
  }
}
Як бачимо, сертифікат надає можливість надати публічний ключ. Цей спосіб є недолік — ми використовуємо sun.security, що вважається ризикованим, т.к. цей пакет не є частиною публічного Java API. Саме тому при компіляції необхідно вказати параметр XDignore.symbol.file. Є ще один спосіб створити сертифікат вручну. Мінус у тому, що використовується внутрішній API, який не задокументований. Проте знати про нього корисно. Як мінімум, тому що наочно видно, як використовується специфікація RFC-2459: " Internet X.509 Public Key Infrastructure ". Ось приклад:
// 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, т.е. ім'я того, с чем ассоциирован публичный ключ
// 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);
}
Java Cryptography Architecture: Перше знайомство - 15

Сховище ключів (KeyStore)

Останнє, про що хотілося б поговорити, це про сховище ключів та сертифікатів, яке називається KeyStore. Зрозуміло, що постійно генерувати сертифікати та ключі дорого і безглуздо. Тому їх треба якось безпечно зберігати. Для цього є засіб – KeyStore. Сховище ключів описано в документації JCA у розділі " KeyManagement ". API до роботи з ним дуже зрозуміле. Ось невеликий приклад:
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());
}
Як очевидно з прикладу, спочатку виконується loadдля KeyStore. Але у разі ми вказали перший атрибут null, тобто. джерела для KeyStore немає. Значить KeyStore створюється порожньою, щоб зберегти його далі. Другий параметр також null, т.к. ми створюємо новий KeyStore. Якби ми завантажували KeyStore з файлу, тут потрібно було б вказати пароль (за аналогією з методом KeyStore з назвою store).
Java Cryptography Architecture: Перше знайомство - 16

Підсумок

Ось ми і розглянули з Вами основні і елементарні дії в рамках Java Cryptography Architecture (воно ж JCA). Ми побачабо, що таке симетричне та асиметричне шифрування і як це реалізовано у JCA. Ми побачабо, як створюються сертифікати та цифрові підписи, а також як використовуються. Це лише основи основ, за якими стоїть ще багато складних і цікавих речей. Сподіваюся, дані оглядовий матеріал буде корисним та зацікавить Вас на подальше вивчення даного напрямку. Ну і на завершення хотілося б вказати супер відео на цю тему:
Java Cryptography Architecture: Перше знайомство - 17
Додаткові матеріали:
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ