Spec-Zone.ru › OpenJDK 17

Класс X509Certificate

java.lang.Object
java.security.cert.Certificate
java.security.cert.X509Certificate
Все реализованные интерфейсы:
Serializable, X509Extension
public abstract class X509Certificate extends Certificate implements X509Extension

Абстрактный класс для сертификатов X.509. Он предоставляет стандартный способ доступа ко всем атрибутам сертификата X.509.

В июне 1996 года базовый формат X.509 v3 был завершен ISO/IEC и ANSI X9, который описан ниже в ASN.1:

 Certificate  ::=  SEQUENCE  {
     tbsCertificate       TBSCertificate,
     signatureAlgorithm   AlgorithmIdentifier,
     signature            BIT STRING  }
 

Эти сертификаты широко используются для поддержки аутентификации и других функций в системах безопасности Интернета. Общие приложения включают Privacy Enhanced Mail (PEM), Transport Layer Security (SSL), подпись кода для надельного распространения программного обеспечения и Secure Electronic Transactions (SET).

Эти сертификаты управляются и гарантируются Уполномоченными центрами сертификации (УЦС). УЦС — это сервисы, которые создают сертификаты, помещая данные в стандартный формат X.509, а затем цифрово подписывают эти данные. УЦС действуют как доверенные третьи стороны, обеспечивая знакомство между принципами, которые не имеют прямого знания друг друга. Сертификаты УЦС либо подписаны самим УЦС, либо другим УЦС, например, «корневым» УЦС.

Более подробную информацию можно найти в RFC 5280: Профиль сертификатов и списков отозванных сертификатов (CRL) для общедоступной инфраструктуры открытых ключей Internet X.509.

Определение ASN.1 для tbsCertificate:

 TBSCertificate  ::=  SEQUENCE  {
     version         [0]  EXPLICIT Version DEFAULT v1,
     serialNumber         CertificateSerialNumber,
     signature            AlgorithmIdentifier,
     issuer               Name,
     validity             Validity,
     subject              Name,
     subjectPublicKeyInfo SubjectPublicKeyInfo,
     issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                          -- If present, version must be v2 or v3
     subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                          -- If present, version must be v2 or v3
     extensions      [3]  EXPLICIT Extensions OPTIONAL
                          -- If present, version must be v3
     }
 

Сертификаты создаются с помощью фабрики сертификатов. Ниже приведен пример создания сертификата X.509:

 try (InputStream inStream = new FileInputStream("fileName-of-cert")) {
     CertificateFactory cf = CertificateFactory.getInstance("X.509");
     X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
 }
 
С тех пор:
1.2
См. также:
  • Certificate
  • CertificateFactory
  • X509Extension
  • Сериализованная форма

Краткое описание вложенных классов

Вложенные классы/интерфейсы, объявленные в классе java.security.cert.Certificate

Certificate.CertificateRep

Краткое описание конструкторов

X509Certificate()
Модификатор Конструктор Описание
protected
Конструктор для сертификатов X.509.

Краткое описание методов

