Mantenere una stringa segreta nel codice sorgente (aperto)


50

Ho finito di sviluppare un'app per Android e intendo pubblicarla con GPL: voglio che sia open source. Tuttavia, la natura dell'applicazione (un gioco) è che richiede enigmi e ha le risposte codificate nella risorsa stringa. Non riesco a pubblicare le risposte! Mi è stato detto di cercare di archiviare le password in modo sicuro, ma non ho trovato nulla di appropriato.

È possibile pubblicare il mio codice sorgente con un array di stringhe nascosto, crittografato o altrimenti oscurato? Magari leggendo le risposte da un database online?

Aggiornare

La soluzione di Yuval Filmus qui sotto ha funzionato. Quando l'ho letto per la prima volta non ero ancora sicuro di come farlo. Ho trovato alcune soluzioni, per la seconda opzione: archiviare la soluzione con hash nell'origine e calcolare l'hash ogni volta che l'utente indovina. Per fare questo in javascript c'è la libreria crypto-js su http://code.google.com/p/crypto-js/ . Per Android, utilizzare la funzione MessageDigest . Esiste un'applicazione (su fdroid / github) chiamata HashPass che lo fa.


11
Mi chiedo quanto sia ontopico questo qui; potrebbe essere più adatto alla sicurezza delle informazioni in ogni caso.
Raffaello

2
@YuvalFilmus Non lasciarti ingannare dai voti "Hot Question". Ma punto preso.
Raffaello

4
I dettagli importanti mancanti qui sono: Vuoi solo verificare le risposte degli utenti o vuoi essere in grado di stampare anche la risposta corretta? E hai bisogno di qualche fuzzine o c'è solo un chiaro insieme limitato di risposte corrette (che in modo da poter verificare la risposta dell'utente contro questo insieme uno a uno)?
hyde,

4
Tutte le risposte chiedono quale sia il problema che si desidera risolvere. Perché non puoi pubblicare le risposte?
Rhymoid,

1
Cosa deve fare il tuo codice con queste stringhe? Deve essere in grado di decodificarli? O è sufficiente confrontare le stringhe con esse?
David Schwartz,

Risposte:


83

Hai almeno due opzioni, a seconda del problema che vuoi risolvere.

Se vuoi che i lettori innocenti del tuo codice non ottengano inavvertitamente le risposte, o almeno vuoi renderlo un po 'difficile in modo che gli utenti non siano tentati, puoi crittografare le soluzioni e archiviare la chiave come parte del tuo codice, forse un risultato di alcuni calcoli (per renderlo ancora più difficile).

Se si desidera impedire agli utenti di recuperare la risposta, è possibile utilizzare una funzione unidirezionale o, nel gergo del computer, una funzione hash . Memorizza un hash della risposta e loro possono verificare se la risposta è corretta senza che sia possibile dedurla affatto senza trovarla prima. Questo ha lo svantaggio che è più difficile cercare una risposta vicina alla risposta corretta, anche se ci sono alcune soluzioni anche a questo problema.


9
Una cosa che aggiungerei è che se hai bisogno di ancora più sicurezza, ogni risposta dovrebbe probabilmente essere salata con un sale diverso. Questo evita un attacco del dizionario contro tutte le risposte contemporaneamente. Se vuoi vedere come lo fanno le persone "reali" in criptovaluta, dai un'occhiata al sistema String-to-Key in OpenPGP .
Pseudonimo,

