Статус: Новичок
Группы: Участники
Зарегистрирован: 01.11.2022(UTC) Сообщений: 1 Откуда: Rostov-on-Don
|
При создании подписи на основе модифицированного примера из jcp-2.0.40035\Doc\sample-source\CMS_samples\DetachedSignatureFileExample.java и jcp-2.0.40035\Doc\sample-source\CMS_samples\CMS.java и проверке ее внутренним методом на валидность получаем валидную подпись. А вот при проверке на сайте https://crypto.kontur.ru/verify#resultполучаем сообщение об ошибке : Подпись не подтверждена. Файл был модифицирован или подпись не соответствует файлу. Помогите пожалуйста разобраться Код:
package utils.CMS;
.....
public class DetachedSignatureFileExample {
public static final String fileName = "C:\\eClinic\\test.pdf";
public static final String alias = "?????????????";
public static final char[] password = "********".toCharArray();
public static void main(String[] args) throws Exception {
// Грузим хранилище.
KeyStore keyStore = KeyStore.getInstance(JCP.HD_STORE_NAME);
keyStore.load(null, null);
// Получаем ключ и сертификат.
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password);
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);
String algorithm = JCP.GOST_SIGN_2012_256_NAME;
// Создаем подпись, при этом сначала получаем хеш с файла.
byte[] data = VUtl.readFile( fileName);
Signature signature = Signature.getInstance(algorithm );
signature.initSign(privateKey);
signature.update( data);
// Создаем подпись.
byte[] cms = CMS.createCMS(data, signature.sign(), certificate, true);
VUtl.writeToFile( cms, fileName+".sig");
// Проверяем подпись, снова сначала получаем хеш с файла.
signature = Signature.getInstance( algorithm );
signature.initVerify(certificate.getPublicKey());
signature.update( data);
verify(cms, certificate, signature);
}
public static void verify(byte[] buffer, X509Certificate cert, Signature signature)
throws Exception {
int i;
final Asn1BerDecodeBuffer asnBuf = new Asn1BerDecodeBuffer(buffer);
final ContentInfo all = new ContentInfo();
all.decode(asnBuf);
if (!new OID(CMStools.STR_CMS_OID_SIGNED).eq(all.contentType.value)) {
throw new Exception("Not supported");
}
final SignedData cms = (SignedData) all.content;
if (cms.version.value != 1) {
throw new Exception("Incorrect version");
}
if (!new OID(CMStools.STR_CMS_OID_DATA).eq(cms.encapContentInfo.eContentType.value)) {
throw new Exception("Nested not supported");
}
OID digestOid = null;
DigestAlgorithmIdentifier a = new DigestAlgorithmIdentifier(new OID(CMStools.DIGEST_OID_2012_256).value);
for (i = 0; i < cms.digestAlgorithms.elements.length; i++) {
if (cms.digestAlgorithms.elements[i].algorithm.equals(a.algorithm)) {
digestOid =
new OID(cms.digestAlgorithms.elements[i].algorithm.value);
break;
}
}
if (digestOid == null) {
throw new Exception("Unknown digest");
}
int pos = -1;
for (i = 0; i < cms.certificates.elements.length; i++) {
final Asn1BerEncodeBuffer encBuf = new Asn1BerEncodeBuffer();
cms.certificates.elements[i].encode(encBuf);
final byte[] in = encBuf.getMsgCopy();
X509Certificate tmp = (X509Certificate) CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(in));
System.out.println(tmp.getSubjectDN());
System.out.println(cert.getSubjectDN());
if (Arrays.equals(in, cert.getEncoded())) {
pos = i;
break;
}
}
if (pos == -1) {
throw new Exception("Not signed on certificate.");
}
final SignerInfo info = cms.signerInfos.elements[pos];
if (info.version.value != 1) {
throw new Exception("Incorrect version");
}
if (!digestOid.equals(new OID(info.digestAlgorithm.algorithm.value))) {
throw new Exception("Not signed on certificate.");
}
final byte[] sign = info.signature.value;
// check
final boolean checkResult = signature.verify(sign);
if (checkResult) {
if (CMStools.logger != null) {
CMStools.logger.info("Valid signature");
}
}
else {
throw new Exception("Invalid signature.");
}
}
/////////////////////////////////////////////////////////////////////////////////////////
package utils.CMS;
.............................
public class CMS {
.............................
public static byte[] createCMS(
byte[] data
, byte[] sign
, Certificate cert
, boolean detached
) throws Exception {
return createCMSEx(
data
, sign
, cert
, detached
, CMStools.DIGEST_OID_2012_256
, CMStools.SIGN_OID_2012_256
, CMStools.DIGEST_ALG_NAME_2012_256
, JCP.PROVIDER_NAME
);
}
/**
* createCMS
*
* @param data : bytes[] of file for signed
* @param sign sign
* @param cert cert
* @param detached detached signature
* @param digestOid digest algorithm OID (to append to CMS)
* @param signOid signature algorithm OID (to append to CMS)
* @return byte[]
* @throws Exception e
* @since 2.0
*/
public static byte[] createCMSEx(
byte[] data
, byte[] sign
, Certificate cert
, boolean detached
, String digestOid
, String signOid
, String digestAlg
, String providerName
) throws Exception {
//create hashCMS // Формируем контекст подписи формата PKCS7.
final ContentInfo all = new ContentInfo();
all.contentType = new Asn1ObjectIdentifier( new OID(CMStools.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 (detached) {
cms.encapContentInfo = new EncapsulatedContentInfo( new Asn1ObjectIdentifier(
new OID(CMStools.STR_CMS_OID_DATA).value),null);
}
else {
cms.encapContentInfo = new EncapsulatedContentInfo( new Asn1ObjectIdentifier(
new OID(CMStools.STR_CMS_OID_DATA).value),new Asn1OctetString(data));
}
// certificate // Добавляем сертификат подписи.
cms.certificates = new CertificateSet(1);
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate = new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
final Asn1BerDecodeBuffer decodeBuffer = new Asn1BerDecodeBuffer(cert.getEncoded());
certificate.decode(decodeBuffer);
cms.certificates.elements = new CertificateChoices[1];
cms.certificates.elements[0] = new CertificateChoices();
cms.certificates.elements[0].set_certificate(certificate);
// signer info // Добавялем информацию о подписанте.
cms.signerInfos = new SignerInfos(1);
cms.signerInfos.elements[0] = new SignerInfo();
cms.signerInfos.elements[0].version = new CMSVersion(1);
cms.signerInfos.elements[0].sid = new SignerIdentifier();
final byte[] encodedName = ((X509Certificate) cert).getIssuerX500Principal().getEncoded();
final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
final Name name = new Name();
name.decode(nameBuf);
final CertificateSerialNumber num = new CertificateSerialNumber(((X509Certificate) cert).getSerialNumber());
cms.signerInfos.elements[0].sid.set_issuerAndSerialNumber(new IssuerAndSerialNumber(name, num));
cms.signerInfos.elements[0].digestAlgorithm = new DigestAlgorithmIdentifier(new OID(digestOid).value);
cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signatureAlgorithm = new SignatureAlgorithmIdentifier(new OID(signOid).value);
cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signature = new SignatureValue(sign);
////+++++++++++++++++
//signedAttributes
final int kmax = 4;
cms.signerInfos.elements[0].signedAttrs = new SignedAttributes(kmax);
//-contentType
int k = 0;
cms.signerInfos.elements[0].signedAttrs.elements[k] = new Attribute(
new OID(CMStools.STR_CMS_OID_CONT_TYP_ATTR).value
,new Attribute_values(1)
);
final Asn1Type conttype = new Asn1ObjectIdentifier( new OID(CMStools.STR_CMS_OID_DATA).value);
cms.signerInfos.elements[0].signedAttrs.elements[k].values.elements[0] = conttype;
//-Time
k += 1;
cms.signerInfos.elements[0].signedAttrs.elements[k] =
new Attribute(new OID(CMStools.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[0].signedAttrs.elements[k].values.elements[0] = time.getElement();
//-message digest !!! ?????????????????
k += 1;
cms.signerInfos.elements[0].signedAttrs.elements[k] = new Attribute(
new OID(CMStools.STR_CMS_OID_DIGEST_ATTR).value
,new Attribute_values(1));
final byte[] messageDigestBlob;
if (detached) {
messageDigestBlob = CMStools.digestm(data, digestAlg, providerName);
} // if
else {
messageDigestBlob = CMStools.digestm(cms.encapContentInfo.eContent.value,digestAlg, providerName);
} // else
final Asn1Type messageDigest = new Asn1OctetString( messageDigestBlob);
cms.signerInfos.elements[0].signedAttrs.elements[k].values.elements[0] = messageDigest;
////*******
// Добавление signingCertificateV2 в подписанные аттрибуты, чтобы подпись
// стала похожа на CAdES-BES.
// Собственно, аттрибут с OID'ом id_aa_signingCertificateV2.
k += 1;
cms.signerInfos.elements[0].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(
CMStools.digestm(cert.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[0].signedAttrs.elements[k].values.elements[0] = signingCertificateV2;
////=================
// encode // Получаем закодированную подпись.
final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();
all.encode(asnBuf, true);
return asnBuf.getMsgCopy();
}
.......
}
|