Mantendo uma string secreta no código-fonte (aberto)

50

Concluí o desenvolvimento de um aplicativo para Android e pretendo publicá-lo com a GPL - quero que ele seja de código aberto. No entanto, a natureza do aplicativo (um jogo) é que ele pede enigmas e tem as respostas codificadas no recurso de sequência. Não consigo publicar as respostas! Disseram-me para procurar armazenar senhas com segurança - mas não encontrei nada apropriado.

É possível publicar meu código-fonte com uma matriz de strings oculta, criptografada ou obscurecida? Talvez lendo as respostas de um banco de dados online?

Atualizar

A solução de Yuval Filmus abaixo funcionou. Quando o li pela primeira vez, eu ainda não tinha certeza de como fazê-lo. Encontrei algumas soluções para a segunda opção: armazenar a solução hash na fonte e calcular o hash toda vez que o usuário adivinhar. Para fazer isso em javascript, existe a biblioteca crypto-js em http://code.google.com/p/crypto-js/ . Para Android, use a função MessageDigest . Existe um aplicativo (no fdroid / github) chamado HashPass que faz isso.

Nunca mais
fonte
11
Eu me pergunto como isso é ontopico aqui; pode ser mais adequado à segurança da informação em qualquer caso.
Raphael
2
@YuvalFilmus Não se deixe enganar pelos votos da "Pergunta quente". Mas ponto levado.
Raphael
4
Os detalhes importantes que faltam aqui são: Você deseja apenas verificar as respostas do usuário ou também pode imprimir a resposta correta? E você precisa de fuzzines ou existe apenas um conjunto claro e limitado de respostas corretas (para que você possa verificar a resposta do usuário nesse conjunto, um por um)?
Hyde
4
Todas as respostas estão perguntando qual é o problema que você deseja resolver. Por que você não pode publicar as respostas?
Rhymoid
11
O que seu código precisa fazer com essas strings? Precisa ser capaz de decodificá-los? Ou é capaz de comparar seqüências de caracteres a elas suficientes?
David Schwartz

Respostas:

83

Você tem pelo menos duas opções, dependendo do problema que deseja resolver.

Se você deseja que leitores inocentes do seu código não obtenham as respostas inadvertidamente, ou pelo menos queira torná-lo um pouco difícil para que os usuários não sejam tentados, você pode criptografar as soluções e armazenar a chave como parte do seu código, talvez um resultado de alguma computação (para tornar ainda mais difícil).

Se você deseja impedir que os usuários recuperem a resposta, use uma função unidirecional ou, no jargão do computador, uma função hash . Armazene um hash da resposta e você poderá testar se a resposta está correta, sem que seja possível deduzir a resposta , sem encontrá-la primeiro. Isso tem a desvantagem de que é mais difícil procurar por uma resposta próxima da resposta correta, embora existam algumas soluções para esse problema.

Yuval Filmus
fonte
9
Uma coisa que eu acrescentaria é que, se você precisar de ainda mais segurança, cada resposta provavelmente deve ser salgada com um sal diferente. Isso evita um ataque de dicionário contra todas as respostas de uma só vez. Se você quiser ver como as pessoas de criptografia "reais" fazem isso, dê uma olhada no sistema String-to-Key no OpenPGP .
Pseudônimo
11
Manter hashes no código significa que todas as informações são estáticas e salt / qualquer outra coisa também estará prontamente disponível. Acredito que, como resultado, seria razoável se o espaço de resposta fosse grande o suficiente (como uma faixa completa de valores inteiros de 32 bits), caso contrário (ou seja, no caso de perguntas de múltipla escolha), a tabela rainbow daria respostas corretas rapidamente.
Alexei Levenkov
3
Como Alexei aponta, se suas possíveis entradas ocuparem um espaço pequeno, o armazenamento das respostas no código as abrirá para qualquer invasor determinado - e eu acho que a maioria dos enigmas terá espaços de estado bastante pequenos, pois suas respostas geralmente devem ser palavras ou números relativamente pequenos. Você pode fazer hash ou criptografar para evitar erros inocentes, mas não há como impedir que alguém obtenha a resposta que realmente deseja. (Além disso, eles poderiam simplesmente perguntar a alguém que já resolveu o enigma!)
Chris Hayes
4
Para combater o que Chris está mencionando, você pode escolher um processo de hash muito lento, digamos que leva 100ms (essa é a abordagem adotada por alguns padrões de PK). Isso ainda é muito rápido da perspectiva do usuário, mas torna a enumeração muito mais difícil.
Yuval Filmus
12
@YuvalFilmus Novamente, até certo ponto. Se o seu enigma termina em "Jan, Joe ou Jane foram criminosos?" será muito fácil enumerar mesmo se você fizer o hash demorar um minuto inteiro. A menos que o jogo inteiro seja escrito com isso em mente, e todas as perguntas sejam extremamente abertas, isso representará um problema. Mas sim, se suas perguntas são tão abertas que o espaço de estado é suficientemente grande, as respostas podem ser protegidas.
Chris Hayes
28

