Re: Поддержка Рутокен ЭЦП в OpenSSL

Аверченко Кирилл, спасибо, в очередной раз помогли.

Ещё один маленький вопрос - создал самоподписанный корневой (СА) сертификат, пытаюсь им подписать запрос на сертификат из предыдущего действия:

openssl ca -utf8 -days +365 -keyfile demoCA/private/cakey.pem -cert demoCA/certs/cacert.pem -in demoCA/newcerts/client01.csr -out client01.pem
Using configuration from C:\openssl-1.1.1q\openssl.cnf

Команда выполняется без ошибок и предупреждений, но файла конечного нет. Параметры команды неверные или в чём-то другом ошибка? Можете пример привести?

Re: Поддержка Рутокен ЭЦП в OpenSSL

xfnreg, в C:\openssl-1.1.1q\openssl.cnf есть секция [ ca ]?

Re: Поддержка Рутокен ЭЦП в OpenSSL

Аверченко Кирилл, да, конечно:

[ ca ]
default_ca    = CA_default        # The default ca section

####################################################################
[ CA_default ]

dir        = ./demoCA
certs        = $dir/certs
crl_dir        = $dir.crl]        # Where the issued crl are kept
database    = $dir/index.txt    # database index file.
#unique_subject    = no            # Set to 'no' to allow creation of  several certs with same subject.
new_certs_dir    = $dir/newcerts

certificate    = $dir/certs/cacert.pem

serial        = $dir/serial.
crlnumber    = $dir]crlnumber.    # the current crl number  must be commented out to leave a V1 CRL
crl        = $dir]crl.pem         # The current CRL

private_key    = $dir/private/cakey.pem

x509_extensions    = usr_cert        # The extensions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt     = ca_default        # Subject Name options
cert_opt     = ca_default        # Certificate field options

# Extension copying option: use with caution.
# copy_extensions = copy

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions    = crl_ext

default_days    = 365            # how long to certify for
default_crl_days= 30            # how long before next CRL
default_md    = default        # use public key default MD
preserve    = no            # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy        = policy_match

Re: Поддержка Рутокен ЭЦП в OpenSSL

xfnreg, А в сертификате, который вы сгенерировали, как корневой, указано что он CA? Или вы пытаетесь использовать простой самоподписанный сертификат в качестве корневого?

(2022-08-25 12:28:11 отредактировано xfnreg)

Re: Поддержка Рутокен ЭЦП в OpenSSL

Аверченко Кирилл, использую самоподписанный сертификат как корневой.

openssl req -new -x509 -key demoCA/private/cakey.pem -out demoCA/certs/cacert.pem -extensions v3_ca -days +3650 -outform PEM

v3_ca в конфиге:

[ v3_ca ]

subjectKeyIdentifier=hash

authorityKeyIdentifier=keyid:always,issuer

#basicConstraints = critical,CA:true
basicConstraints = CA:true


C:\openssl-1.1.1q>openssl x509 -in demoCA/certs/cacert.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            0a:1d:07:19:ae:31:0c:3e:45:6f:c9:4d:e9:61:5d:69:f1:4b:39:11
        Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
        Issuer: C = RU, ST = MSK, O = CA, OU = CA, CN = CA
        Validity
            Not Before: Aug 25 09:25:05 2022 GMT
            Not After : Aug 22 09:25:05 2032 GMT
        Subject: C = RU, ST = MSK, O = CA, OU = CA, CN = CA
        Subject Public Key Info:
            Public Key Algorithm: GOST R 34.10-2012 with 256 bit modulus
                Public key:
                   X:1B4DD59E1EC4E2E20CB38A892AA26705E9EB2B4037063AC8368C53A3F33D97D7
                   Y:79FD4EE602E09D89EC7A9D27FE4C253C4194882B0548A830C35D22D7D3AA896B
                Parameter set: GOST R 34.10-2012 (256 bit) ParamSet A
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                66:50:2D:6A:E2:AD:9D:25:7A:A8:63:09:D9:41:D0:C5:61:16:8F:9D
            X509v3 Authority Key Identifier:
                keyid:66:50:2D:6A:E2:AD:9D:25:7A:A8:63:09:D9:41:D0:C5:61:16:8F:9D

            X509v3 Basic Constraints:
                CA:TRUE
    Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
         2d:00:16:ef:7b:33:d8:f3:c8:d4:9e:c6:84:67:95:51:7c:fd:
         26:19:55:47:9a:d6:f6:c9:1e:a3:18:b2:ef:c1:10:a7:e2:1d:
         6c:4f:7a:33:e9:f1:f5:37:4e:91:95:f6:6f:52:07:55:30:4f:
         ad:23:1b:ee:4c:da:a9:42:94:53

Re: Поддержка Рутокен ЭЦП в OpenSSL

xfnreg, проверил у себя ваши команды, в результате файл сертификата успешно создан в папке, откуда запущена консоль.
Команды

