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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline somenickname123  
#1 Оставлено : 29 июля 2021 г. 7:55:03(UTC)
somenickname123

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

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

Здравствуйте.
Появилась задача добавить время создания подписи. Пример сравнения подписей со смежной системой:
[img=https://cloud.mail.ru/public/YemC/twCmbiGYf]Отсутствующее время создания подписи[/img]

Подпись отсоединенная в формате pkcs7. Метод, возвращающий бинарник подписи:
Код:
@Override
    public byte[] createCMS(String timeStampServerUrl, byte[] content, X509Certificate x509Certificate, byte[] timestamp, byte[] signature) throws BaseSystemException {
        try {
            LOGGER.info("INFO START public byte[] createCMS(String timeStampServerUrl, byte[] content, X509Certificate x509Certificate, byte[] timestamp, byte[] signature) throws BaseSystemException Start");
            LOGGER.info("timeStampServerUrl: " + timeStampServerUrl);

            // выбираем из сертификата информацию для формирования подписи
            String AlgInCert = x509Certificate.getPublicKey().getAlgorithm();

            if (AlgInCert == JCP.GOST_EL_DEGREE_NAME) {
                DIGEST_OID = JCP.GOST_DIGEST_OID;
                SIGN_OID = JCP.GOST_EL_KEY_OID;
                LOGGER.info("DIGEST_OID = JCP.GOST_DIGEST_OID(1.2.643.2.2.9), SIGN_OID = JCP.GOST_EL_KEY_OID(1.2.643.2.2.19)");

            } else if (AlgInCert == JCP.GOST_EL_2012_256_NAME) {
                DIGEST_OID = JCP.GOST_DIGEST_2012_256_OID;
                SIGN_OID = JCP.GOST_PARAMS_SIG_2012_256_KEY_OID;
                LOGGER.info("DIGEST_OID = JCP.GOST_DIGEST_2012_256_OID(1.2.643.7.1.1.2.2), SIGN_OID = JCP.GOST_PARAMS_SIG_2012_256_KEY_OID(1.2.643.7.1.1.1.1)");

            } else if (AlgInCert == JCP.GOST_EL_2012_512_NAME) {
                DIGEST_OID = JCP.GOST_DIGEST_2012_512_OID;
                SIGN_OID = JCP.GOST_PARAMS_SIG_2012_512_KEY_OID;
                LOGGER.info("JCP.GOST_DIGEST_2012_512_OID(1.2.643.7.1.1.2.3), SIGN_OID = JCP.GOST_PARAMS_SIG_2012_512_KEY_OID(1.2.643.7.1.1.1.2)");

            } else {
                LOGGER.info("EXCEPTION INFO in public byte[] createCMS Excetion"
                        + "Unknown Algorithm in cert was:" + AlgInCert);
                throw new BaseSystemException(Message.BASE_ERROR);
            }

            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(DIGEST_OID).value);
            a.parameters = new Asn1Null();
            cms.digestAlgorithms.elements[0] = a;

            Asn1OctetString asn1OctetString = null;
            if (content != null)
                asn1OctetString = new Asn1OctetString(content);
            cms.encapContentInfo = new EncapsulatedContentInfo(
                    new Asn1ObjectIdentifier(
                            new OID(STR_CMS_OID_DATA).value),
                    asn1OctetString);

            // certificate
            cms.certificates = new CertificateSet(1);
            final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate = new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
            Asn1BerDecodeBuffer decodeBuffer = new Asn1BerDecodeBuffer(x509Certificate.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();
            //insert timestamp

            LOGGER.info("INFO START public byte[] createCMS insert TIMESTAMP Start");
            if (timestamp != null && timestamp.length > 0) {
                Asn1ObjectIdentifier unsignedObjId = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_UNSIGNED_ATTR).value);
                cms.signerInfos.elements[0].unsignedAttrs = new UnsignedAttributes(1);
                cms.signerInfos.elements[0].unsignedAttrs.elements[0] = new Attribute(unsignedObjId, new Attribute_values(1));

                //ASN1InputStream aIn = new ASN1InputStream(resp);
                //aIn.readObject().toASN1Primitive()
                ru.CryptoPro.JCP.ASN.PKIXTSP.TimeStampResp tsp = new ru.CryptoPro.JCP.ASN.PKIXTSP.TimeStampResp();
                decodeBuffer = new Asn1BerDecodeBuffer(timestamp);
                tsp.decode(decodeBuffer);
                cms.signerInfos.elements[0].unsignedAttrs.elements[0].values.elements[0] = tsp.timeStampToken;
            }
            LOGGER.info("Timestamp: " + timestamp.toString());

            LOGGER.info("public byte[] createCMS insert TIMESTAMP End");

            final byte[] encodedName = (x509Certificate).getIssuerX500Principal().getEncoded();
            final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
            final Name name = new Name();
            name.decode(nameBuf);

            final CertificateSerialNumber num = new CertificateSerialNumber((x509Certificate).getSerialNumber());
            cms.signerInfos.elements[0].sid.set_issuerAndSerialNumber(new IssuerAndSerialNumber(name, num));
            cms.signerInfos.elements[0].digestAlgorithm = new DigestAlgorithmIdentifier(new OID(DIGEST_OID).value);
            cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
            cms.signerInfos.elements[0].signatureAlgorithm = new SignatureAlgorithmIdentifier(new OID(SIGN_OID).value);
            cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
            cms.signerInfos.elements[0].signature = new SignatureValue(signature);
            // encode

            LOGGER.info("Start final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer()");
            LOGGER.info("Start final Asn1BerEncodeBuffer CMS was:" + cms
                    + "/n" + " cms.signerInfos.elements[0].digestAlgorithm.toString()" + cms.signerInfos.elements[0].digestAlgorithm.toString());


            LOGGER.info("final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer()");
            final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();

            LOGGER.info("all.encode(asnBuf, true)");

            all.encode(asnBuf, true);

            LOGGER.info(String.format("return asnBuf.getMsgCopy(): %s", asnBuf.getMsgCopy().toString()));

            return asnBuf.getMsgCopy();
}