Модификатор и тип Метод Описание
abstract void checkValidity()
Проверяет, является ли сертификат в данный момент действительным.
abstract void checkValidity(Date date)
Проверяет, попадает ли заданная дата в период действия сертификата.
abstract int getBasicConstraints()
Получает длину пути ограничений сертификата из критического BasicConstraints расширения (OID = 2.5.29.19).
List<String> getExtendedKeyUsage()
Получает список только для чтения строк, представляющих OBJECT IDENTIFIERы поля ExtKeyUsageSyntax расширения расширенного использования ключа (OID = 2.5.29.37).
Collection<List<?>> getIssuerAlternativeNames()
Получает неизменяемую коллекцию альтернативных имен издателя из IssuerAltName расширения (OID = 2.5.29.18).
abstract Principal getIssuerDN()
Устарело.
Используйте getIssuerX500Principal() вместо этого.
abstract boolean[] getIssuerUniqueID()
Получает значение issuerUniqueID из сертификата.
X500Principal getIssuerX500Principal()
Возвращает значение издателя (различительное имя издателя) из сертификата как X500Principal.
abstract boolean[] getKeyUsage()
Получает булевый массив, представляющий биты KeyUsage расширения (OID = 2.5.29.15).
abstract Date getNotAfter()
Получает дату notAfter из периода действия сертификата.
abstract Date getNotBefore()
Получает дату notBefore из периода действия сертификата.
abstract BigInteger getSerialNumber()
Получает значение serialNumber из сертификата.
abstract String getSigAlgName()
Получает имя алгоритма подписи для алгоритма подписи сертификата.
abstract String getSigAlgOID()
Получает строку OID алгоритма подписи из сертификата.
abstract byte[] getSigAlgParams()
Получает параметры алгоритма подписи в формате DER из алгоритма подписи этого сертификата.
abstract byte[] getSignature()
Получает значение signature (сырые биты подписи) из сертификата.
Collection<List<?>> getSubjectAlternativeNames()
Получает неизменяемую коллекцию альтернативных имен субъекта из SubjectAltName расширения (OID = 2.5.29.17).
abstract Principal getSubjectDN()
Устарело.
Используйте getSubjectX500Principal() вместо этого.
abstract boolean[] getSubjectUniqueID()
Получает значение subjectUniqueID из сертификата.
X500Principal getSubjectX500Principal()
Возвращает значение субъекта (различительное имя субъекта) из сертификата как X500Principal.
abstract byte[] getTBSCertificate()
Получает закодированную в DER информацию о сертификате, tbsCertificate из этого сертификата.
abstract int getVersion()
Получает значение version (номер версии) из сертификата.
void verify(PublicKey key, Provider sigProvider)
Проверяет, что этот сертификат был подписан с использованием закрытого ключа, соответствующего указанному открытому ключу.

Методы, объявленные в классе java.security.cert.Certificate

equals, getEncoded, getPublicKey, getType, hashCode, toString, verify, verify, writeReplace

Методы, объявленные в классе java.lang.Object

clone, finalize, getClass, notify, notifyAll, wait, wait, wait

Методы, объявленные в интерфейсе java.security.cert.X509Extension

getCriticalExtensionOIDs, getExtensionValue, getNonCriticalExtensionOIDs, hasUnsupportedCriticalExtension

Подробное описание конструкторов

X509Certificate

protected X509Certificate()
Конструктор для сертификатов X.509.

Подробное описание методов

checkValidity

public abstract void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException
Проверяет, является ли сертификат в настоящее время действительным. Он действителен, если текущая дата и время находятся в пределах периода действия, указанного в сертификате.

Период действия состоит из двух значений даты/времени: первой и последней дат (и времени), на которые сертификат действителен. Он определен в ASN.1 как:

 validity             Validity

 Validity ::= SEQUENCE {
     notBefore      CertificateValidityDate,
     notAfter       CertificateValidityDate }

 CertificateValidityDate ::= CHOICE {
     utcTime        UTCTime,
     generalTime    GeneralizedTime }
 
Исключение:
CertificateExpiredException - если сертификат просрочен.
CertificateNotYetValidException - если сертификат еще не действителен.

checkValidity

public abstract void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException
Проверяет, входит ли заданная дата в период действия сертификата. Другими словами, это определяет, будет ли сертификат действителен в заданную дату/время.
Параметры:
date - дата для проверки, действителен ли этот сертификат в эту дату/время.
Исключение:
CertificateExpiredException - если сертификат просрочен относительно предоставленной date.
CertificateNotYetValidException - если сертификат еще не действителен относительно предоставленной date.
См. также:
  • checkValidity()

getVersion

public abstract int getVersion()
Получает значение version (номер версии) из сертификата. Определение ASN.1 для этого:
 version  [0] EXPLICIT Version DEFAULT v1

 Version ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
 
Возвращает:
номер версии, т.е. 1, 2 или 3.

getSerialNumber

