Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline ApTeM  
#1 Оставлено : 3 июля 2008 г. 22:12:25(UTC)
ApTeM

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.07.2008(UTC)
Сообщений: 5

Стоит задача получения PKCS#7 сообщения, извлечение из него сертификата открытого ключа и сравнение полученного сертификата с имеющимся сертификатом. На основе примеров были написаны два метода, один из которых делает обертку сообщения, а другой ее снимает и извлекает сертификат. В процессе отладки обнаружилось, что после кодирования сообщения в набор байт в соответствие с кодировкой Ans1 Ber, и последующего его декодирования и извлечения сертификата, закодированное значение сертификата не совпадает с закодированным значением исходного сертификата, над которым не производились все вышеперечисленные манипуляции. Значения сертификатов различаются незначительно, буквально на несколько байт и оба могут быть преобразованы в X.509-сертификат класса java.security.cert.X509Certificate. При этом, хотя значения toString() этих двух сертификатов в точности совпадают, equals для них равен false. Ниже приведен код, поясняющий ситуацию:

Код:

// все данные сообщения
final ContentInfo allData = new ContentInfo();
// подписанные данные
final SignedData cms = new SignedData();
// идентификатор криптографической хэш-функции
final DigestAlgorithmIdentifier digestIdentifier;
// перекодированный сертификат
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate;
// имя стороны, выдавшей сертификат
final Name name;
final CertificateChoices cerChoices;
// буфер для кодирования сообщения в Ans1.Ber
final Asn1BerEncodeBuffer asnBuf;

allData.content = cms; // содержимое Cryprographic Message Syntax
allData.contentType = new Asn1ObjectIdentifier(new OID(PKCS7_OID_SIGNED).value);

// установка параметров данных
cms.version = new CMSVersion(CMS_VERSION);
cms.digestAlgorithms = new DigestAlgorithmIdentifiers(DIGEST_NUM);
digestIdentifier = new DigestAlgorithmIdentifier(new OID(OID_GOST_3411_HASH).value);
digestIdentifier.parameters = new Asn1Null();
cms.digestAlgorithms.elements[0] = digestIdentifier;
		
// инкапсулировать в сообщение данные
cms.encapContentInfo =
new EncapsulatedContentInfo(new Asn1ObjectIdentifier(
 new OID(PKCS7_OID_DATA).value),
 new Asn1OctetString(data)
);
		
// установить информацию о сертификате
certificate = new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
certificate.decode(new Asn1BerDecodeBuffer(pubCert.getEncoded())); [b]// pubCert - сертификат открытого ключа[/b]
cerChoices = new CertificateChoices();
cerChoices.set_certificate(certificate);
cms.certificates = new CertificateSet(CERT_SET_SIZE);
cms.certificates.elements = new CertificateChoices[] { cerChoices };

[b]// далее идет код установки информации о подписчике (опущен)...[/b]

// ...
// ...

// закодировать сообщение и вернуть как массив байтов
asnBuf = new Asn1BerEncodeBuffer();
allData.encode(asnBuf, true); // ?? что означает второй параметр

[b]// отладочный код проверки идентичности сертификата[/b]

ContentInfo dAllData = new ContentInfo();
dAllData.decode(new Asn1BerDecodeBuffer(asnBuf.getMsgCopy()));
SignedData dCms = (SignedData) dAllData.content;
final Asn1BerEncodeBuffer dEncBuf = new Asn1BerEncodeBuffer();
dCms.certificates.elements[0].encode(dEncBuf);
byte[] dCertEncoded = dEncBuf.getMsgCopy();
java.security.cert.X509Certificate x509 = (java.security.cert.X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(dCertEncoded));

boolean dIsEquaEquals = pubCert.equals(x509);  // false
boolean dIsEqualString = pubCert.toString().equals(x509.toString());  // true
boolean dIsEqualByte = dCertEncoded.equals(pubCert.getEncoded());    // false




Прошу подсказать, как выйти из этой ситуации. Как правильно сравнить сертификаты и почему происходит изменение сертификата.

Отредактировано пользователем 3 июля 2008 г. 22:14:44(UTC)  | Причина: Не указана

