Каков наилучший способ защиты конфиденциальных данных в коде? - PullRequest
20 голосов
/ 21 октября 2011

Я изучал способы защиты своего кода от декомпиляции.

Здесь есть несколько хороших потоков, описывающих запутывание и упаковку кода как возможные способы защиты кода.Однако ни один из них не является идеальным, запутывание не работает с отражением, когда используются строковые методы / имена свойств.Многие люди не рекомендуют использовать обфускацию вообще.

Поэтому в настоящее время я решил не идти ни с одним из вышеперечисленного. Однако , У меня есть части кода, где мне нужно своего рода шифрование , например, строка подключения к базе данных с IP, логином и паролем хранится внутри кода как простая const string, аналогично данным учетной записи электронной почты.

В ASP.NET есть возможность переместить конфиденциальные данные в файл .config и зашифровать их, но для этого требуется ключ сервера, т. Е. Связанный с однимкомпьютер.Я не особо читал об этом, но думаю, что нечто подобное доступно для настольных приложений.Но мне нужно, чтобы это работало на любом компьютере, на котором установлено приложение.

И вот вопрос: есть ли способы кодировать / защищать такие данные, чтобы их нельзя было прочитать вместе сдекомпилированный код?

Ответы [ 7 ]

16 голосов
/ 21 октября 2011

Первый совет: никогда не храните ничего чувствительного в вашем коде напрямую.Вы можете всегда перепроектировать это, независимо от того, насколько умно вы пытаетесь его запутать.

Я читал о таких вещах, как взлом пароля на несколько частей, размещение его в разных местах вкодировать и запускать их через ряд функций, прежде чем, наконец, использовать их ... хотя это усложняет задачу, вы все равно всегда можете контролировать приложение, используя отладчик, и в конечном итоге вы сможете получить секретную информацию.

Если я правильно интерпретирую ваш сценарий, то у вас есть код, который должен быть развернут на территории какого-либо клиента, и ваш код подключен к базе данных (что, я полагаю, также находится под наблюдением клиента), для подключения к нему требуется пароль.Этот пароль известен этому клиенту, поэтому пытаться скрыть его от клиента довольно бесполезно.То, что вы делаете хотите, это ограничить доступ к этому паролю от любого, кто не должен его знать.

Обычно вы достигаете этого, помещая конфиденциальную информацию в отдельный файл в папку, котораядолжны иметь очень ограничительные разрешения, доступ должен иметь только приложение и несколько избранных пользователей.Затем приложение получит доступ к информации, когда это необходимо во время выполнения.

Кроме того, шифрование отдельного файла становится проблемой - если вы это сделаете, то есть ключ, который снова должен быть каким-то образом защищен - бесконечно.рекурсия идет своим чередом :) Обеспечение доступа к файлу часто достаточно, но если вам действительно нужно быть максимально безопасным, тогда решение заключается в использовании шифрования на основе пароля для файла.Но идея здесь не в том, чтобы хранить пароль в другом месте системы, а в виде внеполосной информации (например, в физическом хранилище) и ввода пароля при запуске приложения.Это также имеет свои проблемы: физическое присутствие человека требуется для (повторного) запуска приложения, и вы все равно можете получить пароль из ОЗУ компьютера, на котором запущено приложение.Но, вероятно, это лучшее, что вы можете сделать без специального оборудования.

Еще одна хорошая альтернатива шифрованию на основе пароля - это использование специфичных для ОС «хранилищ паролей», таких как Windows 101 * * Isolated Storage * 1018.* это своего рода компромисс между отсутствием шифрования и сохранением пароля вне диапазона.

11 голосов
/ 21 октября 2011

Это не ответ с шифрованием, но один из способов «обезопасить» это сделать все вызовы вашей базы данных через веб-сервис.Затем ваши учетные данные будут храниться на вашем защищенном сервере, и клиенты будут проходить через него все вызовы.

Ничего деликатного в твоем перераспределенном виде не хранится вообще ...

5 голосов
/ 21 октября 2011

Я сталкивался с этой проблемой в прошлом и придумал три способа решения этой проблемы, но я не уверен, что любой из них идеален:

  1. Обфусцируйте или зашифруйте значениеи надеюсь на лучшее.Шифрование, конечно, это просто дополнительный уровень запутывания, поскольку ключ должен быть доставлен вместе с остальными.
  2. Устраните необходимость в самом ключе, используя вместо этого одностороннее шифрование.Используйте закрытый ключ для генерации открытого ключа.Это может быть использовано для лицензирования или проверки пароля.Вы генерируете лицензии с закрытым ключом, но открытый ключ может использоваться для их проверки.Либо вы используете личный ключ для генерации пароля, который можно проверить, но не отменить с помощью открытого ключа.
  3. Создайте свой собственный системный механизм генерации ключей, аналогичный тому, который используется в ASP.NET.Вы можете ограничить влияние отмены шифрования / обфускации на шаге 1, создав уникальный ключ для каждой установки или сайта.
