1) Добавление поддержки алгоритмов в openSSL
1.1) В версии до 1.0 ее просто нет (тут нужно ставить платную версию от КриптоПро) или компилировать вручную из исходников новую версию.
Это я не делал, поэтому пропускаю
1.2) OpenSSL версии 1.0 (1.1 по другому)
gost engine входит в операционную систему уже. Чтоб подключить engine, нужно
nano /etc/ssl/openssl.cnf
сразу до секции [ new_oids ]
вписать
"openssl_conf=openssl_def"
и в самом низу файла
[openssl_def]
engines = engine_section
# Engine scetion
[engine_section]
gost = gost_section
# Engine gost section
[gost_section]
engine_id = gost
dynamic_path = /usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines/libgost.so
default_algorithms = ALL
Возможно, libgost.so engine окажется немного не там где у меня
1.3) OpenSSL версии 1.1
Было принято решение убрать из ядра поддержку gost и теперь она на github-е
Нужно ее скачать и выполнить инструкции по установке.
В debian нужно поставить вот эти компиляторы и заголовки к libssl
apt-get install libssl-dev make cmake
https://github.com/gost-engine/engine/blob/master/INSTALL.md
Тут по инструкции все просто и оно рабочее.
Тут же есть и как правильно модифицировать конфиг openssl
2) Где достать всю цепочку сертификатов (мне для версии 1.1 этого не потребовалось почему-то)
После установки КриптоПро и сертификата с
https://ca.kontur.ru/about/certificates
Они выданы неким "Головным удостоверяющим центром". Этот сертификат появляется в системе после установки КриптоПро
и их можно экспортировать в файлы уже
3) Как вытащить приватный ключ из контейнера КриптоПро вы уже знаете.
https://habrahabr.ru/post/275039/
компилировать и ставить Borland C++ не обязательно (там можно скачать уже готовый файл exe под win)
4) Сертификат (публичную часть ключа вы можете прислать довольно просто)
Итак, у нас есть приватная и публичная часть и CA (это цепочка сертификатов до корня). Можно не мучатся и просто закинуть сертификат Контур-а в доверенные в linux и забыть о нем (но мне для 1.1 это не понадобилось)
4.1) Перегнать в форму pem
openssl x509 -inform der -in sphere.cer -out sphere.pem
openssl pkcs12 -in p12.pfx -nocerts -out private.key
openssl pkcs12 -info -engine gost -nodes -in sphere.pfx
openssl pkcs12 -info -engine gost -nodes -in sphere.pfx -password pass:Dsgdfh46yu56hsgdfgdgh
openssl pkcs12 -nocerts -out PushKey.pem -in p12.pfx -nodes -password pass:Dsgdfh46yu56hsgdfgdgh
openssl pkcs12 -nocerts -out PushKey.pem -in sphere.pfx -nodes -password pass:Dsgdfh46yu56hsgdfgdgh
5) Шифрование и расшифровка
openssl smime -encrypt -engine gost -gost89 -in test.txt -out test.txt.enc sphere.pem
openssl smime -decrypt -engine gost -gost89 -in test1.PDF -inform=DER -out test1_dec.pdf -inkey /home/www/certs/private_2018.key
6) Подпись и ее валидация
openssl cms -sign -inkey ~/certs/private_2018.key -CAfile ~/certs/CA.cer -signer ~/certs/sphere.pem -engine gost -binary -in file3.pdf -out file3.pdf.sign
openssl cms -verify -CAfile ~/certs/CA.cer -signer ~/certs/sphere.cer -engine gost -binary -content file3.pdf -in file3.pdf.sign
6.1) Контейнер файла с подписью p7m
openssl cms -sign -inkey ~/certs/private_2018.key -CAfile ~/certs/CA.cer -signer ~/certs/sphere.pem -engine gost -binary -stream -outform DER -nodetach -in file3.pdf -out file3.p7m
openssl cms -verify -binary -CAfile ~/certs/CA.cer -in file3.p7m -inform DER
Есть вариации на тему в какой форме подпись или шифрованный файл. Это решается за счет параметра
-inform=DER (бинарная форма)
-outform der (для отсоединенной формы)
Ссылки по теме:
http://big-town.narod.ru/openssl.html (основная, которая помогла)
https://habrahabr.ru/post/275039/
Второстепенные:
https://stackoverflow.com/questions/12790572/openssl-unable-to-get-local-issuer-certificate
https://www.altlinux.org/ГОСТ_в_OpenSSL
https://toster.ru/q/28353
https://kirill-zak.ru/2015/08/13/298
https://gist.github.com/aamalev/920f1dff286222ef73d7
http://sysadmins.ru/topic478444.html
http://www.ssl.ua/news/most-common-openssl-commands/
http://soft.lissi.ru/ls_product/skzi/OpenSSL/
# coding=utf-8
from datetime import datetime
from os import makedirs, listdir
import json
from django.core import serializers
from django.core.management.base import BaseCommand
from optparse import make_option
from django.db.models.loading import get_model
from django.conf import settings
class Command(BaseCommand):
help = """
Create difsettings from timestamp.
Usage: manage.py docflow_diffsettings_create '2014-01-01'
"""
option_list = BaseCommand.option_list + (
make_option('--from',
action="store",
type="string",
dest='from',
help='timestamp: changed from argument to current DateTime'),
make_option('--project_id',
action="store",
type="int",
dest='project_id',
help='Docflow project number'),
)
def __init__(self, *vargs, **kwargs):
super(Command, self).__init__(*vargs, **kwargs)
self._datetime_format = '%Y-%m-%d %H:%M'
def handle(self, *args, **options):
date_to = datetime.now()
date_from = datetime.strptime(options['from'], self._datetime_format)
project_id = options["project_id"]
project_folder = "%s/docflow/diffsettings/%s" % (settings.BASE_DIR, project_id,)
folder_path = "%s/%s > %s" % (project_folder,
date_from.strftime(self._datetime_format),
date_to.strftime(self._datetime_format))
makedirs(folder_path)
JSONSerializer = serializers.get_serializer("json")
json_serializer = JSONSerializer()
models_paths = set()
for model_path in args:
models_paths.add(model_path)
# deleted objects
models_paths.add('docflow.ObjectsDeleted')
# create files
for model_path in models_paths:
application_name, model_name = model_path.split('.')
model = get_model(application_name, model_name)
objects_changed = model.objects.filter(d_change__range=(date_from,
date_to))
# Обязательно наличие файла, даже если нет ни одной измененной модели
# это необходимо для создания бэкапа при накате настроек
# (если по модели нет изменившихся, но есть удаленные объекты)
# Создание файла отката настроек происходит
# внутри итерации перебота этих файлов
with open("%s/%s.json" % (folder_path, model_path), "w") as out:
json_serializer.serialize(objects_changed, stream=out, indent=4)
RedmineApp::Application.routes.default_scope = { :path => '/redmine', :shallow_path => '/redmine' }
# Это в конфиге есть
RedmineApp::Application.initialize!
Redmine::Utils::relative_url_root = "/redmine"
orker_processes 2
working_directory "/home/www/redmine/"
preload_app true
timeout 30
listen "/home/www/redmine/tmp/sockets/unicorn.sock", :backlog => 64
pid "/home/www/redmine/tmp/pids/unicorn.pid"
stderr_path "/home/www/redmine/log/unicorn.stderr.log"
stdout_path "/home/www/redmine/log/unicorn.stdout.log"
before_fork do |server, worker|
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
~
upstream unicorn_server {
server unix:/home/www/redmine/tmp/sockets/unicorn.sock;
}
server {
server_name docflow.soglasie.ru;
client_max_body_size 8m;
keepalive_timeout 5;
# apache
location / {
proxy_pass http://127.0.0.1:8181;
}
# redmine
location /redmine {
proxy_pass http://unicorn_server;
}
# redmine static
location ~* /redmine/.+\.(ico|css|js|png) {
rewrite /redmine/(.*) /$1 break;
root /home/www/redmine/public/;
}
}