Аутентификация на сайтах с помощью Rutoken WEB / Хабр

Аутентификация на сайтах с помощью Rutoken WEB / Хабр Электронная цифровая подпись

Что нужно из оборудования

  • Компьютер. На нем производится запись необходимого материала с экрана, хранятся все файлы для видео и монтируется ролик.
  • Штатив. На него можно закрепить мобильный телефон для съемки живых кадров.
  • Мобильный телефон. На него, как вы уже догадались, можно снимать живые кадры. Когда есть возможность позвать в этот проект видеооператора, штатив и мобильный телефон не нужны, так как процесс съемки обеспечивает видеооператор.
  • Диктофон. На него записывается звук. Никакой конкретный рекламировать не будем, используйте любой, можно даже тот, что есть в мобильном телефоне.
  • Монтажная программа. В ней мы монтируем и собираем видео. У нас их две: для простого линейного монтажа мы используем программу Movavi, а для более сложного — Adobe Premiere Pro. Первая очень простая и быстрая в освоении. Конечно необходимо, чтобы все используемое ПО было лицензированным.
  • Много памяти на компьютере и мощный процессор. Чтобы сохранять все файлы для ролика и быстро его собирать. Файлы для ролика занимают в разы больше места, чем обычная документация.
  • Программа для обработки звука. В ней мы обрабатываем звук. Можно установить специальную, а можно использовать возможности программы  Adobe Premiere Pro.
  • Текстовый редактор. В нем мы пишем сценарий. Использовать можно любой, но лучше всего тот, в котором организована возможность совместной работы с документом. Например, можно использовать  Microsoft Word 2022 или Google Docs.
  • Программа для записи видео с экрана. С ее помощью мы снимаем видео с экрана, если это необходимо. Мы используем ту же программу, в которой мы делаем скриншоты для обычной документации, это программа Snagit.
  • Программа для создания текстовых слайдов для роликов. Можно использовать любую, мы используем графический онлайн-редактор Readymag.
Читайте также:  Как защититься от нападения, если за тобой идет незнакомец? Рекомендации подростку

.

Библитека signature

.

.

int init( const char* install_path
);

.

char* create_key_request(	const char* pin,	/* PIN-код токена */	const char* slot_key_id,	/* СЛОТ:ID ключа */	const char* paramset,	/* параметры ключа */	const char* request_file,	/* файл, в который будет сохранена заявка */	const char* common_name,	/* понятное имя субъекта */	const char* org,	/* организация */	const char* org_unit,	/* подразделение организации */	const char* city,	/* город */	const char* region,	/* регион */	const char* country,	/* страна */	const char* email,	/* email */	const char* keyUsages,	/* способы использования ключа, через , */	const char* extendedKeyUsages	/* расширенные способы использования ключа, через , */
);

.

int save_pem_cert( const char* cert, /* сертификат в PEM */ const char* cert_file, /*файл с сертификатом в PEM */ const char* slot_cert_id, /* SLOT : ID сертификата */ const char* label /* label */
);

.

char* sign_file(	const char* pin,	/* PIN-код токена */	const char* slot_key_id,	/* СЛОТ:ID ключа */	const char* slot_cert_id,	/* СЛОТ:ID сертификата */	const char* file_path,	/* путь к файлу, который будет подписан */	int detached	/* тип подписи: 1-отсоединенная, 0-присоединенная */
);

.

.

.

