Изграждане на защитени мрежови приложения със сертификати, част 2

За да изградите защитени приложения, трябва да научите инструментите на занаята. За да ви помогна да се запознаете с тези концепции, аз ви запознах с криптографията с публичен ключ в част 1 и обясних как тя избягва проблемите с обмена на ключове, които съпътстват криптографията с секретен ключ. Също така проучих връзката между доверието и мащабируемостта на криптографията с публичен ключ и обясних как сертификатите и инфраструктурата с публичен ключ (PKI) позволяват доверието в по-широк мащаб, отколкото криптографията с публичен ключ може да постигне сама. Накрая описах сертификати и вериги от сертификати и обясних как се отнасят към CA (сертифициращи органи).

Предлагат се много различни вкусове на сертификати, включително SDSI (проста разпределена инфраструктура за сигурност), PGP (доста добра поверителност) и X.509. Този месец, за да разширя допълнително вашия речник на сигурността, ще опиша формата на сертификата, който води пакета и е ключов компонент на нововъзникващите PKI стандарти: сертификатът X.509.

Можете да прочетете цялата серия на сертификати:

  • Част 1: Сертификатите добавят стойност към криптографията с публичен ключ
  • Част 2: Научете се да използвате сертификатите X.509
  • Част 3: Използвайте класовете Java CRL и X509CRL
  • Част 4: Удостоверяване на клиенти и сървъри и проверка на вериги от сертификати

Форматът X.509 в детайли

Международният съюз за далекосъобщения (ITU) разработи и публикува формата на сертификата X.509, който беше избран от работната група за инфраструктура с публичен ключ X.509 (PKIX) на Работната група за интернет инженеринг (IETF). Ако съкращенията показват сила, X.509 очевидно има мощни съюзници.

Използвайки нотация, наречена ASN.1 (Abstract Syntax Notation One), стандартът X.509 определя формата на сертификата. ASN.1 е стандартизиран език, който описва абстрактни типове данни по независим от платформата начин.

Документът „Инфраструктура на публичния ключ на Интернет X.509 - Сертификат и CRL профил“ (вижте Ресурси за връзка), публикуван от работната група на PKIX, описва формат на сертификат X.509 по отношение на нотация ASN.1. Това е увлекателно четиво, ако се интересувате от такива неща.

Типът данни - като сертификат - дефиниран в ASN.1 не е полезен, докато не може еднозначно да дефинира как да се представи екземпляр от тип данни като поредица от битове. За да придаде на типа данни тази функционалност, ASN.1 използва Разграничени правила за кодиране (DER), които определят как да се кодира уникално всеки ASN.1 обект.

С копие на дефиницията ASN.1 на сертификат X.509 и познаване на DER, можете да напишете Java приложение, което ще чете и записва сертификати X.509 и ще взаимодейства с подобни приложения, написани на други езици за програмиране. За щастие вероятно никога няма да се наложи да се справяте с толкова много проблеми, защото платформата Java 2, стандартно издание (J2SE) се предлага с вградена поддръжка за сертификати X.509.

X.509 за (почти) нищо

Всички класове и интерфейси, свързани със сертификата, се намират в пакета java.security.cert. Подобно на останалите членове на семейството на API за сигурност на Sun, пакетът със сертификати е проектиран около фабричната парадигма, в която един или повече Java класове дефинират общ интерфейс към предвидената функционалност на пакета. Класовете са абстрактни, така че приложенията не могат да ги създават директно. Вместо това екземпляр на фабричен клас създава и връща екземпляри на конкретните подтипове на абстрактните класове. Фабричната парадигма заобикаля силното писане на Java, но в замяна позволява на кода да работи без рекомпилация в по-широк диапазон от среди.

В java.security.cert.Certificateи java.security.cert.CRLабстрактни класове определя интерфейсът. Те представляват съответно сертификати и списъци за отмяна на сертификати (CRL). Най- CertificateFactoryкласа е тяхната фабрика.

В java.security.certпакета съдържа конкретни реализации на Certificateи CRLабстрактни класа: X509Certificateи X509CRLкласове. Тези два класа изпълняват основния сертификат и функционалността на CRL, след което го разширяват със специфична функционалност X.509. Когато даден CertificateFactoryекземпляр връща екземпляр от който и да е клас, програма може или да го използва такъв, какъвто е, или изрично да го прехвърли във формата X.509.

В java.security.certпакета интерфейсът X509Extensionопределя интерфейс към разширенията на сертификат X.509. Разширенията са незадължителни компоненти, които осигуряват механизъм за създателите на сертификати да свързват допълнителна информация със сертификат. Например сертификатът може да използва KeyUsageразширението, за да посочи, че може да се използва за подписване на код.

В java.security.certпакета включва и Доставчик на услуги интерфейс (SPI) клас. А доставчик криптографски услуга , която желае да поддържа вид сертификат разширява SPI. Java 2 се предлага с SPI за сертификати X.509.

Нека разгледаме по-подробно класовете и интерфейсите в java.security.certпакета. За краткост ще обсъдя само най-полезните методи. За по-изчерпателно покритие ви препоръчвам да прочетете документацията на Sun. (Вижте Ресурси.)

java.security.cert.CertificateFactory

