Данный код предназначен для иллюстрации проверки подписи c использованием библиотеки openssl. Подробная документация по установке и использованию библиотеки и утлилит openssl доступна на web-сайте http://www.openssl.org
Компиляция и запуск примера:
cc -lcrypto -o ./verify ./verify.c
cl -I./inc32 ./verify.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>
int main(int argc, char ** argv){
// путь к файлу сертификата ЭЦП e-port
char *path = "eport.cer";
// подписанные данные
char *data = "test";
int dlen = 4;
// подпись e-port в шестнадцатеричном представлении
char * hex = "6eb9a0485b7b8dc2f8a8ea15760e3d4bd0e4819b7d5703f69a76818015ff20f89ecd07db1813d57ac3181f4f7dfa326bab704d09be2651c88b2bc571fd40d47e5d3abba81ce5e05db68ae7b37100a46f49b5b8846b166f86d5df23b3b38e98dcb5c00aa3c27d8c8ae241911b01a721cb6c32d8104d0989566a51cf91685d14a3";
// данные подписи для проверки
unsigned char * sign;
int slen;
int i, j;
char c;
unsigned char h;
FILE * f;
X509 *cert;
EVP_MD *md;
EVP_PKEY *key;
EVP_MD_CTX *mdctx;
// читаем файл сертификата публичного ключа e-port
f = fopen("eport.cer", "r");
if(f == NULL){
printf("невозможно открыть файл ключа\n");
return -1;
}
cert = PEM_read_X509(f,NULL,NULL,NULL);
if(cert == NULL) goto ERROR;
fclose(f);
// извлекаем публичный ключ ЭЦП e-port
key = X509_get_pubkey(cert);
if(key == NULL) goto ERROR;
// определяем размер ключа
slen = EVP_PKEY_size(key);
// размер подписи будет таким же
sign = (unsigned char*) malloc(slen);
if(sign == NULL) goto ERROR;
// получаем данные подписи из шестнадцатеричного предстваления
for(i = 0, j = 0; i < slen; i++){
c = hex[j++];
if (c > 47 && c < 58) h = c - 48;
else if (c > 96 && c < 103) h = c - 87;
else if (c > 64 && c < 71) h = c - 55;
else return -1;
h = h << 4;
c = hex[j++];
if (c > 47 && c < 58) h = h | (c - 48);
else if (c > 96 && c < 103) h = h | (c - 87);
else if (c > 64 && c < 71) h = h | (c - 55);
else return -1;
sign[i] = h;
}
// получаем доступ к хэш-функции 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_VerifyInit(mdctx, md)) goto ERROR;
// инициализируем контекст подписанными данными
if(! EVP_VerifyUpdate(mdctx, data, dlen)) goto ERROR;
// проверяем полдпись:
switch(EVP_VerifyFinal (mdctx, sign, slen, key)){
case 1:
// подпись верна
printf("Verify OK\n");
break;
case 0:
// подпись неверна
printf("Bad signature\n");
break;
default:
// сбой
goto ERROR;
}
free(sign);
X509_free(cert);
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;
}