4 голосов
/ 21 октября 2011

Существует множество методов, но реальность такова, что если вы действительно хотите защитить свой код, единственное решение - использовать «профессиональные» продукты :-) не пытайтесь изобретать велосипед.Эти продукты обычно имеют опции для шифрования строк.Настоящая проблема в другом: без профессионального продукта (и даже с профессиональным продуктом) эксперт может просто поставить точку останова и посмотреть параметры, переданные библиотечному методу (например, тот, который открывает соединения).Теперь ... Если вы действительно хотите зашифровать строки своего кода, это довольно просто.Но будет ли это полезно?Нет.

Теперь, чтобы никто не пометил это как "не ответ", я выложу простой код шифрования / дешифрования:

// Generate key. You do it once and save the key in the code
var encryptorForGenerateKey = Aes.Create();
encryptorForGenerateKey.BlockSize = 128;
encryptorForGenerateKey.KeySize = 128;
encryptorForGenerateKey.GenerateKey();
encryptorForGenerateKey.GenerateIV();

var key = encryptorForGenerateKey.Key;
var iv = encryptorForGenerateKey.IV;

// Encrypt: this code doesn't need to be in the program. You create a console
// program to do it
var encryptor = Aes.Create();
var encryptorTransformer = encryptorForGenerateKey.CreateEncryptor(key, iv);

string str = "Hello world";
var bytes = Encoding.UTF8.GetBytes(str);
var encrypted = encryptorTransformer.TransformFinalBlock(bytes, 0, bytes.Length);
var encryptedString = Convert.ToBase64String(encrypted);

Console.WriteLine(encryptedString);

// Decrypt: this code needs to be in the program

var decryptor = Aes.Create();
var decryptorTransformer = decryptor.CreateDecryptor(key, iv);

byte[] encrypted2 = Convert.FromBase64String(encryptedString)

var result = decryptorTransformer.TransformFinalBlock(encrypted2, 0, encrypted2.Length);

var str2 = Encoding.UTF8.GetString(result);

Этот кодявно не в безопасности.Любой может декомпилировать программу, добавить Console.WriteLine(str2) и перекомпилировать ее.

3 голосов
/ 21 октября 2011

Как отметил Лукас в своем комментарии, если у вас есть только одна часть, то любой, кто декомпилирует ваше приложение, может перепроектировать его и расшифровать пароли вашей базы данных.

Что касается хранения учетных данных, моя обычная практика - всегда сохранять их в файле конфигурации приложения. Если затем мне нужно защитить его, я использую SecureString и некоторое шифрование. И это может работать для любой информации о конфигурации, а не только для учетных данных. Вот действительно хорошая статья о защите файлов конфигурации: Шифрование паролей в файле .NET app.config *

3 голосов
/ 21 октября 2011

Конечно, вы можете зашифровать свою строку перед ее компиляцией, но ваш код иногда нуждается в этом в виде простого текста, если вы используете простой db или http url.

В этом случае реальной защиты нет:Каждый может прослушивать (точку останова) указанный метод и при его вызове видеть, что происходит, в действительности не читая ваш код.Так что нет, никакой реальной защиты от этого нет, также с помощью обфускации в какой-то момент вы вызовете какой-нибудь метод .NET с этой строкой в ​​виде простого текста, и каждый сможет прочитать его.

Вы можете, например, поставить COMили C ++ dll для хранения зашифрованных строк.Неуправляемая dll не является декомпилируемой, однако опытные люди, конечно, могут понять разборку dll.И, как уже было сказано, иногда вам понадобятся простые данные, и в этот момент защита не сможет сохраниться.

Единственное, что вы можете сделать, - это изменить свою архитектуру.

Например, если ваша база данных находится в сети, а ваше приложение является клиентским приложением, вы можете подключиться с помощью веб-служб.Тогда вы можете предоставлять только те веб-сервисы, которые действительно нужны пользователю, и нет риска написания пользователем запросов sql.Затем вы можете добавить логику защиты на сервере, а не на клиенте.

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

1 голос
/ 21 октября 2011

Может быть, вам стоит прочитать больше о шифровании web.config http://learn.iis.net/page.aspx/141/using-encryption-to-protect-passwords/

Иначе мало что можно сделать. Хранение конфиденциальных данных в коде не вариант, так как любой, у кого есть инструмент для отражения, может открыть его и увидеть. Если вы хотите, чтобы код или переменные были невидимы для всех, вы должны создать веб-сервис на частном сервере, который принимает данные, преобразует их с помощью магии и возвращает их клиенту. Таким образом, все между публикацией и получением данных держится в секрете.

...