Статус: Активный участник
Группы: Участники
Зарегистрирован: 10.02.2015(UTC) Сообщений: 37 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 7 раз
|
Здравствуйте! JCP 1.0.54 - 2.0 использовать не могу. Я подписываю на сервере документ по примерам так: Код: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;
}
А дальше я усовершенствую эту подпись до CAdES_X_Long_Type_1: Код:/**
* Усовершенствование CAdES-BES подписи до CAdES-X Long Type 1.
*
* @param signature Подпись для усовершенствования.
* @param file подписываемый файл.
* @param chain цепочка сертификатов.
* @param tsaAddress адрес службы штампов.
* @return усовершенствованная подпись
* @throws CAdESException /
* @throws IOException /
*/
public static byte[] enhanceSignature(final byte[] signature, final byte[] file,
final Collection<X509Certificate> chain, final String tsaAddress) throws CAdESException, IOException {
CAdESSignature cadesSignature = new CAdESSignature(signature, file, null);
LOG.debug("Start verify signature with chain size {}, {}", chain.size(), chain);
cadesSignature.verify(chain, null);
// Список всех подписантов в исходной подписи.
final Collection<SignerInformation> srcSignerInfos = new ArrayList<SignerInformation>();
for (CAdESSigner signer : cadesSignature.getCAdESSignerInfos()) {
srcSignerInfos.add(signer.getSignerInfo());
}
// 2. Усовершенствование подписи.
// Получаем только первую CAdES-BES подпись, усовершенствуем ее.
// Остальных не трогаем.
final CMSSignedData srcSignedData = cadesSignature.getSignedData();
final CAdESSigner srcSigner = cadesSignature.getCAdESSignerInfo(0);
// Исключаем ее из исходного списка, т.к. ее место займет усовершенствованная
// подпись.
srcSignerInfos.remove(srcSigner.getSignerInfo());
// Усовершенствуем CAdES-BES до CAdES-X Long Type 1.
srcSigner.enhance(JCP.PROVIDER_NAME, JCP.GOST_DIGEST_OID, chain,
tsaAddress, CAdESType.CAdES_X_Long_Type_1);
// Подписант усовершенствованной подписи.
final SignerInformation enhSigner = srcSigner.getSignerInfo();
// Добавляем его в исходный список подписантов.
srcSignerInfos.add(enhSigner);
// Список подписантов.
final SignerInformationStore dstSignerInfoStore = new SignerInformationStore(srcSignerInfos);
// Обновляем исходную подпись c ее начальным списком подписантов на тот же,
// но с первым подписантом с усовершенствованной подписью.
final CMSSignedData dstSignedData =
CMSSignedData.replaceSigners(srcSignedData, dstSignerInfoStore);
// 3. Проверка усовершенствованной подписи.
// Проверяем подпись.
cadesSignature = new CAdESSignature(dstSignedData.getEncoded(), file, null);
cadesSignature.verify(chain, null);
printSignatureInfo(cadesSignature);
return cadesSignature.getSignedData().getEncoded();
}
Вопрос: если у меня есть только хеш (isExternalDigest = true), могу ли я усовершенствовать подпись?
|