Цифровая подпись в проектах на CryptoAPI (Лабораторная работа № 3), страница 5

1.  Для генерации ключей по алгоритму подписи RSA с размером ключа 1024 бит для г-на Иванова:

sign.exe –g ivanov.private ivanov.public –s RSA_SIGN -k 1024

2.  Для подписи документа «document.doc» закрытым ключом «ivanov.private» лично г-ном Ивановым с сохранением подписи в файл «document.signature» с использованием алгоритма нахождения хэш-значения «MD5».

sign.exe –s ivanov.private document.doc document.signature –h MD5

3.  Для проверки подписи «document.signature» документа «document.doc» открытым ключом «ivanov.public» г-на Иванова с использованием алгоритма нахождения хэш-значения «MD5».

sign.exe –v ivanov.public document.doc document.signature –h MD5

4.  Для вывода списка поддерживаемых в системе алгоритмов подписи и хэш алгоритмов, которые можно использовать в программе. Для данного списка используйте алгоритм перечисления провайдеров и их алгоритмов из четвёртой лабораторной работы.

sign.exe –l


Приложение 1

Чтение и запись файлов

Пример на C++:

bool readFile(LPCTSTR fileName)

{

  // Открываем файл для чтения

  HANDLE infile = ::CreateFile(

    fileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0

  );

  // Если он не может быть открыт

  if (infile == INVALID_HANDLE_VALUE) {

    ::printf(_T("Cannot open file <%s>\n"), fileName);

    return false;

  }

  // Получаем размер файла

  DWORD size = ::GetFileSize(infile, 0);

  // Выделяем буфер равный размеру файла

  BYTE * buf = reinterpret_cast<BYTE*>(

    ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, size)

  );

  // Читаем содержимое файла в буфер

  DWORD read = 0; // <-- Сколько действительно прочиталось

  ::ReadFile(infile, reinterpret_cast<LPVOID>(buf), size, &read, 0);

  /* ... Используем буфер для своих нужд ... */

  // Освобождаем буфер после использования

  ::HeapFree(::GetProcessHeap(), 0, buf);

  // Закрываем файл.

  ::CloseHandle(infile);

  return true;

}

bool writeFile(LPCTSTR fileName)

{

  // Открываем файл для записи

  HANDLE outfile = ::CreateFile(

    fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,

    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0

  );

  // Если он не может быть открыт

  if (outfile == INVALID_HANDLE_VALUE) {

    ::printf(_T("Cannot create file <%s>\n"), fileName);

    return false;

  }

  DWORD size;  // <-- Размер буфера

  BYTE * buf;

  /* ... Получаем данные в буфер ... */

  DWORD written = 0; // <-- Сколько действительно записалось

  // Записываем данные в файл

  ::WriteFile(

    outfile, reinterpret_cast<LPCVOID>(buf), size, &written, 0

  );

  // Закрываем файл.

  ::CloseHandle(outfile);

  return true;

}


Пример на Delphi:

procedure ReadFile(fileName: String);

var

  infile : TFileStream;

  size   : integer;

  buf    : PByte;

begin

  // Открываем файл для чтения

  infile := TFileStream.Create(fileName, fmOpenRead);

  // Получаем размер файла

  size := infile.Size;

  // Выделяем буфер равный размеру файла

  buf  := SysGetMem(size);

  // Читаем содержимое файла в буфер

  infile.Read(Pointer(buf)^, size);

  { ... Используем буфер для своих нужд ... }

  // Освобождаем буфер после использования

  SysFreeMem(buf);

  // Закрываем файл.

  infile.Free;

end;

procedure WriteFile(fileName: String);

var

  outfile : TFileStream;

  size    : integer;

  buf     : PByte;

begin

  // Открываем файл для записи

  outfile := TFileStream.Create(fileName, fmCreate);

  { ... Получаем данные в буфер ... }

  // Записываем содержимое буфера в файл

  outfile.Write(Pointer(buf)^, size);

  // Закрываем файл.

  outfile.Free;

end;

Естественно, читать большой файл целиком не рекомендуется, вместо этого лучше обрабатывать его блоками.



[1] Здесь и далее функция возвращает TRUE в случае успеха и FALSE в противном случае.