Offline ApTeM  
#2 Оставлено : 7 июля 2008 г. 14:18:56(UTC)
ApTeM

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.07.2008(UTC)
Сообщений: 5

И еще вопрос такой. Как извлечь информацию об имени принципала и серийном номере сертификата подписчика из SignerInfo.sid?

Всем заранее спасибо за ответы.
Offline Ольга  
#3 Оставлено : 7 июля 2008 г. 16:13:57(UTC)
Ольга

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.01.2008(UTC)
Сообщений: 207

Поблагодарили: 3 раз в 3 постах
ApTeM написал:
Как извлечь информацию об имени принципала и серийном номере сертификата подписчика из SignerInfo.sid?

...
final SignedData cms = (SignedData) all.content;
Asn1BerEncodeBuffer encBuf = new Asn1BerEncodeBuffer();
cms.signerInfos.elements[0].sid.encode(encBuf);
final Asn1BerDecodeBuffer decBuf =
new Asn1BerDecodeBuffer(encBuf.getMsgCopy());
IssuerAndSerialNumber isn = new IssuerAndSerialNumber();
isn.decode(decBuf);
//name
encBuf.reset();
isn.issuer.encode(encBuf);
X500Principal name = new X500Principal(encBuf.getMsgCopy());
//serial number
encBuf.reset();
isn.serialNumber.encode(encBuf);
SerialNumber sn = new SerialNumber(encBuf.getInputStream());
Offline Ольга  
#4 Оставлено : 7 июля 2008 г. 19:07:55(UTC)
Ольга

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.01.2008(UTC)
Сообщений: 207

Поблагодарили: 3 раз в 3 постах
Сертификаты правильнее сравнивать по отпечатку: hex-строка хеша сертификата (алгоритм SHA1)
Offline ApTeM  
#5 Оставлено : 7 июля 2008 г. 22:53:12(UTC)
ApTeM

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.07.2008(UTC)
Сообщений: 5

Спасибо за ответ. :) Вы имеете ввиду по подписи в сертификатах?
Offline Ольга  
#6 Оставлено : 8 июля 2008 г. 14:19:29(UTC)
Ольга

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.01.2008(UTC)
Сообщений: 207

Поблагодарили: 3 раз в 3 постах
нет не по подписи, а по хешу всего сертификата:
Код:
Certificate cert;
final byte[] encCertInfo = cert.getEncoded();
final MessageDigest md = MessageDigest.getInstance("SHA1");
final byte[] digest = md.digest(encCertInfo);
результат: toHexString(digest);


ps: если в сертификате время не приведено к GMT, то сертификат при закодировании раскодировании может измениться...
такое время раньше проставлялось при генерировании самоподписанного сертификата в JCP, но это уже давно исправлено.

Отредактировано пользователем 8 июля 2008 г. 19:25:44(UTC)  | Причина: Не указана

Offline ApTeM  
#7 Оставлено : 8 июля 2008 г. 22:34:19(UTC)
ApTeM

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.07.2008(UTC)
Сообщений: 5

А в чем принципиальная разница между побайтовым сравнением и отпечатком? Или это так принято?

Отпечатки будут не равны, конечно.

Цитата:

ps: если в сертификате время не приведено к GMT, то сертификат при закодировании раскодировании может измениться...
такое время раньше проставлялось при генерировании самоподписанного сертификата в JCP, но это уже давно исправлено.


Хотите сказать, что в JCP нет ошибок, связанных с кодированием-декодированием сертификатов?
Offline Ольга  
#8 Оставлено : 9 июля 2008 г. 14:25:13(UTC)
Ольга

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.01.2008(UTC)
Сообщений: 207

Поблагодарили: 3 раз в 3 постах
ApTeM написал:
А в чем принципиальная разница между побайтовым сравнением и отпечатком? Или это так принято?

так принято

ApTeM написал:
Хотите сказать, что в JCP нет ошибок, связанных с кодированием-декодированием сертификатов?

если сертификат нормальный, то и ошибок возникать не должно
thanks 1 пользователь поблагодарил Ольга за этот пост.
pshevchuk оставлено 09.11.2015(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.