1
Mantenere gli hash nel codice significa che tutte le informazioni sono statiche e salt / qualunque altra cosa sarà prontamente disponibile. Ritengo che sarebbe ragionevole se lo spazio di risposta fosse abbastanza grande (come l'intera gamma di valori interi a 32 bit), altrimenti (cioè in caso di domande a scelta multipla) la tabella arcobaleno darebbe rapidamente le risposte corrette.
Alexei Levenkov,

3
Come sottolinea Alexei, se i tuoi possibili input si estendono in un piccolo spazio, la memorizzazione delle risposte nel codice li aprirà a qualsiasi aggressore determinato - e immagino che la maggior parte degli indovinelli avrà spazi di stato piuttosto piccoli, in quanto le loro risposte generalmente devono essere parole o numeri relativamente piccoli. Puoi hash o crittografare per evitare errori innocenti, ma non si può impedire a qualcuno di ottenere la risposta che la vuole davvero. (Inoltre, potrebbero semplicemente chiedere a qualcuno che ha già risolto il tuo indovinello!)
Chris Hayes,

4
Per contrastare ciò di cui parla Chris, puoi scegliere un processo di hashing molto lento, diciamo che impiega 100 ms (questo è l'approccio adottato da alcuni standard PK). Questo è ancora molto veloce dal punto di vista dell'utente, ma rende l'enumerazione molto più difficile.
Yuval Filmus,

12
@YuvalFilmus Ancora una volta, fino a un certo punto. Se il tuo indovinello finisce in "Jan, Joe o Jane era il criminale?" allora sarà molto facile enumerare anche se fai in modo che l'hash impieghi un minuto intero. A meno che l'intero gioco non sia stato scritto tenendo presente questo aspetto e che tutte le domande siano estremamente aperte, ciò costituirà un problema. Ma sì, se le tue domande sono così aperte che lo spazio degli stati è sufficientemente ampio, le risposte possono essere protette.
Chris Hayes,

28

Hai due tre opzioni:

Tieni le risposte separate dal resto del codice sorgente

Se vuoi che il tuo codice sia open source, tuttavia non vuoi che le risposte siano open source, allora apri il codice sorgente per l'applicazione senza domande e risposte, con le domande e le risposte che sono un "plug-in" separato chiuso o file di dati. La tua app Android raggrupperebbe entrambi questi in un'unica app.

Inserisci le risposte nel tuo codice sorgente

In alternativa, se consideri le domande e le risposte come una parte fondamentale di ciò che desideri open source, allora dovresti inserire le risposte nel codice sorgente, preferibilmente non offuscato in modo che altri possano leggerle e modificarle . Offuscare il codice sorgente in modo che non possa essere compreso e modificato non è realmente in linea con i principi del codice open source.

Inserisci le risposte su un server su Internet

Con entrambe le soluzioni di cui sopra è possibile per qualcuno che ha scaricato la tua app trovare le risposte senza riprodurre il programma in entrambi i casi, indipendentemente da come offuscare / crittografare le tue risposte, se il tuo programma è in grado di identificare la risposta senza ulteriori informazioni, quindi può un essere umano esaminare la tua app compilata.

Se vuoi davvero assicurarti che nessuno possa trovare le risposte, l'unica vera opzione è non dare loro le risposte e fare in modo che l'app chiami un servizio web ecc ... ogni volta che vogliono conoscere la risposta. L'app dovrebbe inviare la risposta che l'utente ha inserito e il servizio web dovrebbe dire all'app se la risposta è corretta o meno, in questo modo l'utente non ha modo di dire quale sia la risposta fino a quando non ha già la risposta corretta (breve di forzare brutalmente il servizio Web, che è possibile rilevare e proteggere).

Se stai cercando modi per offuscare le tue risposte, ciò mi suggerisce che non vuoi davvero aprire le tue risposte in primo luogo, quindi dovresti considerare le prime opzioni.

Se è fondamentale che l'utente non sia in grado di trovare la risposta in anticipo, la terza opzione è la tua unica vera scelta, tuttavia faccio fatica a pensare a uno scenario in cui questo varrebbe la pena, anche perché impedisce ai tuoi utenti dall'uso della tua app senza una connessione Internet.


8
Le domande e risposte non devono nemmeno essere un plugin, può essere un semplice file di dati. I file di dati di input non sono necessariamente inclusi come parte del software concesso in licenza e possono essere coperti con la propria licenza separata. Finché fornisci un (diverso) file di dati di esempio da utilizzare con il codice sorgente, non stai ostacolando l'uso gratuito della fonte o dei programmi compilati da detta fonte, e quindi non dovresti violare la GPL.
Doktor J,

Non sono sicuro che risolva davvero il suo problema: se le risposte sono crittografate e codificate nel codice o distribuite come file separato, il codice deve comunque essere in grado di decrittografare le risposte, quindi chiunque scarichi la sua app può fare ciò il codice sorgente fa per ottenere le risposte. (a meno che non siano hash, come suggerito in un'altra risposta)
Johnny,

1
Se l'obiettivo è controllare le risposte e non è necessario che vengano visualizzate, è possibile farlo allo stesso modo delle password con un hash unidirezionale.
JamesRyan,

@Justin, grazie per la tua risposta, e i tuoi commenti sul fatto che costituisca open source sono interessanti. Penso che nascondere le risposte non abbia lo scopo di offuscare il codice sorgente o il funzionamento dell'applicazione, ma piuttosto preservare l'integrità della sfida. La crittografia, a quanto pare, è un mezzo meraviglioso per distribuire indovinelli senza dover essere lì quando l'utente indovina ('è questo, è questo?')
Mai più il

4

Se l'oggetto è quello di oscurare le stringhe dalla lettura casuale del codice sorgente ma tenerle aperte in modo che altre persone possano facilmente apportare le proprie modifiche, ad esempio se si pubblicasse la fonte in un'avventura testuale e non si desiderasse che comparisse alcun testo descrittivo che costituirebbe uno spoiler, quindi utilizzare qualcosa di reversibile come rot13.

In effetti, è possibile ruotare13 tutti i file di traduzione e capovolgerli al volo.

Questo mantiene lo spirito aperto. Gli hash casuali "magici" non sono realmente adatti ai programmatori.


4
Ricorda che molte persone di GeoCaching tra noi leggono rot13 quasi con la stessa fluidità dell'originale.
giovedì

4

L'open source richiede che il codice sorgente sia reso pubblico e disponibile, non i dati di gioco. Quindi potresti facilmente inserire i dati in un altro file e non pubblicarli. Aggiungi un po 'di crittografia se vuoi impedire la lettura casuale del file. Dubito che una forte crittografia sia necessaria per la tua applicazione.


1
In che senso puoi "non pubblicare" i dati di gioco? Il gioco deve essere in grado di accedere a tali dati in modo che chiunque abbia una copia del gioco abbia una copia dei dati. Questo è esattamente ciò che l'editoria è: rendere pubblico.
David Richerby,

1
@DavidRicherby Dipende da cosa si desidera pubblicare e terminare. Quel gioco o il tuo motore che potrebbero essere utilizzati per creare molti giochi simili? Consentire alle persone di manipolare il tuo gioco, ispezionare il codice per falle di sicurezza o semplicemente riutilizzare i componenti? Se la tua interfaccia è semplice come "CSV con q & a + programma = gioco" penso che sia concepibile pubblicare solo il programma, non il CSV.
Raffaello

1
@Raphael Ma distribuire un gioco che consiste in un file eseguibile e in un file di dati di testo semplice non raggiunge l'obiettivo di rendere segrete le risposte. Se vuoi proporre una versione crittografata del file di dati, va bene, purché tutti comprendano che si tratta solo di sicurezza per oscurità (la chiave è nella fonte). Ma poi entriamo nella questione se il testo in chiaro del file di dati costituisca un codice sorgente nel senso della GPL e, a quel punto, la domanda diventa una questione di interpretazione della GPL, piuttosto che di informatica.
David Richerby,

@DavidRicherby: concordato. Tuttavia, sebbene IANAL, dubito fortemente che un file di dati costituito da indovinelli e le loro risposte sarebbe considerato una parte del programma così essenziale e insostituibile che non potrebbe essere concesso in licenza separatamente - soprattutto se si includesse un file di dati di esempio non crittografato in la distribuzione del codice sorgente, insieme alle istruzioni per modificarlo e crittografarlo se necessario, per chiarire che chiunque abbia il codice sorgente può effettivamente creare i propri file di dati personalizzati e usarli con il programma.
Ilmari Karonen,

4

Perché dovresti memorizzare le tue risposte nel tuo codice sorgente GPL se non vuoi che i tuoi utenti le conoscano? Anche se non sono noti o facilmente crackabili ora, possono (e probabilmente lo saranno) in futuro.

Invece di memorizzarli nella tua app, usa un database esterno. Crea un piccolo servizio web che paragona le risposte a ciò che è nel tuo database. Quindi lascia che la tua applicazione faccia una chiamata a quel servizio web ogni volta che deve verificarla. Il problema principale è che, poiché richiede l'accesso a Internet, perderai un po 'di velocità e potenziali utenti. la licenza dell'app dovrebbe essere valida solo per l'app stessa, non per il servizio web.

Potresti anche mettere le tue risposte in un piccolo database e inserirle nel tuo programma. Per quanto ne so, GPL si applica solo al codice sorgente, non a tutti i dati che l'app memorizza. Potrei sbagliarmi, però.


1
"Per quanto ne so, GPL si applica solo al codice sorgente, non ai dati che l'app memorizza". Bene, la GPL dice "Devi licenziare l'intera opera, nel suo insieme, sotto questa Licenza a chiunque entri in possesso di una copia." Quindi potresti pensare che ora dobbiamo decidere se i dati fanno parte del "lavoro completo". Ma in realtà, sicuramente tutte le restrizioni della GPL (compresa quella) si applicano solo ai licenziatari. È bello che anche i licenziatari mantengano lo spirito della GPL, ma non dovrebbero preoccuparsi di una visita della polizia del copyright.
Peter Ford,

1

Ricordare che anche se si memorizza un database in un server Web remoto, è possibile duplicare il database semplicemente annotando tutte le coppie chiave / valore corrette che sono state viste. E in generale, le app mobili dovrebbero cercare di non dare errori o smettere di funzionare perché la rete è inattiva (utilizzare la messaggistica in coda e "aggiorna quando puoi").

Quindi, se vuoi un database locale, ma non ti piace l'idea che venga palesemente decrittografato, puoi usare un filtro bloom (per evitare di parlare con una rete o avere un grande database decrittografato localmente). Questo è il modo in cui i correttori ortografici funzionavano quando lo spazio di memoria era molto ridotto.

Quindi, se aggiungi coppie di domande / risposte nel filtro come:

Hash (NormalizeString (Domanda [n])) + Hash (NormalizeString (risposta [n]))

Se chiedi se "Capitol of Virginia? Richmond" è nel set, o risponderà "sicuramente no", o "quasi certamente sì". Se si ottengono troppi falsi positivi, allargare il database.

Potresti avere un immenso database in un piccolo spazio, supponendo che l'utente scriverà la domanda e la risposta esattamente come previsto. Mantenere piccolo il database aiuta con gli aggiornamenti, perché probabilmente devono essere trasferiti su reti wireless.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.