Статус: Новичок
Группы: Участники
Зарегистрирован: 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)
| Причина: Не указана
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 03.07.2008(UTC) Сообщений: 5
|
И еще вопрос такой. Как извлечь информацию об имени принципала и серийном номере сертификата подписчика из SignerInfo.sid?
Всем заранее спасибо за ответы.
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 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());
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 23.01.2008(UTC) Сообщений: 207
Поблагодарили: 3 раз в 3 постах
|
Сертификаты правильнее сравнивать по отпечатку: hex-строка хеша сертификата (алгоритм SHA1)
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 03.07.2008(UTC) Сообщений: 5
|
Спасибо за ответ. :) Вы имеете ввиду по подписи в сертификатах?
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 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)
| Причина: Не указана
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 03.07.2008(UTC) Сообщений: 5
|
А в чем принципиальная разница между побайтовым сравнением и отпечатком? Или это так принято? Отпечатки будут не равны, конечно. Цитата: ps: если в сертификате время не приведено к GMT, то сертификат при закодировании раскодировании может измениться... такое время раньше проставлялось при генерировании самоподписанного сертификата в JCP, но это уже давно исправлено.
Хотите сказать, что в JCP нет ошибок, связанных с кодированием-декодированием сертификатов?
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 23.01.2008(UTC) Сообщений: 207
Поблагодарили: 3 раз в 3 постах
|
ApTeM написал:А в чем принципиальная разница между побайтовым сравнением и отпечатком? Или это так принято? так принято ApTeM написал:Хотите сказать, что в JCP нет ошибок, связанных с кодированием-декодированием сертификатов? если сертификат нормальный, то и ошибок возникать не должно
|
1 пользователь поблагодарил Ольга за этот пост.
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close