Mantener una cadena secreta en el código fuente (abierto)

50

He terminado de desarrollar una aplicación para Android y tengo la intención de publicarla con GPL. Quiero que sea de código abierto. Sin embargo, la naturaleza de la aplicación (un juego) es que hace acertijos y tiene las respuestas codificadas en el recurso de cadena. ¡No puedo publicar las respuestas! Me dijeron que buscara almacenar contraseñas de forma segura, pero no he encontrado nada apropiado.

¿Es posible publicar mi código fuente con una matriz de cadenas oculta, encriptada u oculta? ¿Quizás leyendo las respuestas de una base de datos en línea?

Actualizar

La solución de Yuval Filmus a continuación funcionó. Cuando lo leí por primera vez, todavía no estaba seguro de cómo hacerlo. Encontré algunas soluciones para la segunda opción: almacenar la solución hash en la fuente y calcular el hash cada vez que el usuario adivina. Para hacer esto en javascript, existe la biblioteca crypto-js en http://code.google.com/p/crypto-js/ . Para Android, use la función MessageDigest . Hay una aplicación (en fdroid / github) llamada HashPass que hace esto.

Nunca más
fuente
11
Me pregunto cuán onópico es esto aquí; En cualquier caso , puede ser más adecuado para la seguridad de la información .
Raphael
2
@YuvalFilmus No se deje engañar por los votos de "Preguntas importantes". Pero punto tomado.
Rafael
44
Los detalles importantes que faltan aquí son: ¿Desea verificar las respuestas de los usuarios o también puede imprimir la respuesta correcta? Y, ¿necesita alguna fuzzines, o solo hay un conjunto limitado y claro de respuestas correctas (que puede verificar la respuesta del usuario contra este conjunto uno por uno)?
hyde
44
Todas las respuestas preguntan cuál es el problema que quieres resolver. ¿Por qué no puedes publicar las respuestas?
Rhymoid
1
¿Qué debe hacer su código para poder hacer con estas cadenas? ¿Necesita poder decodificarlos? ¿O es capaz de comparar cadenas con ellos suficiente?
David Schwartz

Respuestas:

83

Tiene al menos dos opciones, según el problema que desee resolver.

Si desea que lectores inocentes de su código no obtengan las respuestas inadvertidamente, o al menos quiere que sea un poco difícil para que los usuarios no se vean tentados, puede cifrar las soluciones y almacenar la clave como parte de su código, tal vez un resultado de algún cálculo (para hacerlo aún más difícil).

Si desea evitar que los usuarios recuperen la respuesta, puede usar una función unidireccional o, en la jerga de la computadora, una función hash . Almacenar un hash de la respuesta, y que se puede comprobar si la respuesta es correcta, sin que sea posible deducir la respuesta en absoluto sin encontrar primero. Esto tiene la desventaja de que es más difícil buscar una respuesta que esté cerca de la respuesta correcta, aunque hay algunas soluciones incluso para este problema.

Yuval Filmus
fuente
99
Una cosa que agregaría es que si necesita aún más seguridad, cada respuesta probablemente debería ser salada con una sal diferente. Esto evita un ataque de diccionario contra todas las respuestas a la vez. Si desea ver cómo lo hacen las personas criptográficas "reales", eche un vistazo al sistema String-to-Key en OpenPGP .
Seudónimo
1
Mantener los hashes en el código significa que toda la información es estática y la sal / cualquier otra cosa también estará disponible. Creo que, como resultado, sería razonable si el espacio de respuesta es lo suficientemente grande (como el rango completo de valores enteros de 32 bits), de lo contrario (es decir, en el caso de preguntas de opción múltiple), la tabla de arcoiris daría respuestas correctas rápidamente.
Alexei Levenkov
3
Como señala Alexei, si sus posibles entradas abarcan un espacio pequeño, el almacenamiento de las respuestas en el código las abrirá a cualquier atacante determinado, y supongo que la mayoría de los acertijos tendrán espacios de estado bastante pequeños, ya que sus respuestas generalmente deben ser ya sea palabras o números relativamente pequeños. Puede hacer hash o cifrar para evitar errores inocentes, pero no hay forma de evitar que alguien obtenga la respuesta que realmente quiere. (Además, ¡podrían preguntarle a alguien que ya resolvió tu enigma!)
Chris Hayes
44
Para contrarrestar lo que Chris menciona, puede elegir un proceso de hash que sea muy lento, digamos que toma 100 ms (ese es el enfoque adoptado por algunos estándares de PK). Esto sigue siendo muy rápido desde la perspectiva del usuario, pero hace que la enumeración sea mucho más difícil.
Yuval Filmus
12
@YuvalFilmus De nuevo, hasta cierto punto. Si su acertijo termina en "¿Era Jan, Joe o Jane el criminal?" entonces será muy fácil enumerar incluso si hace que el hash tome un minuto completo. A menos que todo el juego esté escrito con esto en mente, y todas las preguntas sean extremadamente abiertas, esto planteará un problema. Pero sí, si sus preguntas son tan abiertas que el espacio de estado es lo suficientemente grande, las respuestas pueden protegerse.
Chris Hayes
28