#include <windows.h>
#include "signature.h"
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL
Java_Rutoken_OpenSSL_Init
(	JNIEnv*	env,	jclass	cl,	jstring	install_path
)
{	if(!install_path)	return 0;	return (jint)init((*env).GetStringUTFChars(install_path, false));
}
JNIEXPORT jint JNICALL
Java_Rutoken_OpenSSL_SaveCertToToken
(	JNIEnv*	env,	jclass	cl,	jstring	cert,	// сертификат в PEM	jstring	cert_file,	// файл с сертификатом в PEM	jstring	slot_cert_id,	// SLOT : ID сертификата	jstring	label
)
{	char* pCert	=	NULL;	char* pCertFile	=	NULL;	char* pId	=	NULL;	char* pLabel	=	NULL;	if( (!cert && !cert_file) || !slot_cert_id)	return 0;	if(cert)	pCert=(char*)(*env).GetStringUTFChars(cert, false);	if(cert_file)	pCertFile=(char*)(*env).GetStringUTFChars(cert_file, false);	pId=(char*)(*env).GetStringUTFChars(slot_cert_id, false);	if(label)	pLabel=(char*)(*env).GetStringUTFChars(label, false);	return (jint)save_pem_cert(	pCert, pCertFile, pId, pLabel);
}
JNIEXPORT jstring JNICALL
Java_Rutoken_OpenSSL_CreateKeyRequest
(	JNIEnv*	env,	jclass	cl,	jstring	pin, // PIN-код токена	jstring	slot_key_id, // СЛОТ:ID ключа	jstring	paramset, // параметры ключа	jstring	request_file, // файл, в который будет сохранена заявка	jstring	common_name, // понятное имя субъекта	jstring	org, // организация	jstring	org_unit, // подразделение организации	jstring	city, // город	jstring	region, // регион	jstring	country, // страна	jstring	email, // почтовый адрес	jstring	keyUsages, // способы использования ключа, через ,	jstring	extendedKeyUsages	// расширенные способы использования ключа, через ,
)
{	char* pPin	=	NULL;	char* pSlotKeyId	=	NULL;	char* pParamset =	NULL;	char* pCommonName	=	NULL;	char* pOrg	=	NULL;	char* pOrgUnit	=	NULL;	char* pCity	=	NULL;	char* pRegion	=	NULL;	char* pCountry	=	NULL;	char* pEmail	=	NULL;	char* pKeyUsages	=	NULL;	char* pExtendedKeyUsages	=	NULL;	char* request	=	NULL;	if(!pin || !slot_key_id || !paramset || !common_name || !email || !keyUsages || !extendedKeyUsages) return NULL;	pPin=(char*)(*env).GetStringUTFChars(pin, false);	pSlotKeyId=(char*)(*env).GetStringUTFChars(slot_key_id, false);	pParamset=(char*)(*env).GetStringUTFChars(paramset, false);	pCommonName=(char*)(*env).GetStringUTFChars(common_name, false);	pOrg=(char*)(*env).GetStringUTFChars(org, false);	pEmail=(char*)(*env).GetStringUTFChars(email, false);	pKeyUsages=(char*)(*env).GetStringUTFChars(keyUsages, false);	pExtendedKeyUsages=(char*)(*env).GetStringUTFChars(extendedKeyUsages, false);	if(org) pOrg=(char*)(*env).GetStringUTFChars(org, false);	if(org_unit)	pOrgUnit=(char*)(*env).GetStringUTFChars(org_unit, false);	if(city)	pCity=(char*)(*env).GetStringUTFChars(city, false);	if(region)	pRegion=(char*)(*env).GetStringUTFChars(region, false);	if(country)	pCountry=(char*)(*env).GetStringUTFChars(country, false);	request=(char*)create_key_request(	pPin, pSlotKeyId, pParamset, NULL,	pCommonName, pOrg, pOrgUnit, pCity,	pRegion, pCountry, pEmail, pKeyUsages,	pExtendedKeyUsages);	if(request)	return (*env).NewStringUTF((const char*)request);	else	return NULL;
}
JNIEXPORT jstring JNICALL
Java_Rutoken_OpenSSL_SignFile
(	JNIEnv*	env,	jclass	cl,	jstring	pin,	// PIN-код токена	jstring	slot_key_id,	// СЛОТ:ID ключа	jstring	slot_cert_id,	// СЛОТ:ID сертификата	jstring	file_path,	// путь к файлу, который будет подписан	jint	detached
)
{	char* pPin	=	NULL;	char* pKeyID	=	NULL;	char* pCertID	=	NULL;	char* pFilePath	=	NULL;	char* signature	=	NULL;	if(!pin || !slot_key_id || !slot_cert_id || !file_path)	return NULL;	pPin=(char*)(*env).GetStringUTFChars(pin, false);	pKeyID=(char*)(*env).GetStringUTFChars(slot_key_id, false);	pCertID=(char*)(*env).GetStringUTFChars(slot_cert_id, false);	pFilePath=(char*)(*env).GetStringUTFChars(file_path, false);	signature=sign_file(	pPin,	pKeyID,	pCertID,	pFilePath,	(int)detached);	if(signature)	return (*env).NewStringUTF((const char*)signature);	else	return NULL;
}
#ifdef __cplusplus
}
#endif