openssl req -new -x509 -key demoCA/private/cakey.pem -out demoCA/certs/cacert.pem -extensions v3_ca -days +3650 -outform PEM
openssl req -utf8 -new -keyform engine -key "pkcs11:id=000001" -engine rtengine -out demoCA/newcerts/client01.csr
openssl ca -utf8 -days +365 -keyfile demoCA/private/cakey.pem -cert demoCA/certs/cacert.pem -in demoCA/newcerts/client01.csr -out client01.pem

Конфиг openssl

# Динамическое подключение rtengine
openssl_conf = openssl_def

[ openssl_def ]
engines = engine_section

[ engine_section ]
rtengine = gost_section

[ gost_section ]
dynamic_path = "./rtengine.dll"
enable_rand = yes
pkcs11_path = "./rtpkcs11ecp.dll"
rand_token = pkcs11:manufacturer=Aktiv%20Co.;model=Rutoken%20ECP
default_algorithms = ALL

# Настройки создания запросов на сертификат
[ req ]
prompt = no
distinguished_name = req_distinguished_name
req_extensions = ext

# Сведения о владельце сертификата
[ req_distinguished_name ]
countryName = RU
commonName = Ivanov
emailAddress = ivanov@mail.ru
stateOrProvinceName = Moscow

# Расширения сертификата
[ ext ]
subjectSignTool = ASN1:FORMAT:UTF8,UTF8String:СКЗИ \"Рутокен ЭЦП 2.0\"
extendedKeyUsage=emailProtection
keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment

[ v3_ca ]

subjectKeyIdentifier=hash

authorityKeyIdentifier=keyid:always,issuer

#basicConstraints = critical,CA:true
basicConstraints = CA:true

# Настройки удостоверяющего центра
[ ca ]
default_ca = CA_default

[ CA_default ]
dir = ./demoCA # папка УЦ
database = $dir/index.txt
new_certs_dir = $dir/newcerts # папка, куда кладутся новые сертификаты

certificate = $dir/cacert.pem # сертификат УЦ
serial = $dir/serial
private_key = $dir/private/cakey.pem # закрытый ключ УЦ
RANDFILE = $dir/private/.rand

default_days = 365 # сколько дней будет действителен выданный сертификат
default_crl_days = 30
default_md = md_gost12_256 # алгоритм хеширования по умолчанию

policy = policy_any
email_in_dn = no

name_opt = ca_default
cert_opt = ca_default
copy_extensions = copy

# Обязательность полей в запросе на сертификат
[ policy_any ]
countryName = supplied
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ tsa ]
default_tsa = tsa_config

[ tsa_config ]
dir = ./demoCA
serial = $dir/tsa_serial
signer_cert = $dir/tsacert.pem
signer_key = $dir/private/tsakey.pem
signer_digest = md_gost12_256
default_policy = 1.2.3.4
digests = md_gost94,md_gost12_256,md_gost12_512
tsa_name = yes
ess_cert_id_chain = yes
ess_cert_id_alg = md_gost12_256

[ tsa_ext ]
basicConstraints = critical,CA:false
extendedKeyUsage = critical,timeStamping
keyUsage = critical,nonRepudiation
subjectKeyIdentifier = hash

Re: Поддержка Рутокен ЭЦП в OpenSSL

Аверченко Кирилл, спасибо. Этот конфиг, если не ошибаюсь, из примера сдк. С ним тоже не формируется. Мне помогла другая команда:

openssl x509 -req -in democa/newcerts/client01.csr -CA democa/certs/cacert.pem -CAkey democa/private/cakey.pem -CAcreateserial -out democa/certs/client01_gost.pem -days 365

С ней файл успешно формируется.

Ещё раз спасибо большое за помощь.

(2022-11-10 22:08:05 отредактировано OlegShtch)

Re: Поддержка Рутокен ЭЦП в OpenSSL

Здравствуйте, разбираюсь с проверкой подписей. Сформировал ключ и тестовый сертификат на https://ra.rutoken.ru/. Там же подписал файл отсоединённой подписью с включением сертификата. Проверил на госуслугах https://www.gosuslugi.ru/pgu/eds что подпись верная.

Теперь пытаюсь проверить локально с помощью openssl на Debian testing:

Преобразовываем подпись из base64 в DER:

openssl base64 -d -a -nopad -in signature_140854_10112022.sig -out signature_140854_10112022.sig.der

Проверяем, что подпись в формате PKCS#7:

openssl pkcs7 -inform der -in signature_140854_10112022.sig.der -print

Извлекаем открытый ключ из сертификата:

openssl x509 -engine rtengine -in Test.crt -pubkey -out Test.pem

Проверяем подпись, возвращается "Verification failure":

openssl dgst -engine rtengine -verify Test.pem -signature signature_140854_10112022.sig.der Test-doc.txt

С -engine gost всё также не работает.

Версии пакетов

openssl: 3.0.7-1
libengine-gost-openssl: 3.0.1-2+b1
librtengine3: 3.1.1
librtpkcs11ecp: 2.6.1.0
rutokenplugin: 4.7.0-1

