Zachowanie sekretu łańcucha w (otwartym) kodzie źródłowym

50

Skończyłem opracowywać aplikację na Androida i zamierzam opublikować ją na GPL - chcę, żeby była open source. Jednak natura aplikacji (gry) polega na tym, że zadaje ona zagadki i ma zakodowane odpowiedzi w zasobie łańcucha. Nie mogę opublikować odpowiedzi! Powiedziano mi, żebym szukał bezpiecznego przechowywania haseł - ale nie znalazłem nic odpowiedniego.

Czy jest możliwe opublikowanie mojego kodu źródłowego z ukrytą, zaszyfrowaną lub w inny sposób zasłoniętą tablicą łańcuchów? Może czytając odpowiedzi z internetowej bazy danych?

Aktualizacja

Rozwiązanie Yuval Filmusa poniżej zadziałało. Kiedy po raz pierwszy to przeczytałem, nadal nie byłem pewien, jak to zrobić. Znalazłem kilka rozwiązań dla drugiej opcji: przechowywanie zaszyfrowanego rozwiązania w źródle i obliczanie skrótu za każdym razem, gdy użytkownik zgadnie. Aby to zrobić w javascript, jest biblioteka crypto-js pod adresem http://code.google.com/p/crypto-js/ . W systemie Android użyj funkcji MessageDigest . Istnieje aplikacja (na fdroid / github) o nazwie HashPass, która to robi.

Nigdy więcej
źródło
11
Zastanawiam się, jak tu jest ontopic; w każdym przypadku może być lepiej dostosowane do bezpieczeństwa informacji .
Raphael
2
@YuvalFilmus Nie daj się zwieść głosom „Hot Question”. Ale uwaga.
Raphael
4
Brakuje tutaj ważnych informacji: czy chcesz tylko zweryfikować odpowiedzi użytkowników, czy też chcesz wydrukować poprawną odpowiedź? I czy potrzebujesz jakichś fuzzusów, czy jest tylko wyraźny, ograniczony zestaw poprawnych odpowiedzi (które pozwalają sprawdzić odpowiedź użytkownika względem tego zestawu jeden po drugim)?
hyde
4
Wszystkie odpowiedzi pytają, jaki problem chcesz rozwiązać. Dlaczego nie możesz opublikować odpowiedzi?
Rhymoid
1
Co twój kod musi zrobić z tymi ciągami? Czy musi być w stanie je rozszyfrować? Czy jest w stanie porównać do nich ciągi znaków?
David Schwartz

Odpowiedzi:

83

Masz co najmniej dwie opcje, w zależności od problemu, który chcesz rozwiązać.

Jeśli chcesz, aby niewinni czytelnicy twojego kodu nie otrzymali nieumyślnie odpowiedzi, lub przynajmniej sprawisz, że będzie to trochę trudne, aby użytkownicy nie ulegali pokusie, możesz zaszyfrować rozwiązania i przechowywać klucz jako część kodu, być może wynik niektórych obliczeń (aby uczynić to jeszcze trudniejszym).

Jeśli chcesz uniemożliwić użytkownikom uzyskanie odpowiedzi, możesz użyć funkcji jednokierunkowej lub, w żargonie komputerowym, funkcji skrótu . Przechowywanie hash odpowiedź, i można sprawdzić, czy odpowiedź jest prawidłowa bez możliwości wydedukować odpowiedź w ogóle bez znalezienia go w pierwszej kolejności. Ma to tę wadę, że trudniej jest znaleźć odpowiedź zbliżoną do poprawnej, chociaż istnieją pewne rozwiązania nawet tego problemu.

