JavaRush /Java блогу /Random-KY /Java криптографиясынын архитектурасы: Биринчи киришүү
Viacheslav
Деңгээл

Java криптографиясынын архитектурасы: Биринчи киришүү

Группада жарыяланган
Маалымат алмашуунун коопсуздугу заманбап колдонмолордун эң маанилүү касиеттеринин бири. Байыркы доорлордон бери адамдар айлакер ыкмаларды ойлоп табышып, адамзаттын өнүгүшү менен бүткүл криптография orмине айланган. Албетте, Java четте калган жок жана иштеп чыгуучуларга Java криптографиялык архитектурасын (JCA) сунуш кылды. Бул карап чыгуу анын кантип иштээри жөнүндө биринчи түшүнүктү бериши керек.

Кириш сөз

Мен убакытка саякаттоону сунуштайм. Биздин алдыбызда Байыркы Рим турат. Ал эми биздин алдыбызда Гай Юлий Цезарь турат, ал өзүнүн командирлерине кабар жөнөтөт. Келгиле, бул билдирүүдө эмне бар экенин карап көрөлү:
Java криптографиясынын архитектурасы: Биринчи киришүү - 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);
    }
  }
}
Биздин алдыбызда Цезарь шифринин эң жөнөкөй ишке ашырылышы турат. Байыркы римдик тарыхчы Светонийдин «Он эки Цезардын жашоосу» деген эмгегине ылайык, Цезарь өзүнүн генералдарына билдирүүлөрдү дал ушундай шифрлеген. Жана бул криптография сыяктуу нерсени колдонуунун эң байыркы шилтемелеринин бири . «Криптография» сөзү байыркы гректин «жашыруун» жана «жазуу» деген сөздөрүнөн келип чыккан, б.а. бул купуялык техникасы жөнүндөгү orм. Java криптография үчүн өзүнүн колдоосуна ээ жана ал Java Cryptography Architecture (JCA) деп аталат. Сүрөттөмө Oracle расмий documentтеринде тапса болот - " Java Cryptography Architecture (JCA) ". Мен сизге JCAнын аркасында кандай мүмкүнчүлүктөрдү алып жатканыбызды карап чыгууну сунуштайм.
Java криптографиясынын архитектурасы: Биринчи киришүү - 3

J.C.A.

Биз мурда билгендей, Java криптография менен иштөө үчүн Java криптографиялык архитектурасын (JCA) сунуштайт. Бул архитектурада API (мисалы, интерфейстердин белгилүү бир топтому) жана провайдерлер (аларды ишке ашырган):
Java криптографиясынын архитектурасы: Биринчи киришүү - 4
Документте айтылгандай, " Java платформасы бир катар орнотулган провайдерлерди камтыйт ". Башкача айтканда, Java платформасы зарыл болгон учурда кеңейтorши мүмкүн болгон камтылган провайдерлердин топтомун камсыз кылат. Муну сиз өзүңүз көрө аласыз:
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 . Бирок бул кароодо биз үчүнчү тараптын китепканалары жок негизги куралдарды гана колдонобуз. Биздин негизги document: " Java Cryptography Architecture (JCA) ". JCA кантип иштээрин түшүнүү ошол эле JCA жигердүү колдонулган технологияларды оңой түшүнүүгө жардам берет. Мисалы: HTTPS (" HTTPден HTTPSге " караңыз).
Java криптографиясынын архитектурасы: Биринчи киришүү - 5

MessageDigest

