Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка использования метода CryptDecrypt, Шифрование строки асимметричным методом  
V
    Опции темы
domcom
Дата 13.5.2010, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 12.4.2010

Репутация: нет
Всего: нет



Привет!
У меня следующая задача.
Есть программа KeyGen, генерирующая строку, которая содержит некую лицензионную информацию. Есть также другая программа П, которая должна эту строку использовать. Строка должна быть зашифрована после генерации, чтобы злоумышленник не смог её самостоятельно изменять, но программа П должна уметь её расшифровать.

Исходники программы П общедоступны, а исходники программы KeyGen закрыты.

Для этого я хочу использовать асимметричный алгоритм шифрования RSA. В закрытых исходниках KeyGen будет прописан (прямо как строка) закрытый пароль, а открытый будет в исходниках программы П.

Я пытаюсь использовать CryptoAPI, но у меня проблемы с использованием CryptDecrypt. И вообще, я не уверен, правильно ли я все делаю!

Код

{ Создаем контекст криптопровайдера. Если такой уже есть - заменяем его }
function GetProvider: HCRYPTPROV;
begin
  CryptAcquireContext(@Result, ContName, nil, PROV_RSA_FULL,
    CRYPT_DELETEKEYSET);
  if not CryptAcquireContext(@Result, ContName, nil, PROV_RSA_FULL,
    CRYPT_NEWKEYSET) then RaiseLastOSError;
end;

{Этот метод вообще не должен быть ни в KeyGen, ни в П. Он просто генерирует пару ключей и возвращает их как строки, которые я потом и пропишу в исходниках обеих программ. Тут я его привожу, чтобы было видно, что я делаю это правильно.}
procedure GenerateKeys(out PrivateKey, PublicKey: string);
var
  Prov: HCRYPTPROV;
  ExchangeKey: HCRYPTKEY;
begin
  Prov := GetProvider;
  try
    if not CryptGenKey(Prov, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, @ExchangeKey) then
      RaiseLastOSError;
    try
      PrivateKey := ExportKey(ExchangeKey, PRIVATEKEYBLOB);
      PublicKey := ExportKey(ExchangeKey, PUBLICKEYBLOB);
    finally
      if not CryptDestroyKey(ExchangeKey) then
        RaiseLastOSError;
    end;
  finally
    if not CryptReleaseContext(Prov, 0) then
      RaiseLastOSError;
  end;
end;

{Экспотрирует либо открытый ключ, либо пару, в зависимости от параметра BlobType. }
function ExportKey(ExchangeKey: HCRYPTKEY; BlobType: Cardinal): string;
var
  Stream: TMemoryStream;
  BufSize: DWORD;
begin
  if not CryptExportKey(ExchangeKey, 0, BlobType, 0, nil, @BufSize) then
    RaiseLastOSError;
  Stream := TMemoryStream.Create;
  try
    Stream.SetSize(BufSize);
    if not CryptExportKey(ExchangeKey, 0, BlobType, 0, PByte(Stream.Memory),
      @BufSize) then RaiseLastOSError;
    SetLength(Result, BufSize);
    Stream.Position := 0;
    Stream.Read(PChar(Result)^, BufSize);
  finally
    Stream.Free;
  end;
end;


{Импорт ключа. Метод "преобразует" жестко прописанную строку в ключ}
function ImportKey(Prov: HCRYPTPROV; Key: string): HCRYPTKEY;
var
  Stream: TMemoryStream;
begin
  Stream:=TMemoryStream.Create;
  try
    Stream.Write(PChar(Key)^, Length(Key));
    Stream.Position := 0;
    if not CryptImportKey(Prov, PByte(Stream.Memory), Stream.Size, 0, 0,
      @Result) then RaiseLastOSError;
  finally
    Stream.Free;
  end;
end;


{Зашифровать лицензионную строку. Метод из KeyGen.}
function Encode(Str: string): string;
var
  Prov: HCRYPTPROV;
  PrivateKey: HCRYPTKEY;
  BufLen: DWORD;
  DataLen: DWORD;
begin
  Prov := GetProvider;
  try
    PrivateKey := ImportKey(Prov, FPrivateKey); // FPrivateKey - это и есть закрытый ключ. Получен в GenerateKeys
    try
      Result := Str;
      DataLen := Length(Result);
      BufLen := DataLen;
      if not CryptEncrypt(PrivateKey, 0, True, 0, nil, @BufLen, 0) then
        RaiseLastOSError;
      SetLength(Result, BufLen);
      if not CryptEncrypt(PrivateKey, 0, True, 0, PByte(Result), @DataLen,
        BufLen) then RaiseLastOSError;
    finally
      if not CryptDestroyKey(PrivateKey) then
        RaiseLastOSError;
    end;
  finally
    if not CryptReleaseContext(Prov, 0) then
      RaiseLastOSError;
  end;
end;

{Расшифровать лицензионную строка. Метод из приложения П.}
function Decode(Str: string): string;
var
  Prov: HCRYPTPROV;
  PublicKey: HCRYPTKEY;
  BufLen: DWORD;
begin
  Prov := GetProvider;
  try
    PublicKey := ImportKey(Prov, FPublicKey); // FPublicKey - это открытый ключ. Получен в GenerateKeys
    try
      Result := Str;
      BufLen := Length(Result);
      if not CryptDecrypt(PublicKey, 0, True, 0, PByte(Result), @BufLen) then
        RaiseLastOSError;
    finally
      if not CryptDestroyKey(PublicKey) then
        RaiseLastOSError;
    end;
  finally
    if not CryptReleaseContext(Prov, 0) then
      RaiseLastOSError;
  end;
end;


И вот на первом методе CryptDecrypt происходит ошибка:

---------------------------
Project1
---------------------------
System Error.  Code: -2146893811.

Ключ не существует.
---------------------------
ОК   
---------------------------


Не подскажете ли, где я что делаю не так?
Спасибо!

Это сообщение отредактировал(а) domcom - 13.5.2010, 16:05
PM MAIL   Вверх
domcom
Дата 14.5.2010, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 12.4.2010

Репутация: нет
Всего: нет



Да, решение нашел сам.

GetProvider нужно было переписать так:

Код

function GetProvider: HCRYPTPROV;
begin
  if not CryptAcquireContext(@Result, ContName, nil, PROV_RSA_FULL, 0) then
    RaiseLastOSError;
end;



И еще немного изменить Decode:

Код

function Decode(Str: string): string;
var
  Prov: HCRYPTPROV;
  PublicKey: HCRYPTKEY;
  BufLen: DWORD;
begin
  Prov := GetProvider;
  try
    PublicKey := ImportKey(Prov, FPublicKey);
    try
      Result := Str;
      BufLen := Length(Result);
      if not CryptDecrypt(PublicKey, 0, True, 0, PByte(Result), @BufLen) then
        RaiseLastOSError;
      SetLength(Result, BufLen);
    finally
      if not CryptDestroyKey(PublicKey) then
        RaiseLastOSError;
    end;
  finally
    if not CryptReleaseContext(Prov, 0) then
      RaiseLastOSError;
  end;
end;


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0395 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.