Хранение строкового секрета в (открытом) исходном коде

50

Я закончил разработку приложения для Android и собираюсь опубликовать его под лицензией GPL - я хочу, чтобы оно было с открытым исходным кодом. Однако природа приложения (игры) заключается в том, что оно задает загадки и кодирует ответы в строковом ресурсе. Я не могу опубликовать ответы! Мне сказали, чтобы посмотреть на безопасное хранение паролей - но я не нашел ничего подходящего.

Можно ли опубликовать мой исходный код со строковым массивом, скрытым, зашифрованным или иным образом скрытым? Может быть, читая ответы из онлайн-базы данных?

Обновить

Решение Ювала Фильмуса ниже сработало. Когда я впервые прочитал это, я все еще не был уверен, как это сделать. Я нашел несколько решений для второго варианта: хранить хешированное решение в источнике и вычислять хеш каждый раз, когда пользователь угадывает. Для этого в JavaScript есть библиотека crypto-js по адресу http://code.google.com/p/crypto-js/ . Для Android используйте функцию MessageDigest . Существует приложение (на fdroid / github) под названием HashPass, которое делает это.

никогда больше
источник
11
Интересно, насколько это здесь онтопично; в любом случае он может лучше подходить для информационной безопасности .
Рафаэль
2
@YuvalFilmus Не обманывайтесь голосами «Горячего вопроса». Но точка взята.
Рафаэль
4
Важные детали, отсутствующие здесь: Вы хотите просто проверить ответы пользователя или вы хотите иметь возможность распечатать правильный ответ тоже? И, вам нужны какие-нибудь пушистики, или есть просто четкий ограниченный набор правильных ответов (который вы можете проверить ответ пользователя по этому набору один за другим)?
Hyde
4
Все ответы спрашивают, какую проблему вы хотите решить. Почему вы не можете опубликовать ответы?
Рифмоид
1
Что ваш код должен уметь делать с этими строками? Нужно ли уметь их декодировать? Или достаточно сравнить строки с ними?
Дэвид Шварц

Ответы:

83

У вас есть как минимум два варианта, в зависимости от того, какую проблему вы хотите решить.

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

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

Юваль Фильмус
источник
9
Я хотел бы добавить одну вещь: если вам нужна еще большая безопасность, каждый ответ, вероятно, должен быть засолен другой солью. Это позволяет избежать атаки по словарю против всех ответов одновременно. Если вы хотите увидеть, как «настоящие» крипто люди делают это, взгляните на систему String-to-Key в OpenPGP .
псевдоним
1
Хранение хешей в коде означает, что вся информация статична, и соль / что-либо еще будет легко доступно. Я считаю, что в результате было бы разумно, если бы пространство ответов было достаточно большим (например, полный диапазон 32-битных целочисленных значений), в противном случае (например, в случае вопросов с несколькими вариантами ответов) радужная таблица быстро дала бы правильные ответы.
Алексей Левенков
3
Как указывает Алексей, если ваши возможные входные данные занимают небольшое пространство, хранение ответов в коде откроет их для любого решительного злоумышленника - и я предполагаю, что у большинства загадок будут довольно небольшие пространства состояний, поскольку их ответы обычно должны быть или слова или относительно небольшие цифры. Вы можете хешировать или шифровать, чтобы избежать невинных ошибок, но никто не мешает получить ответ, который действительно этого хочет. (Кроме того, они могли бы просто спросить кого-то, кто уже разгадал вашу загадку!)
Крис Хейс,
4
Чтобы противостоять тому, что упоминает Крис, вы можете выбрать очень медленный процесс хеширования, скажем, он занимает 100 мс (это подход, используемый некоторыми стандартами PK). Это все еще очень быстро с точки зрения пользователя, но делает перечисление намного более сложным.
Юваль Фильмус
12
@YuvalFilmus Опять в какой-то степени. Если ваша загадка заканчивается словами «Был ли Ян, Джо или Джейн преступником?» тогда будет очень легко перечислять, даже если хеш займет целую минуту. Если вся игра не написана с учетом этого, и все вопросы не являются открытыми, это создаст проблему. Но да, если ваши вопросы есть что открытый состав , что пространство состояний достаточно велико, ответы могут быть защищены.
Крис Хейс
28

У вас есть два варианта:

Храните ответы отдельно от остальной части исходного кода

Если вы хотите, чтобы ваш код был с открытым исходным кодом, но не хотите, чтобы ответы были с открытым исходным кодом, то вы открываете исходный код для приложения без вопросов и ответов, при этом вопросы и ответы являются отдельным «плагином» с закрытым исходным кодом. или файл данных. Ваше Android-приложение объединит их в одно приложение.

Положите ответы в свой исходный код

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

Разместите ответы на сервере в интернете

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

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

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

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