Используется библиотеки bouncycastle 1.49 и от cryptopro jcp 2.0.40035. Дерево зависимостей:
[img=https://cloud.mail.ru/public/MCFg/AjL2UVCZP]Дерево зависимостей[/img]

Как добавить время создания подписи? Можно дозаполнить параметр какой-нибудь или нужна другая реализация?
Позволит ли текущий библиотечный набор реализовать требование?


Код легаси с потерянным контролем над кодовой базой. Опыт работы с подписями минимальный. Буду благодарен за советы, полезные ссылки (желательно в разрезе текущей задачи с такими же входными данными)
Offline Евгений Афанасьев  
#2 Оставлено : 29 июля 2021 г. 13:21:28(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,494
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 583 раз в 554 постах
Здравствуйте.
Если имеется в виду подписанный атрибут SigningTime, то в примере CMSSign пакета CMS_samples в samples-sources.jar есть кусок:
Код:

        //-Time
        k += 1;
        cms.signerInfos.elements[i + infos.length].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[i + infos
            .length].signedAttrs.elements[k].values.elements[0] =
            time.getElement();
Offline somenickname123  
#3 Оставлено : 2 августа 2021 г. 13:43:54(UTC)
somenickname123

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

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

Благодарю, но проблема не ушла.
Использовал частично решение, добавил следующий код:
Код:
Asn1ObjectIdentifier signedObjId = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_SIGNING_TIME).value);
                cms.signerInfos.elements[0].signedAttrs = new SignedAttributes(1);
                cms.signerInfos.elements[0].signedAttrs.elements[0] = new Attribute(signedObjId, 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[0].values.elements[0] = time.getElement();

Теперь код метода стал таким:
Код:
@Override
    public byte[] createCMS(String timeStampServerUrl, byte[] content, X509Certificate x509Certificate, byte[] timestamp, byte[] signature) throws BaseSystemException {
        try {
            LOGGER.info("INFO START public byte[] createCMS(String timeStampServerUrl, byte[] content, X509Certificate x509Certificate, byte[] timestamp, byte[] signature) throws BaseSystemException Start");
            LOGGER.info("timeStampServerUrl: " + timeStampServerUrl);

            // выбираем из сертификата информацию для формирования подписи
            String AlgInCert = x509Certificate.getPublicKey().getAlgorithm();

            if (AlgInCert == JCP.GOST_EL_DEGREE_NAME) {
                DIGEST_OID = JCP.GOST_DIGEST_OID;
                SIGN_OID = JCP.GOST_EL_KEY_OID;
                LOGGER.info("DIGEST_OID = JCP.GOST_DIGEST_OID(1.2.643.2.2.9), SIGN_OID = JCP.GOST_EL_KEY_OID(1.2.643.2.2.19)");

            } else if (AlgInCert == JCP.GOST_EL_2012_256_NAME) {
                DIGEST_OID = JCP.GOST_DIGEST_2012_256_OID;
                SIGN_OID = JCP.GOST_PARAMS_SIG_2012_256_KEY_OID;
                LOGGER.info("DIGEST_OID = JCP.GOST_DIGEST_2012_256_OID(1.2.643.7.1.1.2.2), SIGN_OID = JCP.GOST_PARAMS_SIG_2012_256_KEY_OID(1.2.643.7.1.1.1.1)");

            } else if (AlgInCert == JCP.GOST_EL_2012_512_NAME) {
                DIGEST_OID = JCP.GOST_DIGEST_2012_512_OID;
                SIGN_OID = JCP.GOST_PARAMS_SIG_2012_512_KEY_OID;
                LOGGER.info("JCP.GOST_DIGEST_2012_512_OID(1.2.643.7.1.1.2.3), SIGN_OID = JCP.GOST_PARAMS_SIG_2012_512_KEY_OID(1.2.643.7.1.1.1.2)");

            } else {
                LOGGER.info("EXCEPTION INFO in public byte[] createCMS Excetion"
                        + "Unknown Algorithm in cert was:" + AlgInCert);
                throw new BaseSystemException(Message.BASE_ERROR);
            }

            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(DIGEST_OID).value);
            a.parameters = new Asn1Null();
            cms.digestAlgorithms.elements[0] = a;

            Asn1OctetString asn1OctetString = null;
            if (content != null)
                asn1OctetString = new Asn1OctetString(content);
            cms.encapContentInfo = new EncapsulatedContentInfo(
                    new Asn1ObjectIdentifier(
                            new OID(STR_CMS_OID_DATA).value),
                    asn1OctetString);

            // certificate
            cms.certificates = new CertificateSet(1);
            final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate = new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
            Asn1BerDecodeBuffer decodeBuffer = new Asn1BerDecodeBuffer(x509Certificate.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();
            //insert timestamp

            LOGGER.info("INFO START public byte[] createCMS insert TIMESTAMP Start");
            if (timestamp != null && timestamp.length > 0) {
                Asn1ObjectIdentifier unsignedObjId = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_UNSIGNED_ATTR).value);
                cms.signerInfos.elements[0].unsignedAttrs = new UnsignedAttributes(1);
                cms.signerInfos.elements[0].unsignedAttrs.elements[0] = new Attribute(unsignedObjId, new Attribute_values(1));

                //ASN1InputStream aIn = new ASN1InputStream(resp);
                //aIn.readObject().toASN1Primitive()
                ru.CryptoPro.JCP.ASN.PKIXTSP.TimeStampResp tsp = new ru.CryptoPro.JCP.ASN.PKIXTSP.TimeStampResp();
                decodeBuffer = new Asn1BerDecodeBuffer(timestamp);
                tsp.decode(decodeBuffer);
                cms.signerInfos.elements[0].unsignedAttrs.elements[0].values.elements[0] = tsp.timeStampToken;

                Asn1ObjectIdentifier signedObjId = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_SIGNING_TIME).value);
                cms.signerInfos.elements[0].signedAttrs = new SignedAttributes(1);
                cms.signerInfos.elements[0].signedAttrs.elements[0] = new Attribute(signedObjId, 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[0].values.elements[0] = time.getElement();
            }
            LOGGER.info("Timestamp: " + timestamp.toString());

            LOGGER.info("public byte[] createCMS insert TIMESTAMP End");

            final byte[] encodedName = (x509Certificate).getIssuerX500Principal().getEncoded();
            final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
            final Name name = new Name();
            name.decode(nameBuf);

            final CertificateSerialNumber num = new CertificateSerialNumber((x509Certificate).getSerialNumber());
            cms.signerInfos.elements[0].sid.set_issuerAndSerialNumber(new IssuerAndSerialNumber(name, num));
            cms.signerInfos.elements[0].digestAlgorithm = new DigestAlgorithmIdentifier(new OID(DIGEST_OID).value);
            cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
            cms.signerInfos.elements[0].signatureAlgorithm = new SignatureAlgorithmIdentifier(new OID(SIGN_OID).value);
            cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
            cms.signerInfos.elements[0].signature = new SignatureValue(signature);
            // encode

            LOGGER.info("Start final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer()");
            LOGGER.info("Start final Asn1BerEncodeBuffer CMS was:" + cms
                    + "/n" + " cms.signerInfos.elements[0].digestAlgorithm.toString()" + cms.signerInfos.elements[0].digestAlgorithm.toString());


            LOGGER.info("final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer()");
            final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();

            LOGGER.info("all.encode(asnBuf, true)");

            all.encode(asnBuf, true);

            LOGGER.info(String.format("return asnBuf.getMsgCopy(): %s", asnBuf.getMsgCopy().toString()));

            return asnBuf.getMsgCopy();
        } catch (Exception e) {
            LOGGER.error("EXCEPTION INFO in public byte[] createCMS Excetion", e);
            throw new BaseSystemException(Message.BASE_ERROR);
        }
    }


Код:
private static final String STR_CMS_OID_SIGNING_TIME = "1.2.840.113549.1.9.5";


В подписи появилась необходимая информация, но при этом перестала быть валидной [img=https://cloud.mail.ru/public/Yu1c/SUBVtuEU9]Невалидная подпись[/img]
Ответ от стороннего сервиса следующий: "Entity 80feeaa2-71e2-4b0d-8195-e20882f2f64f not found in message 0b097001-1065-423b-8a56-401d163722cd"

Как понимаю, добавленный подписываемый атрибут меняет хэш. Попытки добавить неподписываемый атрибут нужного результата не дали. Как это победить?

Отредактировано пользователем 2 августа 2021 г. 13:45:55(UTC)  | Причина: Не указана

Offline Евгений Афанасьев  
#4 Оставлено : 2 августа 2021 г. 18:38:42(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,494
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 583 раз в 554 постах
Время подписи - подписанный атрибут. Подпись должна быть на все подписанные атрибуты, а она, судя по сигнатуре функции, уже посчитана на что-то и просто добавляется в определённое место cms. Посмотрите пример CMSSign в одноимённом файле в пакете CMS_samples.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.