Você tem duas três opções:

Mantenha as respostas separadas do restante do código-fonte

Se você deseja que seu código seja de código aberto, no entanto, não deseja que as respostas sejam de código aberto, abra o código do aplicativo sem as perguntas e respostas, com as perguntas e as respostas sendo um "plugin" de código fechado separado ou arquivo de dados. Seu aplicativo para Android agruparia esses dois em um único aplicativo.

Coloque as respostas no seu código fonte

Como alternativa, se você considera as perguntas e as respostas uma parte essencial do que deseja código aberto, deve colocar as respostas no código-fonte, de preferência sem ofuscamento, para que outras pessoas possam lê-las e modificá-las . Ofuscar o código-fonte para que não possa ser entendido e modificado não está de acordo com os princípios do código-fonte aberto.

Coloque as respostas em um servidor na internet

Com as duas soluções acima, é possível que alguém que baixou seu aplicativo encontre as respostas sem reproduzir o programa em ambos os casos - não importa como você ofusca / criptografa suas respostas, se o seu programa puder identificar a resposta sem informações adicionais, portanto um humano pode examinar seu aplicativo compilado.

Se você realmente quer ter certeza de que ninguém pode descobrir as respostas, a única opção real é não dar as respostas e solicitar que o aplicativo chame um serviço da web etc ... sempre que quiser saber a resposta. O aplicativo deve enviar a resposta que o usuário digitou e o serviço da Web deve informar ao aplicativo se a resposta está correta ou não, para que o usuário não tenha como saber qual é a resposta até que já tenha a resposta correta (breve forçar brutalmente o serviço da Web, contra o qual você pode detectar e proteger).

Se você está procurando maneiras de ofuscar suas respostas, isso sugere que você realmente não deseja abrir suas respostas em código-fonte, portanto, considere as primeiras opções.

Se é fundamental que o usuário não consiga encontrar a resposta com antecedência, a terceira opção é sua única opção real, no entanto, estou lutando para pensar em um cenário em que isso valha a pena, principalmente porque impede seus usuários. de usar seu aplicativo sem uma conexão com a Internet.

Justin
fonte
8
As perguntas e respostas nem precisam ser um plug-in, podem ser um arquivo de dados simples. Os arquivos de dados de entrada não são necessariamente incluídos como parte do software licenciado e podem ser cobertos por sua própria licença separada. Contanto que você forneça um arquivo de dados de amostra (diferente) para usar com o código-fonte, você não estará impedindo o uso gratuito da fonte ou dos programas compilados a partir dessa fonte e, portanto, não deve violar a GPL.
Doktor J
Não tenho certeza de que realmente resolva o problema dele - se as respostas são criptografadas e codificadas no código ou distribuídas como um arquivo separado, o código ainda precisa ser capaz de descriptografar as respostas, para que quem fizer o download do aplicativo possa fazer o que o código fonte faz para chegar às respostas. (a menos que eles estão em hash, como sugerido em outra resposta)
Johnny
11
Se o objetivo é verificar as respostas e não exigir que elas sejam exibidas, isso pode ser feito da mesma maneira que as senhas com um hash unidirecional.
precisa saber é o seguinte
@ Justin, obrigado pela resposta, e seus comentários sobre se constitui código aberto são interessantes. Penso que ocultar as respostas não visa ofuscar o código fonte ou como o aplicativo funciona, mas preservar a integridade do desafio. A criptografia, como se vê, é um meio maravilhoso de distribuir enigmas sem ter que estar lá quando o usuário adivinha ('é isso, é isso?')
Nevermore
4

Se o objetivo é ocultar as seqüências de caracteres da leitura casual do código-fonte, mas mantê-las abertas para que outras pessoas possam fazer suas próprias alterações com facilidade - por exemplo, se você estivesse publicando a fonte em uma aventura de texto e não quisesse que nenhum texto descritivo aparecesse que constituiria um spoiler, então use algo reversível como rot13.

Na verdade, você pode rotear todos os seus arquivos de tradução e devolvê-los rapidamente.

Isso está mantendo o espírito aberto. Os hashes "mágicos" aleatórios não são realmente adequados para programadores.

moopet
fonte
4
Lembre-se de que muitas pessoas do GeoCaching entre nós leem rot13 quase tão fluentemente quanto o original.
yo '
4

O código-fonte aberto exige que o código-fonte seja tornado público e disponível, não os dados do jogo. Portanto, você pode facilmente colocar os dados em outro arquivo e não publicá-lo. Adicione um pouco de criptografia se desejar impedir a leitura casual do arquivo. Duvido que uma criptografia forte seja necessária para sua aplicação.