.

#include <windows.h>
#include <openssl/lhash.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h> /* for CRYPTO_* and SSLeay_version */
#include <openssl/rand.h>
#include <openssl/md4.h>
#include <openssl/des.h>
#include <openssl/engine.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/cms.h>
#define CMD_LOAD_CERT_CTRL	(ENGINE_CMD_BASE 5)
#define	CMD_SAVE_CERT_CTRL	(ENGINE_CMD_BASE 6)
#define	CMD_LOGOUT (ENGINE_CMD_BASE 8)
#define ENGINE_PKCS11_PIN_MESSAGE	"PKCS#11 token PIN"
char modules_path[MAX_PATH];
/* структура для взаимодействия с engine_pkcs11 */
typedef struct _CERT_PKCS11_INFO {	const char*	s_slot_cert_id;	X509*	cert;	const char*	label;
} CERT_PKCS11_INFO;
/* callback передачи PIN-кода */
int pin_cb(UI *ui, UI_STRING *uis)
{	char* pPin=NULL;	char* pString=NULL;	pString=(char*)UI_get0_output_string(uis);	if(!pString)	return 0;	if(!strncmp(pString, ENGINE_PKCS11_PIN_MESSAGE,	strlen(ENGINE_PKCS11_PIN_MESSAGE))) {	pPin=(char*)UI_get_app_data(ui);	if(!pPin)	return 0;	UI_set_result(ui, uis, pPin);	return 1;	} else	return 0;
}
/* создает объект расширения сертификата */
X509_EXTENSION*
create_X509_extension
(	char* name,	char *value
)
{	X509_EXTENSION *ex;	ex = X509V3_EXT_conf(NULL, NULL, name, value);	if (!ex)	return NULL;	return ex; }
ENGINE* engine_gost=NULL;
ENGINE* LoadEngine(const char* pin)
{	ENGINE* engine_pkcs11=NULL;	char	enginePkcs11[MAX_PATH];	char	engineGost[MAX_PATH];	char	rtPkcs11ECP[MAX_PATH];	/* динамическая загрузка engine GOST */	strcpy(engineGost, modules_path);	strcat(engineGost, "gost.dll");	engine_gost=ENGINE_by_id("dynamic");	if(!engine_gost)	return NULL;	if(!ENGINE_ctrl_cmd_string(engine_gost,	"SO_PATH",	engineGost, 0) || !ENGINE_ctrl_cmd_string(engine_gost,	"ID",	"gost", 0) || !ENGINE_ctrl_cmd_string(engine_gost,	"LOAD",	NULL, 0))	return NULL;	if(!ENGINE_init(engine_gost)) {	ENGINE_free(engine_gost);	return NULL;	}	/* динамическая загрузка engine PKCS11 */	strcpy(enginePkcs11, modules_path);	strcat(enginePkcs11, "pkcs11_gost.dll");	strcpy(rtPkcs11ECP, modules_path);	strcat(rtPkcs11ECP, "rtPKCS11ECP.dll");	/* WARNING: крайне нужный вызов */	ENGINE_add(engine_gost);	engine_pkcs11=ENGINE_by_id("dynamic");	if(!engine_pkcs11)	return NULL;	if(!ENGINE_ctrl_cmd_string(engine_pkcs11,	"SO_PATH",	enginePkcs11, 0) ||	!ENGINE_ctrl_cmd_string(engine_pkcs11,	"ID",	"pkcs11_gost", 0) ||	!ENGINE_ctrl_cmd_string(engine_pkcs11,	"LOAD",	NULL, 0) ||	!ENGINE_ctrl_cmd_string(engine_pkcs11,	"MODULE_PATH",	rtPkcs11ECP, 0))	return NULL;	if(pin) {	if(!ENGINE_ctrl_cmd_string(engine_pkcs11,	"PIN",	pin, 0))	return NULL;	}	if(!ENGINE_init(engine_pkcs11)) {	ENGINE_free(engine_pkcs11);	return NULL;	}	if(!ENGINE_set_default(engine_pkcs11, ENGINE_METHOD_ALL)) {	ENGINE_free(engine_pkcs11);	return NULL;	}	return engine_pkcs11;
}
X509_REQ*
create_request
(	EVP_PKEY*	pKey,	const char* common_name,	/* понятное имя субъекта */	const char* org,	/* организация */	const char* org_unit,	/* подразделение организации */	const char* city,	/* город */	const char* region,	/* регион */	const char* country,	/* страна */	const char* email,	/* почтовый адрес */	const char* keyUsages,	/* способы использования ключа, через , */	const char* extendedKeyUsages	/* расширенные способы использования ключа, через ; */
)
{	X509_REQ* req;	X509_NAME* subject;	BOOL bGoodEmail=TRUE;	subject	= X509_NAME_new();	if(common_name && strlen(common_name)>0) {	if(!X509_NAME_add_entry_by_NID(	subject, NID_commonName,	MBSTRING_UTF8, (unsigned char*)common_name,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	}	if(org && strlen(org)>0)	if(!X509_NAME_add_entry_by_NID(	subject, NID_organizationName,	MBSTRING_UTF8, (unsigned char*)org,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	if(org_unit && strlen(org_unit)>0)	if(!X509_NAME_add_entry_by_NID(	subject, NID_organizationalUnitName,	MBSTRING_UTF8, (unsigned char*)org_unit,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	if(city && strlen(city)>0)	if(!X509_NAME_add_entry_by_NID(	subject, NID_localityName,	MBSTRING_UTF8, (unsigned char*)city,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	if(region && strlen(region)>0)	if(!X509_NAME_add_entry_by_NID(	subject, NID_stateOrProvinceName,	MBSTRING_UTF8, (unsigned char*)region,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	if(country && strlen(country)>0)	if(!X509_NAME_add_entry_by_NID(	subject, NID_countryName,	MBSTRING_UTF8, (unsigned char*)country,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	if(email && strlen(email)>0) {	for (int i=0; i<strlen(email); i )	if (email[i]&0x80) {	bGoodEmail=FALSE;	break;	}	if(bGoodEmail) {	if(!X509_NAME_add_entry_by_NID(	subject, NID_pkcs9_emailAddress,	MBSTRING_UTF8, (unsigned char*)email,	-1, -1, 0)) {	X509_NAME_free(subject);	return NULL;	}	}	}	req=X509_REQ_new();	if(!req) {	X509_NAME_free(subject);	return NULL;	}	/* установка версии */	if(!X509_REQ_set_version(req, 0)) {	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	/* установка subject */	if(!X509_REQ_set_subject_name(req, subject)) {	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	/* установка открытого ключа */	if(!X509_REQ_set_pubkey(req, pKey)) {	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	/* "digitalSignature,keyEncipherment" */	X509_EXTENSION* keyUsageExt =	create_X509_extension("keyUsage", (char*)keyUsages);	if(!keyUsageExt) {	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	/* "clientAuth,emailProtection" */	X509_EXTENSION* extendedKeyUsageExt =	create_X509_extension("extendedKeyUsage", (char*)extendedKeyUsages);	if(!extendedKeyUsageExt) {	X509_EXTENSION_free(keyUsageExt);	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	STACK_OF(X509_EXTENSION)* extension_stack =	sk_X509_EXTENSION_new_null();	if(!extension_stack) {	X509_EXTENSION_free(extendedKeyUsageExt);	X509_EXTENSION_free(keyUsageExt);	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	sk_X509_EXTENSION_push(extension_stack, keyUsageExt);	sk_X509_EXTENSION_push(extension_stack, extendedKeyUsageExt);	if(!X509_REQ_add_extensions(req, extension_stack)) {	X509_EXTENSION_free(extendedKeyUsageExt);	X509_EXTENSION_free(keyUsageExt);	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	if(!X509_REQ_sign(req, pKey, EVP_get_digestbyname("md_gost94"))) {	X509_EXTENSION_free(extendedKeyUsageExt);	X509_EXTENSION_free(keyUsageExt);	X509_REQ_free(req);	X509_NAME_free(subject);	return NULL;	}	sk_X509_EXTENSION_pop_free	(extension_stack,X509_EXTENSION_free);	X509_NAME_free(subject);	return req;
}
ENGINE* engine_pkcs11	=	NULL;
extern "C" __declspec( dllexport )
int init(const char* install_path)
{	HMODULE hLibp11	= NULL;	HMODULE hLibTdl	= NULL;	char libp11[MAX_PATH];	char libtdl[MAX_PATH];	strcpy(modules_path, install_path);	strcpy(libtdl, install_path);	strcat(libtdl, "libltdl3.dll");	hLibTdl=LoadLibraryA(libtdl);	if(!hLibTdl)	return 0;	strcpy(libp11, install_path);	strcat(libp11, "libp11.dll");	hLibp11=LoadLibraryA(libp11);	if(!hLibp11)	return 0;	/* инициализируем OpenSSL */	ENGINE_load_builtin_engines();	OPENSSL_add_all_algorithms_noconf();	engine_pkcs11=LoadEngine(NULL);	if(!engine_pkcs11)	return 0;	return 1;
}
/* записать сертификат на токен */
extern "C" __declspec( dllexport )
int save_pem_cert
(	const char* cert,	/* сертификат в PEM */	const char* cert_file,	/* файл с сертификатом в PEM */	const char* slot_cert_id, /* SLOT : ID сертификата */	const char* label	/* label */
)
{	int	len =	0;	X509*	x509 =	NULL;	BIO*	bio_cert =	NULL;	BIO*	bio_der =	NULL;	CERT_PKCS11_INFO	cert_info;	/* загружаем сертификат */	if(cert) {	bio_cert=BIO_new(BIO_s_mem());	if(!bio_cert)	return 0;	if(!BIO_puts(bio_cert, cert))	return 0;	x509=PEM_read_bio_X509(bio_cert, NULL, NULL, NULL);	if(!x509) {	BIO_free(bio_cert);	return 0;	}	} else if(cert_file) {	bio_cert=BIO_new_file(cert_file, "rb");	if(!bio_cert)	return 0;	x509=PEM_read_bio_X509(bio_cert, NULL, NULL, NULL);	if(!x509) {	BIO_free(bio_cert);	return 0;	}	}	cert_info.s_slot_cert_id=slot_cert_id;	cert_info.cert=x509;	cert_info.label=label;	if(!ENGINE_ctrl(engine_pkcs11, CMD_SAVE_CERT_CTRL, 0,	(void*)&cert_info, NULL)) {	return 0;	}	return 1;
}
/* генерирует ключ подписи ГОСТ Р 34-10.2001 на Рутокен ЭЦП и создает заявку в формате PKCS#10 */
extern "C" __declspec( dllexport )
char* create_key_request(	const char* pin,	/* PIN-код токена */	const char* slot_key_id, /* СЛОТ:ID ключа */	const char* paramset,	/* параметры ключа */	const char* request_file, /* файл, в который будет сохранена заявка */	const char* common_name,	/* понятное имя субъекта */	const char* org,	/* организация */	const char* org_unit,	/* подразделение организации */	const char* city,	/* город */	const char* region,	/* регион */	const char* country,	/* страна */	const char* email,	/* почтовый адрес */	const char* keyUsages,	/* способы использования ключа, через , */	const char* extendedKeyUsages	/* расширенные способы использования ключа, через , */
)
{	BIO*	bio_req=NULL;	BIO*	bio_key=NULL;	X509_REQ*	pRequest=NULL;	BUF_MEM*	pbmReq;	char*	cRequest=NULL;	UI_METHOD*	uim=NULL;	int	reason=0;	EVP_PKEY*	key1=NULL;	EVP_PKEY*	newkey=NULL;	EVP_PKEY_CTX*	ctx=NULL;	key1=EVP_PKEY_new();	if(!key1) {	return NULL;	}	if(!EVP_PKEY_set_type(key1, 811)) {	EVP_PKEY_free(key1);	return NULL;	}	ctx=EVP_PKEY_CTX_new(key1, NULL);	if(!ctx) {	EVP_PKEY_free(key1);	return NULL;	}	if(!EVP_PKEY_keygen_init(ctx)) {	EVP_PKEY_CTX_free(ctx);	return NULL;	}	if(!EVP_PKEY_CTX_ctrl_str(ctx, "paramset", paramset)) {	EVP_PKEY_CTX_free(ctx);	return NULL;	}	if(!EVP_PKEY_CTX_ctrl_str(ctx, "slot_key_id", slot_key_id)) {	EVP_PKEY_CTX_free(ctx);	return NULL;	}	if(!EVP_PKEY_CTX_ctrl_str(ctx, "pin", pin)) {	EVP_PKEY_CTX_free(ctx);	return NULL;	}	if(!EVP_PKEY_keygen(ctx,&newkey)) {	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	pRequest=create_request(	newkey, common_name, org,	org_unit, city, region, country,	email, keyUsages, extendedKeyUsages);	if(!pRequest) {	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	bio_req=BIO_new(BIO_s_mem());	if(!bio_req) {	X509_REQ_free(pRequest);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	if(!PEM_write_bio_X509_REQ(bio_req, pRequest)) {	BIO_free(bio_req);	X509_REQ_free(pRequest);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	BIO_get_mem_ptr(bio_req, &pbmReq);	if(!pbmReq) {	BIO_free(bio_req);	X509_REQ_free(pRequest);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	cRequest=(char*)OPENSSL_malloc(pbmReq->length 1);	if(!cRequest) {	BIO_free(bio_req);	X509_REQ_free(pRequest);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	memset(cRequest, 0, pbmReq->length 1);	memcpy(cRequest, pbmReq->data, pbmReq->length);	BIO_free(bio_req);	bio_req=NULL;	if(request_file) {	bio_req=BIO_new_file(request_file, "wb");	if(!bio_req) {	X509_REQ_free(pRequest);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	if(!PEM_write_bio_X509_REQ(bio_req, pRequest)) {	BIO_free(bio_req);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	BIO_free(bio_req);	}	X509_REQ_free(pRequest);	EVP_PKEY_free(newkey);	EVP_PKEY_CTX_free(ctx);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return cRequest;
}
/* возвращает подпись PKCS#7 по ГОСТ Р 34-10.2001 в формате PEM */
extern "C" __declspec( dllexport )
char* sign_file(	const char* pin,	/* PIN-код токена */	const char* slot_key_id,	/* СЛОТ:ID ключа */	const char* slot_cert_id,	/* СЛОТ:ID сертификата */	const char* file_path,	/* путь к файлу, который будет подписан */	int detached	/* тип подписи: 1-отсоединенная, 0-присоединенная */
)
{	BIO*	bio_cert	=	NULL;	BIO*	in	=	NULL;	BIO*	out	=	NULL;	BUF_MEM*	pbmOut	=	NULL;	EVP_PKEY*	pKey	=	NULL;	UI_METHOD*	uim	=	NULL;	PKCS7*	p7	=	NULL;	char*	pSignature	=	NULL;	int	flags	=	0;	int	reason	=	0;	CERT_PKCS11_INFO	cert_info;	uim=UI_create_method("RutokenECP");	if(!uim)	return NULL;	UI_method_set_reader(uim, pin_cb);	/* считываем закрытый ключ */	pKey=ENGINE_load_private_key(engine_pkcs11, slot_key_id, uim, (void*)pin);	if(!pKey) {	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	memset(&cert_info, 0, sizeof(cert_info));	cert_info.s_slot_cert_id=slot_cert_id;	/* считывем сертификат с токена */	if(!ENGINE_ctrl(engine_pkcs11, CMD_LOAD_CERT_CTRL, 0, &cert_info, NULL)) {	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	BIO_free(bio_cert);	in=BIO_new_file(file_path, "rb");	if(!in) {	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	out=BIO_new(BIO_s_mem());	if(!out) {	BIO_free(in);	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	if(detached)	flags=PKCS7_DETACHED|PKCS7_BINARY;	else	flags=PKCS7_BINARY;	/* подпись pkcs#7 */	p7=PKCS7_sign(cert_info.cert, pKey, NULL, in, flags);	if(!p7) {	BIO_free(out);	BIO_free(in);	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	if(!PEM_write_bio_PKCS7(out, p7)) {	PKCS7_free(p7);	BIO_free(out);	BIO_free(in);	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	BIO_get_mem_ptr(out, &pbmOut);	if(!pbmOut) {	PKCS7_free(p7);	BIO_free(out);	BIO_free(in);	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	pSignature=(char*)OPENSSL_malloc(pbmOut->length 1);	if(!pSignature) {	PKCS7_free(p7);	BIO_free(out);	BIO_free(in);	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return NULL;	}	memset(pSignature, 0, pbmOut->length 1);	memcpy(pSignature,	pbmOut->data, pbmOut->length);	CRYPTO_cleanup_all_ex_data();	PKCS7_free(p7);	BIO_free(out);	BIO_free(in);	EVP_PKEY_free(pKey);	/* logout */	ENGINE_ctrl(engine_pkcs11, CMD_LOGOUT, 0, (void*)slot_key_id, NULL);	return pSignature;
}

.

Как монтировать ролик

.

.

.

.

.

.

.

.

.

Как снимать видео с экрана компьютера или мобильного устройства

.

.

.

.

.

.

Как снимать реальные кадры или записывать закадровый голос

.

.

.

.

.

.

.

.

.

.

.

.

Кто нужен для производства видеоинструкции

.

.

  • Технический писатель. Тот, который писал инструкцию для нашей смарт-карты. Он уже многое знает и напишет сценарий быстрее, чем любой другой, кому придется разбираться в этой теме. Зачем он нам: написать сценарий и снять видео с экрана своего компьютера. Также, если в видео есть реальные кадры, то нарисовать раскадровку для видеооператора. Это идеальная картина, бывает так, что технический писатель и режиссер, и оператор, и монтажер.
  • Видеооператор. Ему  совсем не обязательно быть в теме, для него создана раскадровка, и он по ней работает. У нас это не всегда отдельный человек, если нет на это ресурсов, то тот, кто пишет сценарий и снимает живые кадры. В этот раз он у нас был. Зачем он нам: качественно снять живые кадры и при необходимости помочь с монтажом.
  • Монтажер. У нас это тот, кто писал сценарий, он собирает весь ролик. Видеооператор может помочь ему выполнить какие-то сложные моменты. В этот раз они были: нам надо было показать одновременную работу смарт-карты в двух мобильных операционных системах.
  • Человек, записывающий закадровый голос. У нас это реальный сотрудник технической поддержки, его голос знаком нашим пользователям. Он записывает закадровый голос для ролика.

.

Монтируем созданный том

.

Файл

.

.


Если у Вас не подключен рутокен, то вы получите ошибку «

.

.

image

.

.

.

Обязательно ли писать сценарий

.

.

.

.

.

.

Опыт применения технологии рутокен для регистрации и авторизации пользователей в системе (часть 2)

.

.

).

.

.

.

  1. Скачиваем установочный дистрибутив openssl-1.1.1g.
    У openSSL имеются различные версии. В документации к Рутокену было сказано, что необходима версия openSSL версии 1.1.0 или новее. Я использовал версию openssl-1.1.1g. Можно скачать openSSL с официального сайта, но для более простой установки необходимо найти установочный файл для windows в сети. Я это сделал за вас: slproweb.com/products/Win32OpenSSL.html
    Необходимо пролистать вниз страницы и скачать Win64 OpenSSL v1.1.1g EXE 63MB Installer.
  2. Устанавливаем openssl-1.1.1g на компьютер.
    Установку необходимо провести по стандартному пути, который указывается автоматически в папку C:Program Files. Программа установится в папку OpenSSL-Win64.
  3. Для того, чтобы настроить openSSL так как вам нужно, существует файл openssl.cfg. Этот файл расположен в пути C:Program FilesOpenSSL-Win64bin если вы установили openSSL так, как было сказано в предыдущем пункте. Переходим в папку, где хранится openssl.cfg и открываем этот файл с использованием, например, Notepad .
  4. Вы наверно догадались, что настройка удостоверяющего центра будет производиться как-то изменением содержимого файла openssl.cfg, и вы абсолютно правы. Для этого требуется настроить команду [ ca ]. В файле openssl.cfg начало текста, куда мы будем вносить изменения, можно найти как: [ ca ].
  5. Теперь я приведу пример настройки с его описанием:
    [ ca ]
    default_ca	= CA_default [ CA_default ]
    dir	= /Users/username/bin/openSSLca/demoCA
    certs	= $dir/certs
    crl_dir	= $dir/crl
    database	= $dir/index.txt
    new_certs_dir	= $dir/newcerts
    certificate	= $dir/ca.crt
    serial	= $dir/private/serial
    crlnumber	= $dir/crlnumber
    crl	= $dir/crl.pem
    private_key	= $dir/private/ca.key
    x509_extensions	= usr_cert

    .

    .

    .

    .

    .

  6. Подключаем алгоритмы шифрования предоставляемые Рутокеном.
    Это подключение происходит в файле openssl.cfg.
    • Прежде всего требуется скачать необходимые алгоритмы Рутокена. Это файлы rtengine.dll, rtpkcs11ecp.dll.
      Для этого скачиваем Рутокен SDK: www.rutoken.ru/developers/sdk.

      .

      sdk/openssl/rtengine/bin/windows-x86_64/lib/rtengine.dll
      sdk/pkcs11/lib/windows-x86_64/rtpkcs11ecp.dll

      .

    • Библиотеки rtengine.dll и rtpkcs11ecp.dll можно держать в любом месте учетной записи пользователя.
    • Прописываем пути к этим библиотекам в openssl.cfg. Для этого открываем файл openssl.cfg, в начало этого файла необходимо поместить строчку:
      openssl_conf = openssl_def

      .

      [ openssl_def ]
      engines = engine_section
      [ engine_section ]
      rtengine = gost_section
      [ gost_section ]
      dynamic_path = /Users/username/bin/sdk-rutoken/openssl/rtengine/bin/windows-x86_64/lib/rtengine.dll
      MODULE_PATH = /Users/username/bin/sdk-rutoken/pkcs11/lib/windows-x86_64/rtpkcs11ecp.dll
      RAND_TOKEN = pkcs11:manufacturer=Aktiv Co.;model=Rutoken ECP
      default_algorithms = CIPHERS, DIGEST, PKEY, RAND

      dynamic_path – необходимо прописать свой путь к библиотеке rtengine.dll.
      MODULE_PATH — необходимо прописать свой путь к библиотеке rtpkcs11ecp.dll.

  7. Добавляем переменные среды.

    .

    .

  8. Теперь можно вернуться к пункту 5 и создать недостающие файлы для каталога demoCA.
    1. Первый важный файл без которого ничего не будет работать — serial. Это файл без расширения, значение которого должно быть 01. Можно создать этот файл самостоятельно и прописать внутрь 01. Также можно скачать его из Рутокен SDK по пути sdk/openssl/rtengine/samples/tool/demoCA/.
      В каталоге demoCA лежит файл serial, который нам как раз и нужен.
    2. Создаем корневой приватный ключ.
      Для этого воспользуемся командой библиотеки openSSL, которую необходимо запустить прямо в командной строке:
      openssl genpkey -algorithm gost2022_256 -pkeyopt paramset:A -out ca.key
    3. Создаем корневой сертификат.
      Для этого воспользуемся следующей командой библиотеки openSSL:
      openssl req -utf8 -x509 -key ca.key -out ca.crt

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

    Все теперь имеются все недостающие файлы для полной конфигурации каталога demoCA. Поместите созданные файлы в те каталоги, которые указаны в пункте 5.

.

.

Создаем зашифрованный том

ВНИМАНИЕ! Все дальнейшие необдуманные действия с Вашей стороны со своим жестким диском на Ваш страх и риск! Я описываю самый безопасный способ создания скрытого раздела. Если не хотите потерять данные, придерживайтесь инструкции.Для создания нового тома используем мастер создания томов TrueCrypt – ТомаСоздать новый раздел.
Запускается «Мастер создания томов TrueCrypt». Выбираем «Создать зашифрованный файловый контейнер», т.е. виртуальный зашифрованный диск будет храниться в одной файле.
imageОбычный том».
image
image
image
imageТокен-файлы», вводим пароль рутокена и выбираем токен.
image
image

Оцените статью
ЭЦП Эксперт