Новичок
Профиль
Группа: Участник
Сообщений: 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
|