Статус: Активный участник
Группы: Участники
Зарегистрирован: 10.02.2015(UTC) Сообщений: 37 Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 7 раз
|
Автор: afev Программно, с помощью класса Decoder (в пакете ru.CryptoPro.JCP.tools или ru.CryptoPro.JCP.Util). Все-таки хотелось бы уточнить: 1. Вот тут было предположение, что подпись не проверяется на гос услугах, так как формат подпись не CAdES, а CMS. Сейчас я использую пример (из примеров jcp): Код:public static byte[] createHashCMSEx(final byte[] data, final boolean isExternalDigest,
final PrivateKey[] keys, final Certificate[] certs, final String path,
final boolean detached,
final boolean addSignCertV2, final String digestOid, final String signOid,
final String digestAlg,
final String signAlg, final String providerName) throws Exception {
//create hashCMS
final ContentInfo all = new ContentInfo();
all.contentType = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_SIGNED).value);
final SignedData cms = new SignedData();
all.content = cms;
cms.version = new CMSVersion(1);
// digest
cms.digestAlgorithms = new DigestAlgorithmIdentifiers(1);
final DigestAlgorithmIdentifier a = new DigestAlgorithmIdentifier(new OID(digestOid).value);
a.parameters = new Asn1Null();
cms.digestAlgorithms.elements[0] = a;
// Нельзя сделать подпись совмещенной, если нет данных, а есть только хеш с них.
if (isExternalDigest && !detached) {
throw new Exception("Signature is attached but external digest is available only (not data)");
}
if (detached) {
cms.encapContentInfo = new EncapsulatedContentInfo(
new Asn1ObjectIdentifier(new OID(STR_CMS_OID_DATA).value), null);
} else {
cms.encapContentInfo = new EncapsulatedContentInfo(new Asn1ObjectIdentifier(
new OID(STR_CMS_OID_DATA).value), new Asn1OctetString(data));
}
// certificates
final int nCerts = certs.length;
cms.certificates = new CertificateSet(nCerts);
cms.certificates.elements = new CertificateChoices[nCerts];
for (int i = 0; i < cms.certificates.elements.length; i++) {
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate =
new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
final Asn1BerDecodeBuffer decodeBuffer = new Asn1BerDecodeBuffer(certs[i].getEncoded());
certificate.decode(decodeBuffer);
cms.certificates.elements[i] = new CertificateChoices();
cms.certificates.elements[i].set_certificate(certificate);
}
// Signature.getInstance
final Signature signature = Signature.getInstance(signAlg, providerName);
byte[] sign;
// signer infos
final int nsign = keys.length;
cms.signerInfos = new SignerInfos(nsign);
for (int i = 0; i < cms.signerInfos.elements.length; i++) {
cms.signerInfos.elements[i] = new SignerInfo();
cms.signerInfos.elements[i].version = new CMSVersion(1);
cms.signerInfos.elements[i].sid = new SignerIdentifier();
final byte[] encodedName = ((X509Certificate) certs[i]).getIssuerX500Principal().getEncoded();
final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
final Name name = new Name();
name.decode(nameBuf);
final CertificateSerialNumber num = new CertificateSerialNumber(((X509Certificate) certs[i]).getSerialNumber());
cms.signerInfos.elements[i].sid.set_issuerAndSerialNumber(new IssuerAndSerialNumber(name, num));
cms.signerInfos.elements[i].digestAlgorithm = new DigestAlgorithmIdentifier(new OID(digestOid).value);
cms.signerInfos.elements[i].digestAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[i].signatureAlgorithm = new SignatureAlgorithmIdentifier(new OID(signOid).value);
cms.signerInfos.elements[i].signatureAlgorithm.parameters = new Asn1Null();
//signedAttributes
final int kmax = addSignCertV2 ? 4 : 3;
cms.signerInfos.elements[i].signedAttrs = new SignedAttributes(kmax);
//-contentType
int k = 0;
cms.signerInfos.elements[i].signedAttrs.elements[k] =
new Attribute(new OID(STR_CMS_OID_CONT_TYP_ATTR).value, new Attribute_values(1));
final Asn1Type conttype = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_DATA).value);
cms.signerInfos.elements[i].signedAttrs.elements[k].values.elements[0] = conttype;
//-Time
k += 1;
cms.signerInfos.elements[i].signedAttrs.elements[k] =
new Attribute(new OID(STR_CMS_OID_SIGN_TYM_ATTR).value, new Attribute_values(1));
final Time time = new Time();
final Asn1UTCTime utcTime = new Asn1UTCTime();
//текущая дата с календаря
utcTime.setTime(Calendar.getInstance());
time.set_utcTime(utcTime);
cms.signerInfos.elements[i].signedAttrs.elements[k].values.elements[0] =
time.getElement();
//-message digest
k += 1;
cms.signerInfos.elements[i].signedAttrs.elements[k] =
new Attribute(new OID(STR_CMS_OID_DIGEST_ATTR).value, new Attribute_values(1));
final byte[] messageDigestBlob;
// Если вместо данных у нас хеш, то сразу его передаем, ничего не вычисляем.
if (isExternalDigest) {
messageDigestBlob = data;
} else {
if (detached) {
messageDigestBlob = digestm(data, digestAlg, providerName);
} else {
messageDigestBlob = digestm(cms.encapContentInfo.eContent.value, digestAlg, providerName);
}
}
final Asn1Type messageDigest = new Asn1OctetString(messageDigestBlob);
cms.signerInfos.elements[i].signedAttrs.elements[k].values.elements[0] = messageDigest;
// Добавление signingCertificateV2 в подписанные аттрибуты, чтобы подпись стала похожа на CAdES-BES.
if (addSignCertV2) {
// Собственно, аттрибут с OID'ом id_aa_signingCertificateV2.
k += 1;
cms.signerInfos.elements[i].signedAttrs.elements[k] = new Attribute(
new OID(ALL_PKIX1Explicit88Values.id_aa_signingCertificateV2).value, new Attribute_values(1));
// Идентификатор алгоритма хеширования, который использовался для
// хеширования контекста сертификата ключа подписи.
final DigestAlgorithmIdentifier digestAlgorithmIdentifier =
new DigestAlgorithmIdentifier(new OID(digestOid).value);
// Хеш сертификата ключа подписи.
final CertHash certHash = new CertHash(digestm(certs[i].getEncoded(), digestAlg, providerName));
// Issuer name из сертификата ключа подписи.
GeneralName generalName = new GeneralName();
generalName.set_directoryName(name);
GeneralNames generalNames = new GeneralNames();
generalNames.elements = new GeneralName[1];
generalNames.elements[0] = generalName;
// Комбинируем издателя и серийный номер.
IssuerSerial issuerSerial = new IssuerSerial(generalNames, num);
ESSCertIDv2 essCertIDv2 = new ESSCertIDv2(digestAlgorithmIdentifier, certHash, issuerSerial);
_SeqOfESSCertIDv2 essCertIDv2s = new _SeqOfESSCertIDv2(1);
essCertIDv2s.elements = new ESSCertIDv2[1];
essCertIDv2s.elements[0] = essCertIDv2;
// Добавляем сам аттрибут.
SigningCertificateV2 signingCertificateV2 = new SigningCertificateV2(essCertIDv2s);
cms.signerInfos.elements[i].signedAttrs.elements[k].values.elements[0] = signingCertificateV2;
}
//signature
Asn1BerEncodeBuffer encBufSignedAttr = new Asn1BerEncodeBuffer();
cms.signerInfos.elements[i].signedAttrs.encode(encBufSignedAttr);
final byte[] hsign = encBufSignedAttr.getMsgCopy();
signature.initSign(keys[i]);
signature.update(hsign);
sign = signature.sign();
cms.signerInfos.elements[i].signature = new SignatureValue(sign);
}
// encode
final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();
all.encode(asnBuf, true);
final byte[] msgCopy = asnBuf.getMsgCopy();
if (path != null) {
Array.writeFile(path, msgCopy);
}
return msgCopy;
}
и в комментарии указано, что "Добавление signingCertificateV2 в подписанные аттрибуты, чтобы подпись стала похожа на CAdES-BES.". То есть формат подписи все равно остается CMS? И причина того, что проверка на госуслугах может не проходить все та же - не тот формат? 2. Если в указанном примере подпись все равно создается в формате CMS, то подскажите, пожалуйста, как создать подпись в формате CAdES при условии использования JCP 1.0.54 (повторюсь, что версия 2.0 не подходит, так как она не сертифицирована).
|