Джастин
источник
8
Q & A даже не должен быть плагином, это может быть простой файл данных. Файлы входных данных не обязательно включены в состав лицензионного программного обеспечения и могут быть защищены отдельной лицензией. Пока вы предоставляете (другой) пример файла данных для использования с исходным кодом, вы не препятствуете бесплатному использованию исходного кода или программ, скомпилированных из указанного источника, и, следовательно, не должны нарушать GPL.
Доктор J
Я не уверен, что это действительно решает его проблему - независимо от того, зашифрованы ли ответы в коде или жестко закодированы в коде или распространены в виде отдельного файла, код все еще должен иметь возможность расшифровывать ответы, поэтому любой, кто загружает его приложение, может делать то, что исходный код делает, чтобы добраться до ответов. (если они не хешированы, как предлагается в другом ответе)
Джонни
1
Если цель состоит в проверке ответов и не требует их показа, то это можно сделать так же, как пароли с односторонним хэшированием.
JamesRyan
@Justin, спасибо за ваш ответ, и ваши комментарии о том, является ли он открытым исходным кодом, интересны. Я думаю, что сокрытие ответов не предназначено для того, чтобы запутать исходный код или работу приложения, а скорее для сохранения целостности задачи. Криптография, как выясняется, является прекрасным средством распространения загадок без необходимости присутствовать там, когда пользователь угадывает («это так, не так ли?»)
Nevermore
4

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

Фактически, вы можете сгнить 13 всех ваших файлов перевода и перевернуть их на лету.

Это держит открытый дух. Случайные «волшебные» хеши не очень удобны для программистов.

moopet
источник
4
Помните, что многие из нас в GeoCaching читают rot13 почти так же свободно, как и оригинал.
лет»
4

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

liftarn
источник
1
В каком смысле вы можете «не публиковать» данные игры? Игра должна иметь возможность доступа к этим данным, чтобы у всех, кто имеет копию игры, была копия данных. Это почти то же самое, что и публикация: обнародование.
Дэвид Ричерби
1
@DavidRicherby Зависит от того, что вы хотите опубликовать и чем закончить. Та игра или ваш движок, который можно использовать для создания множества похожих игр? Разрешить людям манипулировать вашей игрой, проверять код на предмет дыр в безопасности или просто повторно использовать компоненты? Если ваш интерфейс такой простой, как «CSV с q & a + program = game», я думаю, что возможно публиковать только программу, а не CSV.
Рафаэль
1
@Raphael Но распространение игры, состоящей из исполняемого файла и файла данных в виде простого текста, не позволяет достичь секретности ответов. Если вы хотите предложить зашифрованную версию файла данных, это нормально, если все понимают, что это просто безопасность по неизвестности (ключ находится в источнике). Но затем мы сталкиваемся с вопросом о том, является ли открытый текст файла данных исходным кодом в смысле GPL, и в этот момент этот вопрос становится вопросом интерпретации GPL, а не компьютерной науки.
Дэвид Ричерби
@DavidRicherby: Согласен. Тем не менее, хотя IANAL, я очень сомневаюсь, что файл данных, состоящий из загадок и их ответов, будет считаться настолько важной и незаменимой частью программы, что его нельзя будет лицензировать отдельно - особенно, если вы включили незашифрованный образец файла данных в исходный дистрибутив вместе с инструкциями по его модификации и шифрованию, если это необходимо, чтобы дать понять, что любой, у кого есть исходный код, действительно может создавать свои собственные настраиваемые файлы данных и использовать их с программой.
Илмари Каронен
4

Зачем вам хранить ответы в исходном коде GPL, если вы не хотите, чтобы их знали пользователи? Даже если они не известны или их легко взломать сейчас, они могут (и, вероятно, будут) в будущем.

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

Вы также можете просто поместить свои ответы в небольшую базу данных и поместить их в свою программу. Насколько я знаю, GPL применяется только к исходному коду, а не к данным, которые хранит ваше приложение. Хотя я могу ошибаться в этом.

Nzall
источник
1
«Насколько я знаю, GPL применяется только к исходному коду, а не к данным, которые хранит ваше приложение». Ну, в GPL сказано: «Вы должны лицензировать всю работу в целом по этой Лицензии для любого, кто получит копию». Так что вы можете подумать, что теперь нам нужно решить, являются ли данные частью «всей работы». Но на самом деле, безусловно, все ограничения GPL (включая это) распространяются только на лицензиатов. Лицензиарам также приятно придерживаться духа GPL, но им не нужно беспокоиться о посещении полиции по защите авторских прав.
Питер Форд
1

Помните, что даже если вы храните базу данных на удаленном веб-сервере, ее можно дублировать, просто записав все правильные пары ключ / значение, которые были замечены. И вообще говоря, мобильные приложения должны стараться не давать ошибок или перестать функционировать, потому что сеть не работает (используйте обмен сообщениями в очереди и «обновляйте, когда можете»).

Поэтому, если вам нужна локальная база данных, но вам не нравится идея, что она будет явно дешифрована, вы можете использовать фильтр Блума (чтобы не общаться с сетью или иметь локальную расшифрованную базу данных). Так работали средства проверки орфографии, когда места в памяти было очень мало.

Итак, если вы добавите пары вопросов / ответов в фильтр, например:

Hash (NormalizeString (Вопрос [п])) + Hash (NormalizeString (ответ [п]))

Если вы спросите, есть ли в наборе «Капитолий Вирджинии? Ричмонд», он либо ответит «определенно нет», либо «почти наверняка да». Если вы получаете слишком много ложных срабатываний, увеличьте базу данных.

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

обкрадывать
источник