Tienes dos tres opciones:

Mantenga las respuestas separadas del resto del código fuente.

Si desea que su código sea de código abierto, sin embargo, no desea que las respuestas sean de código abierto, entonces abra el código de la aplicación sin las preguntas y respuestas, siendo las preguntas y las respuestas un "complemento" de código cerrado separado o archivo de datos. Su aplicación de Android los agruparía en una sola aplicación.

Pon las respuestas en tu código fuente

Alternativamente, si considera que las preguntas y respuestas son una parte central de lo que desea de código abierto, entonces debe poner las respuestas en el código fuente, preferiblemente sin ofuscar para que otros puedan leerlas y modificarlas . Ofuscar el código fuente para que no se pueda entender y modificar no está realmente de acuerdo con los principios del código fuente abierto.

Pon las respuestas en un servidor en internet

Con las dos soluciones anteriores es posible que alguien que haya descargado su aplicación encuentre las respuestas sin reproducir su programa en ninguno de los casos, sin importar cómo ofusque / encripte sus respuestas, si su programa puede identificar la respuesta sin información adicional, entonces ¿Puede un humano examinar su aplicación compilada?

Si realmente quiere asegurarse de que nadie pueda encontrar las respuestas, entonces la única opción real es no darles las respuestas y hacer que la aplicación llame a un servicio web, etc., siempre que quieran saber la respuesta. La aplicación debe enviar la respuesta que el usuario ha ingresado y el servicio web debe decirle a la aplicación si la respuesta es correcta o no, de esa manera el usuario no tiene forma de decir cuál es la respuesta hasta que ya tenga la respuesta correcta (breve de forzar al servicio web, que puede detectar y proteger).

Si está buscando formas de ofuscar sus respuestas, eso me sugiere que realmente no desea abrir sus respuestas en primer lugar, por lo que debe considerar las primeras opciones.

Si es crítico que el usuario no pueda encontrar la respuesta por adelantado, entonces la tercera opción es su única opción real, sin embargo, me cuesta pensar en un escenario en el que valga la pena el esfuerzo, sobre todo porque impide que sus usuarios de usar su aplicación sin una conexión a Internet.

Justin
fuente
8
El Q&A ni siquiera tiene que ser un complemento, puede ser un simple archivo de datos. Los archivos de datos de entrada no se incluyen necesariamente como parte del software con licencia y se pueden cubrir bajo su propia licencia por separado. Siempre que proporcione un archivo de datos de muestra (diferente) para usar con el código fuente, no está obstruyendo el uso gratuito de la fuente o los programas compilados a partir de dicha fuente y, por lo tanto, no debe violar la GPL.
Doktor J
No estoy seguro de que eso realmente resuelva su problema: si las respuestas están encriptadas y codificadas en el código o distribuidas como un archivo separado, el código aún debe poder descifrar las respuestas, de modo que quien descargue su aplicación puede hacer lo que quiera. el código fuente lo hace para llegar a las respuestas. (a menos que sean hash, como se sugiere en otra respuesta)
Johnny
1
Si el objetivo es verificar las respuestas y no requiere que se muestren, entonces se puede hacer de la misma manera que las contraseñas con un hash unidireccional.
JamesRyan
@Justin, gracias por tu respuesta, y tus comentarios sobre si constituye código abierto son interesantes. Creo que ocultar las respuestas no tiene la intención de ofuscar el código fuente o de cómo funciona la aplicación, sino más bien preservar la integridad del desafío. Resulta que la criptografía es un medio maravilloso para distribuir acertijos sin tener que estar allí cuando el usuario adivina ('¿es esto, es esto?')
Nunca más
4

Si el objetivo es ocultar las cadenas de la lectura casual del código fuente pero mantenerlas abiertas para que otras personas puedan hacer sus propios cambios fácilmente, por ejemplo, si estaba publicando la fuente en una aventura de texto y no quería que apareciera ningún texto descriptivo lo que constituiría un spoiler, luego usa algo reversible como rot13.

De hecho, podría descomponer 13 todos sus archivos de traducción y voltearlos sobre la marcha.

Eso es mantener el espíritu abierto. Los hashes aleatorios "mágicos" no son realmente amigables para los programadores.

moopet
fuente
44
Recuerde que muchas personas de GeoCaching entre nosotros leen rot13 casi tan fluidamente como el original.
yo '
4

El código abierto requiere que el código fuente se haga público y esté disponible, no los datos del juego. Por lo tanto, podría poner fácilmente los datos en otro archivo y no publicarlo. Agregue algunas criptomonedas si desea evitar la lectura casual del archivo. Dudo que sea necesaria una criptografía fuerte para su aplicación.

