Пример исходного кода на C

Данный код предназначен для иллюстрации формирования ЭЦП c использованием библиотеки openssl. Подробная документация по установке и использованию библиотеки и утлилит openssl доступна на web-сайте http://www.openssl.org

Компиляция и запуск примера:

  1. Установите библиотеку и утилиты openssl
  2. Сформируйте файл закрытого ключа priv.key, выполнив команду
    openssl genrsa -out priv.key 1024
  3. Создайте файл sign.c, в который разместите исходный код примера
  4. Компиляция и запуск примера для платформы UNIX
    1. Скомпилируйте программу командой
      cc -lcrypto -o ./sign ./sign.c
    2. Запустите программу sign из той директории, где расположен файл ключа.
  5. Компиляция и запуск примера для платформы WINDOWS
    1. Запустите MS Visual Studio, затем выберите пункт меню Tools >> Visual Studio 2005 Command Prompt, в открывшемся окне интерпретатора командной строки перейдите в директорию, где хранится файл с примером.
    2. Скомпилируйте программу командой
      cl -I./inc32 ./sign.c /MD /link ./bin/libeay32.lib ./bin/ssleay32.lib
      при этом вместо ./inc32 укажите путь до директории с заголовочными файлами, поставляемыми в дистрибутиве openssl, вместо ./bin/libeay32.lib и ./bin/ssleay32.lib - пути (вместе с именами) к библиотекам libeay32.lib и ssleay32.lib (эти библиотеки создаются при установке openssl)
    3. Запустите программу sign.exe из той директории, где расположен файл ключа, при этом убедитесь, что путь к библиотекам libeay32.dll и ssleay32.dll присутствует в переменной окружения PATH, либо эти библиотеки находятся в одной директории с программой. Данные библиотеки установливаются вместе с openssl.
    4. При компиляции данного примера использовались openssl версии 0.9.71, компилятор Microsoft C++ из среды разработки Microsoft Visual Studio 2005, пример линковался с использованием msvcrt.lib, т.е. runtime, компилирование и линковка выполнялись в Microsoft Visual Studio 2005 Command Prompt.

#include <stdio.h>
#include <openssl/pem.h>
#include <openssl/evp.h>


const char HEX[16] = "0123456789abcdef";

int main(int argc, char ** argv){
	// путь к файлу приватного ключа 
	char *keyFile  ="priv.key";
	// подписываемые данные
	char *data  = "test";
	int dlen = 4;
	// подпись - результат вычислений
	unsigned char *sign;
	int slen;
	// подпись в шестнадцатеричном представлении
	char *hex;
	
	int i, j;
	FILE * f;
	EVP_MD *md;
	EVP_PKEY  *key;
	EVP_MD_CTX *mdctx;
	
	
	// читаем файл закрытого ключа
	f = fopen(keyFile, "r");
	if(f == NULL){
		printf("невозможно открыть файл ключа\n");
		return -1;
	}
	key = PEM_read_PrivateKey(f,NULL,NULL,NULL);
	fclose(f);
	if(key == NULL) goto ERROR;
		
	// определяем размер ключа
	slen = EVP_PKEY_size(key);
	
	// размер подписи будет таким же 
	sign = (unsigned char*) malloc(slen);
	if(sign == NULL)  goto ERROR;
		
	// получаем доступ к хэш-функции MD5
	OpenSSL_add_all_digests();
	md  = (EVP_MD*)EVP_get_digestbyname("MD5");
	if(md == NULL) goto ERROR;

	// формируем контекст подписи
	mdctx = EVP_MD_CTX_create();
	if(mdctx == NULL) goto ERROR;
	
	// устанавливаем хэш-функцию, которая буддет использована
	if(! EVP_SignInit(mdctx, md)) goto ERROR;

	// подписываем данные
	if(! EVP_SignUpdate(mdctx, data, dlen)) goto ERROR;

	// завершаем формирование подписи
	if(! EVP_SignFinal (mdctx, sign, &slen, key)) goto ERROR;
		
	// преобразуем результат вычислений в 
	// шестнадцатеричное представление
	hex = (char*) malloc(slen * 2 + 1);
	if(hex == NULL)  goto ERROR;	
	j = 0;
	for (i = 0; i < slen; i++) {
		hex[j++] = HEX[sign[i] >> 4];
		hex[j++] = HEX[sign[i] & 0xF];
	}
	hex[j] = 0;

	// отображаем результат в 16-ричном формате
	printf("Signature  is %s\n", hex);
	
	// освобождаем ресурсы
	free(hex);
	free(sign);
	EVP_PKEY_free(key);
	EVP_MD_CTX_destroy(mdctx);
	
	return 0;
	
	// отладочная информация при сбое
	ERROR:
	ERR_load_crypto_strings();
	printf("ERROR: %s\n", ERR_error_string(ERR_get_error(),NULL));
	return -1;
}