Данный код предназначен для иллюстрации формирования ЭЦП c использованием библиотеки openssl. Подробная документация по установке и использованию библиотеки и утлилит openssl доступна на web-сайте http://www.openssl.org
Компиляция и запуск примера:
openssl genrsa -out priv.key 1024
cc -lcrypto -o ./sign ./sign.c
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)
#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;
}