Историята започва с java.security.cert.CertificateFactory. В CertificateFactoryкласа има статични методи, които създават CertificateFactoryнапример за определен тип сертификат, както и методи, които създават сертификати, така и РЛО от данни, предоставени в входящ поток. Ще опиша накратко най-важните методи, след което ще обясня как да се използват тези методи при генериране на X.509 сертификати и CRL. По-нататък в статията ще ви представя код, който демонстрира действащите методи.

  • public static CertificateFactory getInstance(String stringType)и public static CertificateFactory getInstance(String stringType, String stringProvider)създайте екземпляр и върнете екземпляр на фабрика на сертификати за типа сертификат, посочен от stringTypeпараметъра. Например, ако стойността на stringTypeе низът "X.509", и двата метода ще върнат екземпляр на CertificateFactoryкласа, подходящ за създаване на екземпляри на класовете X509Certificateи X509CRL. Вторият метод приема името на конкретен доставчик на криптографски услуги като аргумент и използва този доставчик вместо по подразбиране.
  • public final Certificate generateCertificate(InputStream inputstream)инстанцира и връща сертификат, използвайки данни, прочетени от предоставения InputStreamекземпляр. Ако потокът съдържа повече от един сертификат и потокът поддържа операциите mark()and reset(), методът ще прочете един сертификат и ще остави потока позициониран преди следващия.
  • public final Collection generateCertificates(InputStream inputstream)създава екземпляри и връща колекция от сертификати, използвайки данни, прочетени от предоставения InputStreamекземпляр. Ако дадения поток не поддържа mark()и reset(), методът ще погълне целия поток.
  • public final CRL generateCRL(InputStream inputstream)инстанцира и връща CRL, използвайки данни, прочетени от предоставения InputStreamекземпляр. Ако потокът съдържа повече от един CRL и поддържа операциите mark()and reset(), методът ще прочете един CRL и ще остави потока позициониран преди следващия.
  • public final Collection generateCRLs(InputStream inputstream)инстанцира и връща колекция от CRL, използвайки данни, прочетени от предоставения InputStreamекземпляр. Ако дадения поток не поддържа mark()и reset(), public final Collection generateCRLs(InputStream inputstream)ще погълне целия поток.

Важно е да се разбере как се държат тези четири метода при генериране на X.509 екземпляри от поток от данни. Нека да разгледаме.

Методите generateCertificate()and и generateCRL()очакват съдържанието на входния поток да съдържа съответно DER-кодирани представления на сертификат или CRL.

Както методите, така generateCertificates()и generateCRLs()методите очакват съдържанието на входния поток да съдържа или последователност от DER-кодирани представления, или сертификат, съвместим с PKCS # 7 (стандарт за криптография с публичен ключ # 7) или CRL. (Вижте Ресурси за връзки.)

java.security.cert.Certificate

java.security.cert.Certificateопределя интерфейса, общ за всички видове сертификати: X.509, PGP и малка шепа други. Най-важните методи на този клас са:

  • public abstract PublicKey getPublicKey() връща публичния ключ, свързан с екземпляра на сертификата, за който се извиква този метод.
  • public abstract byte [] getEncoded() връща кодираната форма на този сертификат.
  • public abstract void verify(PublicKey publickey)и public abstract void verify(PublicKey publickey, String stringProvider)проверете дали частният ключ, съответстващ на предоставения публичен ключ, е подписал въпросния сертификат. Ако ключовете не съвпадат, и двата метода хвърлят a SignatureException.

java.security.cert.X509Certificate

Класът java.security.cert.X509Certificateразширява Certficateописания по-горе клас и добавя функционалност, специфична за X.509. Този клас е важен, защото обикновено взаимодействате със сертификати на това ниво, а не като основен клас.

  • public abstract byte [] getEncoded()връща кодираната форма на този сертификат, както по-горе. Методът използва DER кодирането за сертификата.

По-голямата част от java.security.cert.X509Certificateдопълнителната функционалност на се състои от методи за заявки, които връщат информация за сертификата. Представих по-голямата част от тази информация в част 1. Ето методите:

  • public abstract int getVersion() връща версията на сертификата.
  • public abstract Principal getSubjectDN() връща информация, която идентифицира предмета на сертификата.
  • public abstract Principal getIssuerDN() връща информация, която идентифицира издателя на сертификата, който обикновено е CA, но може да бъде предмет, ако сертификатът е самоподписан.
  • public abstract Date getNotBefore()и public abstract Date getNotAfter()връща стойности, които ограничават периода от време, през който емитентът е готов да гарантира за публичния ключ на субекта.
  • public abstract BigInteger getSerialNumber()връща серийния номер на сертификата. Комбинацията от име на издател на сертификат и сериен номер е неговата уникална идентификация. Този факт е от решаващо значение за отнемането на сертификат, което ще обсъдя по-подробно следващия месец.
  • public abstract String getSigAlgName()и public abstract String getSigAlgOID()връща информация за алгоритъма, използван за подписване на сертификата.

Следните методи връщат информация за разширенията, дефинирани за сертификата. Не забравяйте, че разширенията са механизми за свързване на информация със сертификат; те се появяват само в сертификати от версия 3.

  • public abstract int getBasicConstraints()връща дължината на пътя на ограниченията на сертификата от BasicConstraintsразширението, ако е дефинирано. Пътят на ограниченията указва максималния брой CA сертификати, които могат да следват този сертификат в път за сертифициране.
  • public abstract boolean [] getKeyUsage()връща целта на сертификата, кодирана в KeyUsageразширението.
  • public Set getCriticalExtensionOIDs()и public Set getNonCriticalExtensionOIDs()връща колекция от идентификатори на обекти (OID) за разширенията, маркирани съответно критични и некритични. OID е последователност от цели числа, която универсално идентифицира ресурс.

Не искам да ви оставям без код за игра, така че вместо да се задълбочавам в CRL, което е пълна тема сама по себе си, ще представя кода и ще оставя CRL за част 3.

Кодът

Следващият клас демонстрира как да се получи фабрика за сертификати, как да се използва тази фабрика за генериране на сертификат от DER-кодираното представяне във файл и как да се извлече и покаже информация за сертификата. Ще забележите колко малко трябва да се притеснявате за основното кодиране.