public abstract BigInteger getSerialNumber()
Получает значение serialNumber из сертификата. Номер сертификата — целое число, назначенное центром сертификации каждому сертификату. Он должен быть уникальным для каждого сертификата, выданного данным ЦС (т.е., имя издателя и номер сертификата идентифицируют уникальный сертификат). Определение ASN.1 для этого:
 serialNumber     CertificateSerialNumber

 CertificateSerialNumber  ::=  INTEGER
 
Возвращает:
номер сертификата.

getIssuerDN

@Deprecated(since="16") public abstract Principal getIssuerDN()
Устарело.
Используйте getIssuerX500Principal() вместо этого. Этот метод возвращает issuer как объект, специфичный для реализации Principal, на который не следует полагаться портативному коду.
Получает значение issuer (имя субъекта-выдающего органа) из сертификата. Имя издателя идентифицирует сущность, которая подписала (и выпустила) сертификат.

Поле имени издателя содержит расширенное имя X.500 (DN). Определение ASN.1 для этого:

 issuer    Name

 Name ::= CHOICE { RDNSequence }
 RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
 RelativeDistinguishedName ::=
     SET OF AttributeValueAssertion

 AttributeValueAssertion ::= SEQUENCE {
                               AttributeType,
                               AttributeValue }
 AttributeType ::= OBJECT IDENTIFIER
 AttributeValue ::= ANY
 
Name описывает иерархическое имя, состоящее из атрибутов, таких как имя страны, и соответствующих значений, таких как США. Тип компонента AttributeValue определяется AttributeType; в общем случае это будет directoryString. directoryString обычно является одним из PrintableString, TeletexString или UniversalString.
Возвращает:
объект Principal, имя которого является расширенным именем субъекта-выдающего органа.

getIssuerX500Principal

public X500Principal getIssuerX500Principal()
Возвращает значение издателя (расширенное имя субъекта-выдающего органа) из сертификата в виде X500Principal.

Рекомендуется, чтобы подклассы переопределяли этот метод.

Возвращает:
объект X500Principal, представляющий расширенное имя субъекта-выдающего органа
С:
1.4

getSubjectDN

@Deprecated(since="16") public abstract Principal getSubjectDN()
Устарело.
Используйте getSubjectX500Principal() вместо этого. Этот метод возвращает subject как объект, специфичный для реализации Principal, на который не следует полагаться портативному коду.
Получает значение subject (расширенное имя субъекта) из сертификата. Если значение subject пустое, то метод getName() возвращаемого объекта Principal возвращает пустую строку ("").

Определение ASN.1 для этого:

 subject    Name
 

См. getIssuerDN для Name и других соответствующих определений.

Возвращает:
объект Principal, имя которого является именем субъекта.

getSubjectX500Principal

public X500Principal getSubjectX500Principal()
Возвращает значение субъекта (расширенное имя субъекта) из сертификата как X500Principal. Если значение субъекта пустое, то метод getName() возвращаемого объекта X500Principal возвращает пустую строку ("").

Рекомендуется, чтобы подклассы переопределяли этот метод.

Возвращает:
объект X500Principal, представляющий расширенное имя субъекта
С:
1.4

getNotBefore

public abstract Date getNotBefore()
Получает notBefore дату из периода действия сертификата. Соответствующие определения ASN.1:
 validity             Validity

 Validity ::= SEQUENCE {
     notBefore      CertificateValidityDate,
     notAfter       CertificateValidityDate }

 CertificateValidityDate ::= CHOICE {
     utcTime        UTCTime,
     generalTime    GeneralizedTime }
 
Возвращает:
начальную дату периода действия.
См. также:
  • checkValidity()

getNotAfter

public abstract Date getNotAfter()
Получает notAfter дату из периода действия сертификата. См. getNotBefore для соответствующих определений ASN.1.
Возвращает:
конечную дату периода действия.
См. также:
  • checkValidity()

getTBSCertificate

public abstract byte[] getTBSCertificate() throws CertificateEncodingException
Получает закодированные в DER данные о сертификате, tbsCertificate из этого сертификата. Это можно использовать для независимой проверки подписи.
Возвращает:
закодированные в DER данные о сертификате.
Исключение:
CertificateEncodingException - если произошла ошибка кодирования.