Liftarn
fuente
1
¿En qué sentido puedes "no publicar" los datos del juego? El juego tiene que poder acceder a esos datos para que cualquiera que tenga una copia del juego tenga una copia de los datos. Eso es más o menos exactamente lo que es publicar: hacer público.
David Richerby
1
@DavidRicherby Depende de lo que desee publicar y hasta el final. ¿Ese juego o tu motor que podría usarse para crear muchos juegos similares? ¿Permitir que las personas manipulen tu juego, inspeccionar el código en busca de agujeros de seguridad o simplemente reutilizar componentes? Si su interfaz es tan simple como "CSV con q & a + program = game", creo que es posible publicar solo el programa, no el CSV.
Raphael
1
@Raphael Pero distribuir un juego que consiste en un archivo ejecutable y un archivo de texto sin formato no logra el objetivo de hacer que las respuestas sean secretas. Si desea proponer una versión encriptada del archivo de datos, está bien, siempre y cuando todos entiendan que esto es solo seguridad por oscuridad (la clave está en la fuente). Pero luego nos preguntamos si el texto sin formato del archivo de datos constituye el código fuente en el sentido de la GPL y, en ese punto, la pregunta se convierte en una cuestión de interpretación de la GPL, en lugar de la informática.
David Richerby
@DavidRicherby: De acuerdo. Aún así, aunque IANAL, dudo mucho que un archivo de datos que consiste en acertijos y sus respuestas se consideraría una parte tan esencial e insustituible del programa que no podría obtener una licencia por separado, especialmente si incluyó un archivo de datos de muestra sin cifrar en la distribución fuente, junto con instrucciones para modificarla y encriptarla si es necesario, para dejar en claro que cualquier persona con el código fuente puede crear sus propios archivos de datos personalizados y usarlos con el programa.
Ilmari Karonen
4

¿Por qué almacenaría sus respuestas en su código fuente GPL si no desea que sus usuarios las conozcan? Incluso si no se conocen o son fáciles de descifrar ahora, pueden (y probablemente lo serán) en el futuro.

En lugar de almacenarlos en su aplicación, use una base de datos externa. Haga un pequeño servicio web que compare las respuestas con lo que hay en su base de datos. Luego, deje que su aplicación realice una llamada a ese servicio web siempre que tenga que verificar. El principal problema es que, dado que requiere acceso a Internet, perderá algo de velocidad y una base de usuarios potenciales. la licencia de su aplicación solo debe solicitar la aplicación en sí, no el servicio web.

También puede poner sus respuestas en una pequeña base de datos y ponerlas en su programa. Hasta donde sé, GPL solo se aplica al código fuente, no a los datos que almacena su aplicación. Sin embargo, podría estar equivocado en eso.

Nzall
fuente
1
"Hasta donde yo sé, GPL solo se aplica al código fuente, no a los datos que almacena su aplicación". Bueno, la GPL dice "Debe otorgar una licencia de todo el trabajo, como un todo, bajo esta Licencia a cualquier persona que tenga una copia". Entonces, puede pensar que ahora necesitamos decidir si los datos son parte del "trabajo completo". Pero en realidad, seguramente todas las restricciones de la GPL (incluida esa) solo se aplican a los licenciatarios. Es bueno para los licenciantes mantener el espíritu de la GPL también, pero no deberían preocuparse por una visita de la policía de derechos de autor.
Peter Ford
1

Recuerde que incluso si almacena una base de datos en un servidor web remoto, la base de datos puede duplicarse simplemente escribiendo todos los pares de clave / valor correctos que se hayan visto. Y en términos generales, las aplicaciones móviles deberían tratar de no dar errores o dejar de funcionar porque la red está inactiva (use mensajes en cola y "actualice cuando pueda").

Entonces, si desea una base de datos local, pero no le gusta la idea de que se descifre descaradamente, puede usar un filtro de floración (para evitar hablar con una red o tener una gran base de datos descifrada localmente). Así es como funcionaban los correctores ortográficos cuando el espacio de memoria era realmente escaso.

Entonces, si agrega pares de preguntas / respuestas en el filtro como:

Hash (NormalizeString (Pregunta [n])) + Hash (NormalizeString (Respuesta [n]))

Si pregunta si "Capitol of Virginia? Richmond" está en el set, responderá "definitivamente no" o "casi seguro que sí". Si obtiene demasiados falsos positivos, amplíe la base de datos.

Puede tener una inmensa base de datos en un espacio pequeño, suponiendo que el usuario deletree la pregunta y la respuesta exactamente como espera. Mantener la base de datos pequeña ayuda con las actualizaciones, porque probablemente tengan que transferirse a través de redes inalámbricas.

Robar
fuente