Yuval Filmus
źródło
9
Dodam tylko, że jeśli potrzebujesz jeszcze większego bezpieczeństwa, każda odpowiedź powinna być solona z inną solą. Pozwala to uniknąć ataku słownikowego na wszystkie odpowiedzi naraz. Jeśli chcesz zobaczyć, jak robią to „prawdziwi” ludzie kryptowalut, spójrz na system String-to-Key w OpenPGP .
Pseudonim
1
Trzymanie skrótów w kodzie oznacza, że ​​wszystkie informacje są statyczne i słone / cokolwiek innego będzie również łatwo dostępne. Uważam, że w rezultacie rozsądne byłoby, gdyby przestrzeń odpowiedzi była wystarczająco duża (jak pełny zakres 32-bitowych wartości całkowitych), w przeciwnym razie (tj. W przypadku pytań wielokrotnego wyboru) tablica tęczy szybko dałaby prawidłowe odpowiedzi.
Alexei Levenkov
3
Jak zauważa Aleksiej, jeśli twoje możliwe dane wejściowe obejmują niewielką przestrzeń, przechowywanie odpowiedzi w kodzie otworzy je dla każdego zdeterminowanego atakującego - i domyślam się, że większość zagadek będzie miała raczej małe przestrzenie stanów, ponieważ ich odpowiedzi na ogół muszą być albo słowa, albo stosunkowo małe liczby. Możesz mieszać lub szyfrować, aby uniknąć niewinnych błędów, ale nic nie stoi na przeszkodzie, aby ktoś uzyskał odpowiedź, która naprawdę tego chce. (Plus, mogą po prostu zapytać kogoś, kto już rozwiązał twoją zagadkę!)
Chris Hayes,
4
Aby przeciwstawić się temu, o czym wspomina Chris, możesz wybrać proces mieszania, który jest bardzo powolny, powiedzmy, że zajmuje to 100 ms (takie podejście przyjmują niektóre standardy PK). Jest to wciąż bardzo szybkie z punktu widzenia użytkownika, ale znacznie utrudnia wyliczanie.
Yuval Filmus
12
@YuvalFilmus Znowu do pewnego stopnia. Jeśli twoja zagadka kończy się na „Czy Jan, Joe czy Jane był przestępcą?” to będzie bardzo łatwe do wyliczenia, nawet jeśli sprawisz, że hasz zajmie pełną minutę. O ile cała gra nie jest napisana z myślą o tym, a wszystkie pytania są wyjątkowo otwarte, będzie to stanowić problem. Ale tak, jeśli twoje pytania tak otwarte, że przestrzeń stanu jest wystarczająco duża, odpowiedzi można chronić.
Chris Hayes,
28

Masz dwie trzy opcje:

Zachowaj odpowiedzi oddzielnie od reszty kodu źródłowego

Jeśli chcesz, aby Twój kod był open source, jednak nie chcesz, aby odpowiedzi były open source, to możesz otworzyć kod źródłowy aplikacji bez pytań i odpowiedzi, przy czym pytania i odpowiedzi są osobną „wtyczką” zamkniętego źródła. lub plik danych. Twoja aplikacja na Androida połączy oba te elementy w jedną aplikację.

Umieść odpowiedzi w kodzie źródłowym

Ewentualnie, jeśli uważasz, że pytania i odpowiedzi są kluczową częścią tego, co chcesz, aby były dostępne, należy umieścić odpowiedzi w kodzie źródłowym, najlepiej nie zaciemniać, aby inni mogli je przeczytać i zmodyfikować . Zaciemnianie kodu źródłowego, aby nie można go było zrozumieć i zmodyfikować, nie jest tak naprawdę zgodne z zasadami otwartego kodu źródłowego.

Umieść odpowiedzi na serwerze w Internecie

Dzięki obu powyższym rozwiązaniom osoba, która pobrała aplikację, może znaleźć odpowiedzi bez odtwarzania programu w obu przypadkach - bez względu na to, jak zaciemnisz / zaszyfrujesz swoje odpowiedzi, jeśli Twój program może zidentyfikować odpowiedź bez dodatkowych informacji, więc może człowiek sprawdzający twoją skompilowaną aplikację.

Jeśli naprawdę chcesz się upewnić, że nikt nie może znaleźć odpowiedzi, jedyną prawdziwą opcją jest nie dać im odpowiedzi i wezwać aplikację do usługi internetowej itp., Ilekroć chcą poznać odpowiedź. Aplikacja powinna wysłać odpowiedź, którą podał użytkownik, a usługa internetowa powinna powiedzieć aplikacji, czy odpowiedź jest poprawna, w ten sposób użytkownik nie będzie w stanie powiedzieć, jaka jest odpowiedź, dopóki nie uzyska poprawnej odpowiedzi (krótka brutalnego wymuszania usługi internetowej, którą można wykryć i chronić przed nią).

Jeśli szukasz sposobów zaciemnienia swoich odpowiedzi, to sugeruje mi, że tak naprawdę nie chcesz w ogóle otwierać swoich źródeł, więc powinieneś rozważyć pierwsze opcje.