P.S. Разобрался, нашёл в недрах интернета пример:

openssl smime -engine gost -verify -CAfile caGost256.crt -no_check_time -in signature_140854_10112022.sig.der -inform der -content Test-doc.txt

Re: Поддержка Рутокен ЭЦП в OpenSSL

Здравствуйте OlegShtch, возможно вам будет полезна статья по сценарию работы с engine https://dev.rutoken.ru/pages/viewpage.a … d=43450394
Там есть команда проверки подписи в формате CMS:

openssl cms -verify -binary -in signed_cms -inform PEM -out verified_data -CAfile demoCA/cacert.pem -content data_to_sign

Возможно так получится.

(2022-11-26 23:13:05 отредактировано OlegShtch)

Re: Поддержка Рутокен ЭЦП в OpenSSL

Николай Киблицкий пишет:

Здравствуйте OlegShtch, возможно вам будет полезна статья по сценарию работы с engine https://dev.rutoken.ru/pages/viewpage.a … d=43450394
Там есть команда проверки подписи в формате CMS:

openssl cms -verify -binary -in signed_cms -inform PEM -out verified_data -CAfile demoCA/cacert.pem -content data_to_sign

Возможно так получится.

Да, так тоже работает.

Теперь пробую наоборот подписать файл.

Использую следующий конфигурационный файл:

openssl_conf = openssl_init
 
[openssl_init]
engines = engine_section
 
[engine_section]
rtengine = rtengine_section

[rtengine_section]
engine_id = rtengine
dynamic_path = /usr/lib/x86_64-linux-gnu/engines-3/librtengine.so
enable_rand = yes
rand_token = pkcs11:manufacturer=Aktiv%20Co.;model=Rutoken%20ECP;serial=411d5727
pkcs11_path = /usr/lib/librtpkcs11ecp.so
default_algorithms = ALL
OPENSSL_CONF=openssl.cnf openssl cms -sign -binary -nosmimecap -in Test-doc.txt -out Test-doc.txt.sig -outform PEM -keyform engine -inkey "pkcs11:model=Rutoken%20ECP;manufacturer=Aktiv%20Co.;serial=411d5727;token=Rutoken%20ECP%20%3Cno%20label%3E;id=%53...%36;object=S...6;type=private" -engine rtengine -signer my.crl
Engine "rtengine" set.
Could not read signing key from org.openssl.engine:rtengine:pkcs11:model=Rutoken%20ECP;manufacturer=Aktiv%20Co.;serial=411d5727;token=Rutoken%20ECP%20%3Cno%20label%3E;id=%53...%36;object=S...6;type=private
4087DBC37A7F0000:error:40800088:lib(129):ERR_RTENG_error:no pkcs11 library loaded:engine/standalone/standalone.c:469:
4087DBC37A7F0000:error:13000080:engine routines:ENGINE_load_private_key:failed loading private key:../crypto/engine/eng_pkey.c:79:

Судя по strace /usr/lib/x86_64-linux-gnu/engines-3/librtengine.so подгружается, к /usr/lib/librtpkcs11ecp.so обращений не идёт, а ключ подписи пытается прочитаться с диска.

При этом при проверке движка через команду engine всё корректно проверяется. Если ошибиться в пути к библиотеке или токену будет показана ошибка:

OPENSSL_CONF=openssl.cnf openssl engine -vvvv -tt -c -pre pkcs11_path:/usr/lib/librtpkcs11ecp.so -pre enable_rand:yes -pre "rand_token:pkcs11:manufacturer=Aktiv%20Co.;model=Rutoken%20ECP;serial=411d5727" rtengine
(rtengine) Rutoken engine
[Success]: pkcs11_path:/usr/lib/librtpkcs11ecp.so
[Success]: enable_rand:yes
[Success]: rand_token:pkcs11:manufacturer=Aktiv%20Co.;model=Rutoken%20ECP;serial=411d5727
 [RAND, gost89, gost89-cnt, gost89-cnt-12, gost89-cbc, gost89-ecb, kuznyechik-ecb, kuznyechik-cbc, kuznyechik-ofb, kuznyechik-cfb, kuznyechik-ctr, kuznyechik-ctr-acpkm, kuznyechik-ctr-acpkm-omac, magma-ecb, magma-cbc, magma-ofb, magma-cfb, magma-ctr, magma-ctr-acpkm, magma-ctr-acpkm-omac, md_gost94, md_gost12_256, md_gost12_512, gost-mac, gost-mac-12, kuznyechik-mac, magma-mac, gost2001, gost-mac, gost2012_256, gost2012_512, gost-mac-12, kuznyechik-mac, magma-mac]
     [ available ]
     enable_rand: Enable rand method
          (input flags): STRING
     pkcs11_path: Path to PKCS#11 library
          (input flags): STRING
     rand_token: Rand token URI
          (input flags): STRING

P.S. Решилось перемещением строки pkcs11_path сразу после dynamic_path, без этого она не вызывалась, а также удалением ;type=private из URL.