getSignature

public abstract byte[] getSignature()
Получает значение signature (сырые биты подписи) из сертификата. Определение ASN.1 для этого:
 signature     BIT STRING
 
Возвращает:
подпись.

getSigAlgName

public abstract String getSigAlgName()
Получает имя алгоритма подписи для алгоритма подписи сертификата. Пример — строка "SHA256withRSA". Определение ASN.1 для этого:
 signatureAlgorithm   AlgorithmIdentifier

 AlgorithmIdentifier  ::=  SEQUENCE  {
     algorithm               OBJECT IDENTIFIER,
     parameters              ANY DEFINED BY algorithm OPTIONAL  }
                             -- contains a value of the type
                             -- registered for use with the
                             -- algorithm object identifier value
 

Имя алгоритма определяется из строки OID algorithm.

Возвращает:
имя алгоритма подписи.

getSigAlgOID

public abstract String getSigAlgOID()
Получает строку OID алгоритма подписи из сертификата. OID представлен набором неотрицательных целых чисел, разделенных точками. Например, строка "1.2.840.10040.4.3" идентифицирует алгоритм подписи SHA-1 с DSA, определенный в RFC 3279: Алгоритмы и идентификаторы для инфраструктуры открытых ключей Интернет X.509, сертификаты и профили CRL.

См. getSigAlgName для соответствующих определений ASN.1.

Возвращает:
строку OID алгоритма подписи.

getSigAlgParams

public abstract byte[] getSigAlgParams()
Получает закодированные в DER параметры алгоритма подписи из алгоритма подписи этого сертификата. В большинстве случаев параметры алгоритма подписи равны null; параметры обычно предоставляются с открытым ключом сертификата. Если нужен доступ к отдельным значениям параметров, используйте AlgorithmParameters и инициализируйте его именем, возвращенным getSigAlgName.

См. getSigAlgName для соответствующих определений ASN.1.

Возвращает:
закодированные в DER параметры алгоритма подписи или null, если параметры отсутствуют.

getIssuerUniqueID

public abstract boolean[] getIssuerUniqueID()
Получает значение issuerUniqueID из сертификата. Уникальный идентификатор издателя присутствует в сертификате, чтобы учесть возможность повторного использования имен издателей со временем. RFC 5280 рекомендует не повторно использовать имена и не использовать уникальные идентификаторы в соответствующих сертификатах. Приложения, соответствующие этому профилю, должны уметь анализировать уникальные идентификаторы и сравнивать их.

Определение ASN.1 для этого:

 issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL

 UniqueIdentifier  ::=  BIT STRING
 
Возвращает:
уникальный идентификатор издателя или null, если он отсутствует в сертификате.

getSubjectUniqueID

public abstract boolean[] getSubjectUniqueID()
Получает значение subjectUniqueID из сертификата.

Определение ASN.1 для этого:

 subjectUniqueID  [2]  IMPLICIT UniqueIdentifier OPTIONAL

 UniqueIdentifier  ::=  BIT STRING
 
Возвращает:
уникальный идентификатор субъекта или null, если он отсутствует в сертификате.

getKeyUsage

public abstract boolean[] getKeyUsage()
Получает булевый массив, представляющий биты расширения KeyUsage, (OID = 2.5.29.15). Расширение key usage определяет назначение (например, шифрование, подпись, подписание сертификата) ключа, содержащегося в сертификате. Определение ASN.1 для этого:
 KeyUsage ::= BIT STRING {
     digitalSignature        (0),
     nonRepudiation          (1),
     keyEncipherment         (2),
     dataEncipherment        (3),
     keyAgreement            (4),
     keyCertSign             (5),
     cRLSign                 (6),
     encipherOnly            (7),
     decipherOnly            (8) }
 
RFC 5280 рекомендует помечать его как критическое расширение, если оно используется.
Возвращает:
расширение KeyUsage этого сертификата, представленное массивом булевых значений. Порядок значений KeyUsage в массиве такой же, как и в определении ASN.1 выше. Массив будет содержать значение для каждого определённого выше KeyUsage. Если список KeyUsage, закодированный в сертификате, длиннее вышеперечисленного списка, он не будет усечён. Возвращает null, если этот сертификат не содержит расширения KeyUsage.