Jeśli jest to krytyczny , że użytkownik nie będzie w stanie znaleźć odpowiedź z góry następnie trzecia opcja to jedyny prawdziwy wybór, ale jestem stara się myśleć o sytuacji, w której byłoby to warte wysiłku, choćby dlatego, że uniemożliwia użytkownikom z korzystania z aplikacji bez połączenia z Internetem.

Justin
źródło
8
Pytania i odpowiedzi nie muszą nawet być wtyczką, może to być zwykły plik danych. Pliki danych wejściowych niekoniecznie są dołączane jako część licencjonowanego oprogramowania i mogą być objęte własną osobną licencją. Tak długo, jak podasz (inny) przykładowy plik danych do użycia z kodem źródłowym, nie utrudnisz swobodnego korzystania ze źródła lub programów skompilowanych z tego źródła, a zatem nie powinno to naruszać GPL.
Doktor J
Nie jestem pewien, czy to naprawdę rozwiązuje jego problem - niezależnie od tego, czy odpowiedzi są zaszyfrowane i zakodowane na stałe w kodzie, czy też rozprowadzone jako osobny plik, kod nadal musi być w stanie odszyfrować odpowiedzi, więc każdy, kto pobierze jego aplikację, może zrobić kod źródłowy robi, aby uzyskać odpowiedzi. (chyba że są one mieszane, jak sugerowano w innej odpowiedzi)
Johnny
1
Jeśli celem jest sprawdzenie odpowiedzi i nie wymaga ich wyświetlenia, można to zrobić w taki sam sposób, jak hasła z haszem jednokierunkowym.
JamesRyan
@Justin, dziękuję za odpowiedź, a twoje komentarze na temat tego, czy stanowi on open source, są interesujące. Myślę, że ukrywanie odpowiedzi nie ma na celu zaciemnienia kodu źródłowego ani sposobu działania aplikacji, ale raczej zachowanie integralności wyzwania. Jak się okazuje, kryptografia to wspaniały sposób na rozpowszechnianie zagadek bez konieczności bycia tam, gdy użytkownik zgadnie („czy to jest to, prawda?”)
Nevermore,
4

Jeśli celem jest zasłonięcie ciągów przed przypadkowym odczytaniem kodu źródłowego, ale utrzymanie ich otwartości, aby inni ludzie mogli łatwo wprowadzić własne zmiany - na przykład, jeśli publikujesz źródło w przygodzie tekstowej i nie chcesz, aby pojawiał się tekst opisowy który stanowiłby spoiler, a następnie użyłby czegoś odwracalnego, takiego jak zgnilizna.

W rzeczywistości możesz zepsuć 13 wszystkich plików tłumaczeń i odwrócić je w locie.

To utrzymuje otwartego ducha. Losowe „magiczne” skróty nie są tak naprawdę przyjazne programistom.

moopet
źródło
4
Pamiętaj, że wielu ludzi z GeoCaching czytało rot13 prawie tak płynnie, jak oryginał.
yo „
4

Otwarte źródło wymaga podania kodu źródłowego do publicznej wiadomości i udostępnienia go, a nie danych gry. Możesz więc łatwo umieścić dane w innym pliku i nie publikować tego. Dodaj krypto, jeśli chcesz zapobiec przypadkowemu odczytaniu pliku. Wątpię, aby do twojej aplikacji potrzebny był silny szyfr.

liftarn
źródło
1
W jakim sensie możesz „nie publikować” danych gry? Gra musi mieć dostęp do tych danych, aby każdy, kto ma kopię gry, miał kopię tych danych. To właściwie dokładnie to, co publikowanie: upublicznianie.
David Richerby
1
@DavidRicherby Zależy od tego, co chcesz opublikować i zakończyć. Ta gra lub silnik, którego można użyć do stworzenia wielu podobnych gier? Zezwalać innym na manipulowanie grą, sprawdzanie kodu pod kątem dziur w zabezpieczeniach lub ponowne użycie komponentów? Jeśli twój interfejs jest tak prosty jak „CSV z programem Q&A + = gra”, myślę, że można opublikować tylko program, a nie CSV.
Raphael
1
@Raphael Ale dystrybucja gry, która składa się z pliku wykonywalnego i zwykłego pliku danych tekstowych, nie osiąga celu, aby ukryć odpowiedzi. Jeśli chcesz zaproponować zaszyfrowaną wersję pliku danych, nic nie szkodzi, o ile wszyscy rozumieją, że jest to tylko bezpieczeństwo przez zaciemnienie (klucz znajduje się w źródle). Ale wtedy dochodzimy do pytania, czy zwykły tekst pliku danych stanowi kod źródłowy w rozumieniu GPL, i w tym momencie pytanie staje się kwestią interpretacji GPL, a nie informatyki.
David Richerby
@DavidRicherby: Zgoda. Mimo to, choć IANAL, bardzo wątpię, aby plik danych składający się z zagadek i ich odpowiedzi był uważany za tak istotną i niezastąpioną część programu, że nie można by na niego osobno uzyskać licencji - zwłaszcza jeśli w pliku dołączono niezaszyfrowany przykładowy plik danych dystrybucję źródłową, wraz z instrukcjami modyfikacji i szyfrowania, jeśli to konieczne, aby było jasne, że każdy z kodem źródłowym może rzeczywiście tworzyć własne pliki danych i używać ich z programem.
Ilmari Karonen
4