JCA documentтеринде айтылган биринчи нерсе - MessageDigest. Жалпысынан алганда, орус тorндеги Диджест бирдей болот - дайджест мааниси боюнча "резерв" дегенге туура келет. Бирок криптографияда дайджест хэш суммасы болуп саналат. Ошондой эле англисче Дайджестти дайджест деп да которууга болорун оңой эстей аласыз. Кененирээк маалыматты JCA documentтеринде " MessageDigest " бөлүмүндө таба аласыз. Документте айтылгандай, MessageDigest дайджест же хэш деп аталган белгиленген өлчөмдөгү натыйжаны жаратат. Хешинг бир тараптуу функция, б.а. эгерде биз бир нерсени хэш кылып алсак, анда натыйжадан (б.а. хэштен) баштапкы булакты ала албайбыз. Бирок, эгерде бирдей an objectтер хэштелген болсо (мисалы, окшош белгилердин саптары), анда алардын хэштери дал келиши керек. Документте айтылгандай, мындай хэш кээде маалыматтардын "текшерүү суммасы" же "санариптик манжа изи" деп да аталат. Хешинг ар кандай алгоритмдерди колдонуу менен жүргүзүлүшү мүмкүн. Жеткorктүү алгоритмдерди " JDK 8 үчүн Java криптографиясынын архитектурасынын стандарттык алгоритминин аталышынын documentациясы " documentинде көрүүгө болот . Келгиле, хэшинг жасап, консолго хэшти басып чыгаралы:
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);
    }
  }
}
Хешинг, мисалы, сырсөздөрдү сактоодо пайдалуу болушу мүмкүн. Киргизилген сырсөздүн хэшти мурда сакталган хэш менен текшерүүгө болот. Эгерде хэштер дал келсе, анда сырсөз да дал келет. Андан да коопсуз хэшинг үчүн "туз" деген түшүнүк колдонулат. Tuz SecureRandom классын колдонуу менен ишке ашырылышы мүмкүн . Дайджест ыкмасын аткаруудан мурун, келгиле, "туз" кошууну сүрөттөп көрөлү:
byte[] salt = new byte[16];
SecureRandom.getInstanceStrong().nextBytes(salt);
digester.update(salt);
Бирок хэш бир тараптуу функция. Бирок сиз шифрлөө жана шифрди чечүүнү кааласаңызчы?
Java криптографиясынын архитектурасы: Биринчи киришүү - 6

Симметриялык ачкыч криптографиясы

Симметриялык шифрлөө – шифрлөө жана чечмелөө үчүн бир эле ачкычты колдонгон шифрлөө. Симметриялык шифрлөөнү колдонуу үчүн бизге ачкыч керек. Аны алуу үчүн биз KeyGenerator колдонобуз . Мындан тышкары, бизге шифрди билдирген класс керек болот ( Cipher ). JCA documentтеринде айтылгандай, “ Шифр ​​an objectин түзүү ” бөлүмүндө Шифрди түзүү үчүн сиз жөн гана алгоритм эмес, сапта “трансформацияны” көрсөтүшүңүз керек. Трансформациянын сүрөттөлүшү мындай көрүнөт: "algorithm/rejim/padding":
  • Алгоритм : бул жерде биз “ Шифрлөө (Шифрлөө) Алгоритмдердин ” стандарттык аталыштарын карайбыз . AES колдонуу сунушталат.
  • Режим : шифрлөө режими. Мисалы: ECB же CBC (бул тууралуу кийинчерээк сүйлөшөбүз)
  • Чыгуу/Бөлүү : Маалыматтын ар бир блогу өзүнчө шифрленген. Бул параметр канча маалымат 1 блок катары эсептелерин аныктайт.