getExtendedKeyUsage

public List<String> getExtendedKeyUsage() throws CertificateParsingException
Получает неизменяемый список строк, представляющих идентификаторы OBJECT, поля ExtKeyUsageSyntax расширения extended key usage, (OID = 2.5.29.37). Оно указывает одно или несколько назначений, для которых сертифицированный открытый ключ может быть использован дополнительно или вместо основных назначений, указанных в поле расширения key usage. Определение ASN.1 для этого:
 ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId

 KeyPurposeId ::= OBJECT IDENTIFIER
 
Цели ключей могут быть определены любой организацией, имеющей в этом необходимость. Идентификаторы объектов, используемые для идентификации целей ключей, должны быть назначены в соответствии с IANA или ITU-T Rec. X.660 | ISO/IEC/ITU 9834-1.

Этот метод был добавлен в версию 1.4 платформы Java 2 Standard Edition. Для сохранения обратной совместимости с существующими поставщиками услуг, этот метод не abstract и он предоставляет реализацию по умолчанию. Подклассы должны переопределить этот метод с корректной реализацией.

Возвращает:
расширение ExtendedKeyUsage этого сертификата в виде неизменяемого списка идентификаторов объектов, представленных строками. Возвращает null, если этот сертификат не содержит расширения ExtendedKeyUsage.
Исключение:
CertificateParsingException - если расширение нельзя декодировать
С версии:
1.4

getBasicConstraints

public abstract int getBasicConstraints()
Получает длину пути ограничения сертификата из критического расширения BasicConstraints, (OID = 2.5.29.19).

Расширение базовых ограничений определяет, является ли субъект сертификата центром сертификации (CA) и как глубоко может существовать путь сертификации через этот CA. Поле pathLenConstraint (см. ниже) имеет смысл только если cA установлено в TRUE. В этом случае, оно задаёт максимальное количество сертификатов CA, которые могут следовать за этим сертификатом в пути сертификации. Значение ноль указывает, что за этим сертификатом в пути может следовать только сертификат конечного пользователя.

Определение ASN.1 для этого:

 BasicConstraints ::= SEQUENCE {
     cA                  BOOLEAN DEFAULT FALSE,
     pathLenConstraint   INTEGER (0..MAX) OPTIONAL }
 
Возвращает:
значение pathLenConstraint, если расширение BasicConstraints присутствует в сертификате и субъект сертификата является CA, в противном случае -1. Если субъект сертификата является CA и pathLenConstraint отсутствует, возвращается Integer.MAX_VALUE, чтобы указать, что нет ограничения на допустимую длину пути сертификации.

getSubjectAlternativeNames

public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException
Получает неизменяемую коллекцию альтернативных имён субъекта из расширения SubjectAltName, (OID = 2.5.29.17).

Определение ASN.1 расширения SubjectAltName такое:

 SubjectAltName ::= GeneralNames

 GeneralNames :: = SEQUENCE SIZE (1..MAX) OF GeneralName

 GeneralName ::= CHOICE {
      otherName                       [0]     OtherName,
      rfc822Name                      [1]     IA5String,
      dNSName                         [2]     IA5String,
      x400Address                     [3]     ORAddress,
      directoryName                   [4]     Name,
      ediPartyName                    [5]     EDIPartyName,
      uniformResourceIdentifier       [6]     IA5String,
      iPAddress                       [7]     OCTET STRING,
      registeredID                    [8]     OBJECT IDENTIFIER}
 

Если этот сертификат не содержит расширения SubjectAltName, возвращается null. В противном случае возвращается Collection, содержащий запись, представляющую каждое GeneralName включённое в расширение. Каждая запись представляет собой List, первая запись которой является Integer (тип имени, 0-8), а вторая запись — String или массив байтов (имя, в строковом или ASN.1 DER-закодированном виде соответственно).