liftarn
fonte
11
Em que sentido você pode "não publicar" os dados do jogo? O jogo deve ser capaz de acessar esses dados para que qualquer pessoa que tenha uma cópia do jogo tenha uma cópia dos dados. Isso é exatamente o que é publicar: tornar público.
David Richerby
11
@DavidRicherby Depende do que você deseja publicar e do que deseja terminar. Aquele jogo ou seu mecanismo que poderia ser usado para criar muitos jogos semelhantes? Permitir que as pessoas manipulem o seu jogo, inspecione o código quanto a brechas de segurança ou apenas reutilize componentes? Se sua interface é tão simples quanto "CSV com perguntas e respostas + programa = jogo", acho que é possível publicar apenas o programa, não o CSV.
Raphael
11
@Raphael Mas distribuir um jogo que consiste em um arquivo executável e em um arquivo de dados em texto sem formatação não atinge o objetivo de tornar as respostas secretas. Se você deseja propor uma versão criptografada do arquivo de dados, tudo bem, desde que todos entendam que isso é apenas segurança pela obscuridade (a chave está na fonte). Mas então entramos na questão de saber se o texto simples do arquivo de dados constitui código fonte no sentido da GPL e, nesse ponto, a questão se torna uma questão de interpretação da GPL, e não da ciência da computação.
David Richerby
@DavidRicherby: Concordado. Ainda assim, embora IANAL, duvido muito que um arquivo de dados composto por enigmas e suas respostas seja considerado parte essencial e insubstituível do programa que não possa ser licenciado separadamente - especialmente se você incluiu um arquivo de dados de amostra não criptografado no a distribuição de origem, juntamente com instruções para modificá-la e criptografá-la, se necessário, para deixar claro que qualquer pessoa com o código-fonte pode realmente criar seus próprios arquivos de dados personalizados e usá-los com o programa.
Ilmari Karonen
4

Por que você armazenaria suas respostas no código-fonte GPL se não deseja que seus usuários as conheçam? Mesmo se não forem conhecidos ou facilmente quebráveis ​​agora, eles podem (e provavelmente serão) estar no futuro.

Em vez de armazená-los no seu aplicativo, use um banco de dados externo. Faça um pequeno serviço da Web que compare as respostas com o que está no seu banco de dados. Em seguida, deixe seu aplicativo fazer uma chamada para esse serviço da Web sempre que for necessário verificar. O principal problema é que, por exigir acesso à Internet, você perderá velocidade e potencial base de usuários. sua licença do aplicativo deve se candidatar apenas ao aplicativo em si, não ao serviço da web.

Você também pode colocar suas respostas em um pequeno banco de dados e colocá-las em seu programa. Até onde eu sei, a GPL se aplica apenas ao código-fonte, não a quaisquer dados que seu aplicativo armazena. Eu posso estar errado nisso, no entanto.

Nzall
fonte
11
"Até onde eu sei, a GPL se aplica apenas ao código-fonte, não a quaisquer dados que seu aplicativo armazena". Bem, a GPL diz "Você deve licenciar todo o trabalho, como um todo, sob esta Licença para qualquer pessoa que possua uma cópia". Portanto, você pode pensar que agora precisamos decidir se os dados fazem parte do "trabalho inteiro". Mas, na verdade, certamente todas as restrições da GPL (incluindo essa) se aplicam apenas aos licenciados. É bom que os licenciadores também sigam o espírito da GPL, mas não precisam se preocupar com a visita da polícia de direitos autorais.
Peter
1

Lembre-se de que, mesmo que você armazene um banco de dados em um servidor da Web remoto, o banco de dados ainda poderá ser duplicado, simplesmente anotando todos os pares corretos de chave / valor que foram vistos. E, de um modo geral, os aplicativos móveis devem tentar não cometer erros ou deixar de funcionar porque a rede está inoperante (use mensagens em fila e "atualize quando puder").

Portanto, se você deseja um banco de dados local, mas não gosta da ideia de que ele seja descriptografado descaradamente, use um filtro de bloom (para evitar falar com uma rede ou ter um grande banco de dados descriptografado localmente). É assim que os corretores ortográficos costumavam funcionar quando o espaço da memória era muito pequeno.

Portanto, se você adicionar pares de perguntas / respostas ao filtro, como:

Hash (NormalizeString (pergunta [n])) + Hash (NormalizeString (resposta [n]))

Se você perguntar se "Capitólio da Virgínia? Richmond" está no set, ele responderá "definitivamente não" ou "quase certamente sim". Se você receber muitos falsos positivos, aumente o banco de dados.

Você pode ter um imenso banco de dados em um espaço minúsculo, supondo que o usuário escreva a pergunta e a resposta exatamente como você espera. Manter o banco de dados pequeno ajuda nas atualizações, porque elas provavelmente precisam ser transferidas por redes sem fio.

Roubar
fonte