Мисалы, төмөнкү трансформацияны алалы: "AES/ECB/PKCS5Padding". Башкача айтканда, шифрлөө алгоритми - AES, шифрлөө режими - ECB (электрондук code китебинин кыскасы), блоктун өлчөмү - PKCS5Padding. PKCS5Padding бир блоктун көлөмү 2 byte (16 бит) экенин айтат. Электрондук code китебинин шифрлөө режими ар бир блоктун ырааттуу шифрлөөсүн камтыйт:
Java криптографиясынын архитектурасы: Биринчи киришүү - 7
Бул codeдо мындай көрүнүшү мүмкүн:
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 белгини белгиледик. Бул символдор 16 биттен турган 2 блокту түзөт:
Java криптографиясынын архитектурасы: Биринчи киришүү - 8
Бул учурда кайталап ойнотпоо үчүн, сиз башка режимди колдонушуңуз керек - Cipher Block Chaining (CBC). Бул режим Initialization Vector түшүнүгүн киргизет (IvParameterSpec классы менен көрсөтүлгөн). Ошондой эле бул режимдин аркасында акыркы блокту түзүүнүн натыйжасы кийинки блокту түзүү үчүн колдонулат:
Java криптографиясынын архитектурасы: Биринчи киришүү - 9
Эми муну code менен жазалы:
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 режими сунушталbyte, анткени кайталоолорду көрүүгө жана бул бorмди чечмелөө үчүн колдонууга мүмкүндүк берет. ECB жана CBC жөнүндө көбүрөөк маалымат алуу үчүн, мен сизге материалды окууну сунуштайм: “ Электрондук code китеби режими ”. Бирок симметриялык шифрлөөнүн ачык көйгөйү бар - сиз кандайдыр бир жол менен ачкычты шифрлегенден шифрлегенге өткөрүп беришиңиз керек. Жана бул жолдо бул ачкычты кармап алса болот, андан кийин маалыматтарды кармап калуу мүмкүн болот. Ал эми асимметриялык шифрлөө бул маселени чечүү үчүн иштелип чыккан.
Java криптографиясынын архитектурасы: Биринчи киришүү - 10

Асимметриялык шифрлөө

Асимметриялык шифрлөө же Ачык ачкыч криптографиясы бир жуп ачкычтарды колдонгон шифрлөө ыкмасы: купуя ачкыч (ар бир адам үчүн жашыруун сакталат) жана ачык ачкыч (жалпыга жеткorктүү). Бул бөлүү жашыруун ачкычты коопсуз сактоо менен маалымат алмашуунун тараптарынын ортосунда ачык ачкычты коопсуз алмашуу үчүн зарыл. Ачкыч жуптарын түзүп жатканда, 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 криптографиясынын архитектурасы: Биринчи таанышуу - 11

Санариптик кол коюу

Биз жогоруда көргөндөй, ачык ачкычты билүү менен, купуя ачкычтын ээси гана аны чечмелөө үчүн маалыматтарды жөнөтө аласыз. Башкача айтканда, асимметриялык шифрлөөнүн маңызы – ким шифрлейт, бирок биз гана окуйбуз. Ошондой эле тескери жол-жобосу бар - Санарип кол тамга, Кол классы менен көрсөтүлгөн . Санариптик кол коюу төмөнкү алгоритмдерди колдоно алат: " Кол коюу алгоритмдери ". JCA documentтери бул экөөнү жакшыраак карап чыгууну сунуштайт: DSAwithMD5 жана RSAwithMD5 DSA же RSAдан эмнеси жакшы жана алардын айырмасы эмнеде, сиз бул жерден окуй аласыз: " Шифрленген файлдарды өткөрүү үчүн кайсынысы эң жакшы иштейт - RSA же DSA? ". Же бул жерден талкууларды окуңуз: " SSH аутентификация ачкычтары үчүн RSA vs. DSA ". Ошентип, санариптик кол коюу. Бизге мурункудай эле KeyPair жана жаңы Signature классы керек болот. Эгер сиз буга чейин онлайн компиляторлордо сынап көргөн болсоңуз, анда төмөнкү мисал алар үчүн бир аз кыйын болушу мүмкүн. Менин мисалы бул жерде гана чуркап: rextester.com . Бизге керектүү класстарды импорттоо:
import javax.crypto.*;
import java.security.*;
Биз ошондой эле негизги ыкманы кайра жазабыз:
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 криптографиясынын архитектурасы: Биринчи таанышуу - 12
Жогоруда биз тараптар маалымат алмашууну көрдүк. Бул өз ара аракеттенүү үчүн JCAда берилген стандарттуу интерфейс жокпу? Көрсө, бар экен. Келгиле, карап көрөлү.
Java криптографиясынын архитектурасы: Биринчи таанышуу - 13

KeyAgreement