Имена RFC 822, DNS и URI возвращаются как String с использованием устоявшихся строковых форматов для этих типов (в соответствии с ограничениями, указанными в RFC 5280). Имена адресов IPv4 возвращаются с использованием обозначения точки-тире. Имена адресов IPv6 возвращаются в формате "a1:a2:...:a8", где a1-a8 — шестнадцатеричные значения, представляющие восемь 16-битных частей адреса. Имена OID возвращаются как String в виде последовательности неотрицательных целых чисел, разделенных точками. Имена каталога (различительные имена) возвращаются в строковом формате RFC 2253. Для других имен, имён X.400, имён сторон EDI или любого другого типа имен не определён стандартный строковый формат. Они возвращаются как массивы байтов, содержащие ASN.1 DER-закодированную форму имени.

Обратите внимание, что возвращаемая коллекция Collection может содержать более одного имени одного типа. Также обратите внимание, что возвращаемая коллекция Collection неизменяемая, и любые записи, содержащие массивы байтов, клонируются для защиты от последующих изменений.

Этот метод был добавлен в версию 1.4 платформы Java 2 Platform Standard Edition. Для сохранения обратной совместимости с существующими поставщиками услуг этот метод не abstract и предоставляет реализацию по умолчанию. Подклассы должны переопределить этот метод с корректной реализацией.

Возвращает:
неизменяемую коллекцию Collection альтернативных имён субъекта (или null)
Исключение:
CertificateParsingException - если расширение нельзя декодировать
С версии:
1.4

getIssuerAlternativeNames

public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException
Получает неизменяемую коллекцию альтернативных имён издателя из расширения IssuerAltName, (OID = 2.5.29.18).

Определение ASN.1 расширения IssuerAltName такое:

 IssuerAltName ::= GeneralNames
 
Определение ASN.1 GeneralNames определено в getSubjectAlternativeNames.

Если этот сертификат не содержит расширение IssuerAltName, возвращается null. В противном случае возвращается Collection, содержащий запись, представляющую каждое GeneralName включённое в расширение. Каждая запись представляет собой List, первая запись которой является Integer (тип имени, 0-8), а вторая запись — String или массив байтов (имя, в строковом или ASN.1 DER-закодированном виде соответственно). Более подробную информацию о форматах, используемых для каждого типа имени, см. в методе getSubjectAlternativeNames.

Обратите внимание, что возвращаемая коллекция Collection может содержать более одного имени одного типа. Также обратите внимание, что возвращаемая коллекция Collection неизменяемая, и любые записи, содержащие массивы байтов, клонируются для защиты от последующих изменений.

Этот метод был добавлен в версию 1.4 платформы Java 2 Platform Standard Edition. Для сохранения обратной совместимости с существующими поставщиками услуг, этот метод не abstract и предоставляет реализацию по умолчанию. Подклассы должны переопределить этот метод с корректной реализацией.

Возвращает:
неизменяемую коллекцию Collection альтернативных имён издателя (или null)
Исключение:
CertificateParsingException - если расширение нельзя декодировать
С версии:
1.4

verify

public void verify(PublicKey key, Provider sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
Проверяет, был ли этот сертификат подписан с использованием закрытого ключа, соответствующего указанному открытому ключу. Этот метод использует движок проверки подписи, предоставленный указанным поставщиком. Обратите внимание, что указанный объект Provider не обязательно должен быть зарегистрирован в списке поставщиков. Этот метод был добавлен в версию 1.8 платформы Java Standard Edition. Для сохранения обратной совместимости с существующими поставщиками услуг, этот метод не abstract и предоставляет реализацию по умолчанию.
Переопределяет:
verify в классе Certificate
Параметры:
key - открытый ключ, используемый для выполнения проверки.
sigProvider - поставщик подписей.
Исключение:
NoSuchAlgorithmException - при недопустимых алгоритмах подписи.
InvalidKeyException - при некорректном ключе.
SignatureException - при ошибках подписи.
CertificateException - при ошибках кодирования.
UnsupportedOperationException - если метод не поддерживается
С версии:
1.8

© 1993, 2021, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/security/cert/X509Certificate.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API