Dlaczego przechowujesz swoje odpowiedzi w kodzie źródłowym GPL, jeśli nie chcesz, aby użytkownicy je znali? Nawet jeśli nie są one obecnie znane lub łatwo można je rozdzielić, mogą (i prawdopodobnie będą) istnieć w przyszłości.

Zamiast przechowywać je w aplikacji, użyj zewnętrznej bazy danych. Stwórz małą usługę internetową, która porównuje odpowiedzi z zawartością bazy danych. Następnie pozwól swojej aplikacji nawiązać połączenie z tą usługą internetową, ilekroć będzie musiała to zweryfikować. Głównym problemem jest to, że ponieważ wymaga dostępu do Internetu, stracisz trochę prędkości i potencjalnej bazy użytkowników. Twoja licencja na aplikację powinna mieć zastosowanie tylko do samej aplikacji, a nie do usługi internetowej.

Możesz także umieścić swoje odpowiedzi w małej bazie danych i umieścić je w swoim programie. O ile mi wiadomo, GPL dotyczy tylko kodu źródłowego, a nie danych przechowywanych przez Twoją aplikację. Mogę się jednak mylić.

Nzall
źródło
1
„O ile mi wiadomo, GPL dotyczy tylko kodu źródłowego, a nie danych przechowywanych przez Twoją aplikację”. Cóż, GPL mówi: „Musisz udzielić licencji na całe dzieło jako całość na podstawie niniejszej Licencji każdemu, kto wejdzie w posiadanie kopii”. Możesz więc pomyśleć, że musimy teraz zdecydować, czy dane są częścią „całej pracy”. Ale w rzeczywistości z pewnością wszystkie ograniczenia GPL (w tym również te) dotyczą tylko licencjobiorców. Licencjodawcy dobrze jest też trzymać się ducha GPL, ale nie powinni się martwić wizytą policji praw autorskich.
Peter Ford
1

Pamiętaj, że nawet jeśli przechowujesz bazę danych na zdalnym serwerze WWW, bazę danych nadal można powielić, po prostu zapisując wszystkie poprawne pary klucz / wartość, które były widoczne. Mówiąc ogólnie, aplikacje mobilne powinny starać się nie zgłaszać błędów lub przestać działać, ponieważ sieć nie działa (używaj wiadomości w kolejce i „aktualizuj, kiedy możesz”).

Jeśli więc chcesz mieć lokalną bazę danych, ale nie podoba ci się pomysł jej rażącego odszyfrowania, możesz użyć filtra Bloom (aby uniknąć rozmowy z siecią lub posiadania dużej odszyfrowanej bazy danych lokalnie). Tak działały sprawdzania pisowni, gdy przestrzeń pamięci była naprawdę mała.

Jeśli dodasz do pytania pary pytanie / odpowiedź, takie jak:

Hash (NormalizeString (Pytanie [n])) + Hash (NormalizeString (Odpowiedź [n]))

Jeśli zapytasz, czy „Capitol of Virginia? Richmond” jest w zestawie, odpowie albo „zdecydowanie nie”, albo „prawie na pewno tak”. Jeśli otrzymasz zbyt wiele wyników fałszywie dodatnich, powiększ bazę danych.

Możesz mieć ogromną bazę danych w niewielkiej przestrzeni, zakładając, że użytkownik przeliteruje pytanie i odpowiedź dokładnie tak, jak się spodziewasz. Utrzymywanie małej bazy danych pomaga w aktualizacjach, ponieważ prawdopodobnie muszą być przesyłane przez sieci bezprzewodowe.

Obrabować
źródło