Java Cryptography Architecture маанилүү куралды киргизет - Негизги келишим протокол болуп саналат. Бул KeyAgreement классы менен көрсөтүлөт . JCA documentтеринде айтылгандай, бул протокол бир нече тараптарга бир эле криптографиялык ачкычты тараптардын ортосунда эч кандай жашыруун маалыматты бөлүшпөстөн коюуга мүмкүндүк берет. Кызык угулат? Анда бир мисалды карап көрөлү:
// 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));
Бул мисал JCA documentациясынын мисалынан алынган: " 2 Тараптын ортосундагы Диффи-Хеллман ачкыч алмашуу ". Ачкыч келишиминин протоколун колдонуу менен Java криптографиясынын архитектурасында ассиметриялык шифрлөө болжол менен ушундай көрүнөт. Асимметриялык шифрлөө жөнүндө көбүрөөк маалымат алуу үчүн сунушталган видеолор:
Java криптографиясынын архитектурасы: Биринчи таанышуу - 14

Сертификаттар

Ооба, десерт үчүн бизде дагы деле маанилүү нерсе бар - сертификаттар. Адатта, сертификаттар jdk менен камтылган keytool утorтасын колдонуу менен түзүлөт. Көбүрөөк маалыматты, мисалы, бул жерден окуй аласыз: " Java keytool буйругун колдонуу менен өз алдынча кол коюлган SSL сертификатын түзүү ". Сиз ошондой эле Oracle колдонмосун окуй аласыз. Мисалы, бул жерде: " Сервер сертификатын түзүү үчүн keytool колдонуу ". Мисалы, 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));
  }
}
Көрүнүп тургандай, сертификат ачык ачкычты берүү мүмкүнчүлүгүн берет. Бул ыкманын кемчorги бар - биз sun.securityкооптуу деп эсептелген , анткени... бул пакет коомдук Java API бөлүгү эмес. Ошондуктан компиляция учурунда - параметрин көрсөтүү зарыл XDignore.symbol.file. Дагы бир жолу бар - кол менен күбөлүк түзүү. Кемчorги documentтештирилбеген ички 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, т.е. 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 криптографиясынын архитектурасы: Биринчи киришүү - 15

Ачкыч дүкөнү (Ачкыч дүкөнү)

Мен айткым келген акыркы нерсе - KeyStore деп аталган ачкыч жана сертификаттар дүкөнү. Дайыма күбөлүктөрдү жана ачкычтарды түзүү кымбат жана маанисиз экени түшүнүктүү. Ошондуктан, аларды кандайдыр бир жол менен коопсуз сактоо керек. Бул үчүн курал бар - KeyStore. Ачкыч дүкөнү JCA documentтеринде " 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());
}
Мисалдан көрүнүп тургандай, ал биринчи кезекте loadKeyStore үчүн аткарылат. Бирок биздин учурда биз биринчи атрибутту нөл деп көрсөттүк, б.а. KeyStore үчүн булак жок. Бул KeyStore андан ары сактап калуу үчүн бош түзүлгөн дегенди билдирет. Экинчи параметр да нөл, анткени биз жаңы KeyStore түзүп жатабыз. Эгер биз KeyStore файлын жүктөп жаткан болсок, анда бул жерде сырсөздү көрсөтүшүбүз керек болот (дүкөн деп аталган KeyStore ыкмасына окшош).

Төмөнкү сызык

Ошентип, биз сиз менен Java криптография архитектурасынын (aka JCA) алкагындагы эң негизги жана elementрдык аракеттерди карап чыктык. Биз симметриялык жана асимметриялык шифрлөө деген эмне экенин жана ал JCAда кантип ишке ашырыларын көрдүк. Сертификаттарды жана санариптик кол тамгаларды кантип түзөрүн жана кандай колдонуларын көрдүк. Мунун баары жөн гана негиздер, анын артында дагы көптөгөн татаал жана кызыктуу нерселер бар. Бул карап чыгуу материалы пайдалуу болот жана бул чөйрөнү мындан ары изилдөөгө кызыкдар болот деп ишенем.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION