Menjaga Rahasia String dalam Kode Sumber (Terbuka)

50

Saya telah selesai mengembangkan aplikasi untuk Android dan bermaksud untuk menerbitkannya dengan GPL - Saya ingin itu menjadi open source. Namun, sifat aplikasi (permainan) adalah bahwa ia meminta teka-teki dan memiliki kode jawaban ke sumber daya string. Saya tidak dapat mempublikasikan jawabannya! Saya disuruh melihat ke dalam menyimpan kata sandi dengan aman - tetapi saya belum menemukan sesuatu yang sesuai.

Apakah mungkin untuk mempublikasikan kode sumber saya dengan larik string yang disembunyikan, dienkripsi, atau dikaburkan? Mungkin dengan membaca jawaban dari database online?

Memperbarui

Solusi Yuval Filmus di bawah ini berhasil. Ketika saya pertama kali membacanya, saya masih tidak yakin bagaimana melakukannya. Saya menemukan beberapa solusi, untuk opsi kedua: menyimpan solusi hash di sumber dan menghitung hash setiap kali pengguna menebak. Untuk melakukan ini dalam javascript ada perpustakaan crypto-js di http://code.google.com/p/crypto-js/ . Untuk Android, gunakan fungsi MessageDigest . Ada aplikasi (pada fdroid / github) bernama HashPass yang melakukan ini.

Tidak lagi
sumber
11
Saya heran bagaimana ontopik ini ada di sini; itu mungkin lebih cocok untuk Keamanan Informasi dalam hal apa pun.
Raphael
2
@YuvalFilmus Jangan tertipu oleh suara "Pertanyaan Panas". Tapi poin diambil.
Raphael
4
Detail penting yang hilang di sini adalah: Apakah Anda hanya ingin memverifikasi jawaban pengguna atau Anda ingin dapat mencetak jawaban yang benar juga? Dan, apakah Anda memerlukan fuzzine, atau hanya ada satu set jawaban yang benar dan terbatas (sehingga Anda dapat memeriksa jawaban pengguna terhadap set ini satu-per-satu)?
hyde
4
Semua jawaban menanyakan masalah apa yang ingin Anda pecahkan. Mengapa Anda tidak dapat mempublikasikan jawabannya?
Rhymoid
1
Apa yang harus dilakukan kode Anda dengan string ini? Apakah itu harus dapat memecahkan kode mereka? Atau apakah bisa membandingkan string dengan mereka cukup?
David Schwartz

Jawaban:

83

Anda memiliki setidaknya dua opsi, tergantung pada masalah apa yang ingin Anda selesaikan.

Jika Anda ingin pembaca kode Anda yang tidak bersalah tidak mendapatkan jawaban secara tidak sengaja, atau setidaknya Anda ingin membuatnya sedikit sulit sehingga pengguna tidak tergoda, Anda dapat mengenkripsi solusi dan menyimpan kunci sebagai bagian dari kode Anda, mungkin sebuah hasil dari beberapa perhitungan (untuk membuatnya lebih sulit).

Jika Anda ingin mencegah pengguna mengambil jawaban, Anda dapat menggunakan fungsi satu arah, atau dalam jargon komputer, fungsi hash . Simpan hash dari jawabannya, dan mereka dapat Anda uji apakah jawabannya benar tanpa memungkinkan untuk menyimpulkan jawabannya sama sekali tanpa menemukannya terlebih dahulu. Ini memiliki kekurangan bahwa lebih sulit untuk memeriksa jawaban yang dekat dengan jawaban yang benar, meskipun ada beberapa solusi bahkan untuk masalah ini.

Yuval Filmus
sumber
9
Satu hal yang saya tambahkan adalah bahwa jika Anda membutuhkan keamanan lebih, setiap jawaban mungkin harus diasinkan dengan garam yang berbeda. Ini menghindari serangan kamus terhadap semua jawaban sekaligus. Jika Anda ingin melihat bagaimana orang-orang crypto "nyata" melakukannya, lihat sistem String-to-Key di OpenPGP .
Nama samaran
1
Menyimpan hash dalam kode berarti semua informasi bersifat statis dan garam / apa pun yang lain juga akan tersedia. Saya percaya sebagai hasilnya akan masuk akal jika ruang jawaban cukup besar (seperti kisaran penuh nilai integer 32-bit), jika tidak (yaitu dalam kasus pertanyaan pilihan ganda) tabel pelangi akan dengan cepat memberikan jawaban yang benar.
Alexei Levenkov
3
Seperti yang ditunjukkan oleh Alexei, jika input Anda yang mungkin menjangkau ruang kecil, menyimpan jawaban dalam kode akan membukanya bagi penyerang tertentu - dan saya kira sebagian besar teka-teki akan memiliki ruang negara yang agak kecil, karena jawaban mereka umumnya harus baik kata-kata atau angka yang relatif kecil. Anda dapat hash atau mengenkripsi untuk menghindari kesalahan yang tidak bersalah, tetapi tidak ada yang mencegah seseorang mendapatkan jawaban yang benar-benar menginginkannya. (Plus, mereka hanya bisa bertanya pada seseorang yang sudah memecahkan teka-teki Anda!)
Chris Hayes
4
Untuk mengatasi apa yang disebutkan oleh Chris, Anda dapat memilih proses hashing yang sangat lambat, katakan dibutuhkan 100 ms (itu pendekatan yang diambil oleh beberapa standar PK). Ini masih sangat cepat dari perspektif pengguna, tetapi membuat pencacahan jauh lebih sulit.
Yuval Filmus
12
@YuvalFilmus Lagi, sampai batas tertentu. Jika teka-teki Anda berakhir dengan "Apakah Jan, Joe, atau Jane kriminal?" maka akan sangat mudah untuk menghitung bahkan jika Anda membuat hash mengambil satu menit penuh. Kecuali seluruh permainan ditulis dengan pemikiran ini, dan semua pertanyaannya sangat terbuka, ini akan menimbulkan masalah. Tapi ya, jika pertanyaan Anda adalah bahwa terbuka bahwa negara ruang cukup besar, jawaban dapat dilindungi.
Chris Hayes
28

Anda memiliki dua tiga opsi:

Pisahkan jawaban dari kode sumber lainnya

Jika Anda ingin kode Anda menjadi open source, namun tidak ingin jawaban menjadi open source, maka Anda open source kode untuk aplikasi tanpa pertanyaan & jawaban, dengan pertanyaan & jawaban menjadi "plugin" sumber tertutup yang terpisah. atau file data. Aplikasi Android Anda akan menggabungkan keduanya menjadi satu aplikasi.

Masukkan jawaban dalam kode sumber Anda

Atau, jika Anda menganggap pertanyaan dan jawaban sebagai bagian inti dari apa yang Anda inginkan bersumber terbuka maka Anda harus memasukkan jawaban ke dalam kode sumber, lebih disukai tidak dikaburkan sehingga orang lain dapat membaca dan memodifikasinya . Mengaburkan kode sumber sehingga tidak dapat dipahami dan dimodifikasi tidak benar-benar sesuai dengan prinsip-prinsip kode sumber terbuka.

Letakkan jawaban di server di internet

Dengan kedua solusi di atas, ada kemungkinan bagi seseorang yang telah mengunduh aplikasi Anda untuk menemukan jawabannya tanpa memainkan program Anda dalam kedua kasus - tidak peduli bagaimana Anda mengaburkan / mengenkripsi jawaban Anda, jika program Anda dapat mengidentifikasi jawaban tanpa informasi tambahan, maka dapat manusia memeriksa aplikasi yang dikompilasi.

Jika Anda benar - benar ingin memastikan bahwa tidak ada yang bisa mengetahui jawabannya maka satu-satunya pilihan nyata adalah tidak memberi mereka jawaban dan meminta aplikasi memanggil layanan web dll ... setiap kali mereka ingin tahu jawabannya. Aplikasi harus mengirim jawaban yang telah dimasukkan pengguna dan layanan web harus memberi tahu aplikasi apakah jawabannya benar atau tidak, sehingga pengguna tidak memiliki cara untuk mengatakan apa jawabannya sampai setelah mereka memiliki jawaban yang benar (singkat). dari memaksa layanan web, yang dapat Anda deteksi dan lindungi).

Jika Anda mencari cara untuk mengaburkan jawaban Anda, yang menunjukkan kepada saya bahwa Anda tidak benar-benar ingin membuka sumber jawaban Anda di tempat pertama, jadi Anda harus mempertimbangkan opsi pertama.

Jika sangat penting bahwa pengguna tidak dapat menemukan jawaban di muka maka opsi ketiga adalah satu-satunya pilihan Anda, namun saya berjuang untuk memikirkan skenario di mana ini sepadan dengan usaha, paling tidak karena itu mencegah pengguna Anda dari menggunakan aplikasi Anda tanpa koneksi internet.

Justin
sumber
8
T&J bahkan tidak harus menjadi plugin, itu bisa berupa file data sederhana. File data input tidak harus dimasukkan sebagai bagian dari perangkat lunak berlisensi dan dapat dicakup dalam lisensi terpisah mereka sendiri. Selama Anda memberikan file data sampel (berbeda) untuk digunakan dengan kode sumber, Anda tidak menghalangi penggunaan bebas dari sumber atau program yang dikompilasi dari sumber tersebut, dan dengan demikian tidak boleh melanggar GPL.
Doktor J
Saya tidak yakin benar-benar menyelesaikan masalahnya - apakah jawaban dienkripsi dan dikodekan dalam kode atau didistribusikan sebagai file terpisah, kode tersebut masih harus dapat mendekripsi jawaban, sehingga siapa pun yang mengunduh aplikasinya dapat melakukan apa kode sumber tidak sampai ke jawaban. (kecuali jika hash, seperti yang disarankan dalam jawaban lain)
Johnny
1
Jika tujuannya adalah untuk memeriksa jawaban dan tidak mengharuskan mereka untuk ditampilkan maka itu dapat dilakukan dengan cara yang sama seperti kata sandi dengan hash satu arah.
JamesRyan
@Justin, terima kasih atas jawaban Anda, dan komentar Anda tentang apakah itu merupakan open source menarik. Saya pikir menyembunyikan jawaban tidak dimaksudkan untuk mengaburkan kode sumber, atau cara kerja aplikasi, tetapi untuk menjaga keutuhan tantangan. Kriptografi, ternyata, adalah cara yang luar biasa untuk mendistribusikan teka-teki tanpa harus berada di sana ketika pengguna menebak ('apakah ini, apakah ini?')
Nevermore
4

Jika objeknya adalah untuk mengaburkan string dari pembacaan kasual kode sumber tetapi tetap buka sehingga orang lain dapat dengan mudah membuat perubahan sendiri - misalnya jika Anda menerbitkan sumber ke petualangan teks dan tidak ingin teks deskriptif muncul yang akan membentuk spoiler, kemudian gunakan sesuatu yang dapat dibalik seperti rot13.

Bahkan, Anda dapat memutar semua file terjemahan dan membalikkannya dengan cepat.

Itu menjaga semangat terbuka. Hash "magic" acak tidak benar-benar ramah-programmer.

moopet
sumber
4
Ingatlah bahwa banyak orang GeoCaching di antara kita membaca rot13 yang hampir lancar seperti aslinya.
yo '
4

Open source membutuhkan kode sumber untuk dipublikasikan dan tersedia, bukan data game. Jadi Anda bisa dengan mudah memasukkan data ke file lain dan tidak mempublikasikannya. Tambahkan beberapa crypto jika Anda ingin mencegah pembacaan file yang biasa saja. Saya ragu crypto yang kuat diperlukan untuk aplikasi Anda.

Liftarn
sumber
1
Dalam hal apa Anda bisa "tidak mempublikasikan" data game? Gim harus dapat mengakses data tersebut sehingga siapa pun yang memiliki salinan gim tersebut memiliki salinan data tersebut. Seperti itulah tepatnya penerbitan: mempublikasikan.
David Richerby
1
@ DavidRicherby Tergantung pada apa yang ingin Anda terbitkan dan untuk mengakhiri. Bahwa permainan atau mesin Anda yang dapat digunakan untuk membuat banyak permainan yang sama? Izinkan orang untuk memanipulasi permainan Anda, periksa kode untuk lubang keamanan atau hanya menggunakan kembali komponen? Jika antarmuka Anda sesederhana "CSV dengan q & a + program = game" Saya pikir mungkin untuk hanya mempublikasikan program, bukan CSV.
Raphael
1
@Raphael Tetapi mendistribusikan game yang terdiri dari file data teks yang dapat dieksekusi dan polos tidak mencapai tujuan untuk membuat rahasia jawabannya. Jika Anda ingin mengajukan versi datafile yang dienkripsi, tidak apa-apa, selama semua orang mengerti bahwa ini hanya keamanan dengan ketidakjelasan (kuncinya ada di sumber). Tapi kemudian kita masuk ke pertanyaan apakah plaintext dari datafile merupakan kode sumber dalam arti GPL dan, pada saat itu, pertanyaannya menjadi masalah interpretasi GPL, daripada ilmu komputer.
David Richerby
@ DavidRicherby: Setuju. Namun, meskipun IANAL, saya sangat meragukan bahwa file data yang terdiri dari teka-teki dan jawaban mereka akan dianggap sebagai bagian yang penting dan tidak tergantikan dari program yang tidak dapat dilisensikan secara terpisah - terutama jika Anda menyertakan file data sampel yang tidak dienkripsi dalam distribusi sumber, bersama dengan instruksi untuk memodifikasi dan mengenkripsi itu jika perlu, untuk memperjelas bahwa siapa pun dengan kode sumber memang dapat membuat file data mereka sendiri yang disesuaikan dan menggunakannya dengan program.
Ilmari Karonen
4

Mengapa Anda menyimpan jawaban Anda dalam kode sumber GPL Anda jika Anda tidak ingin pengguna mengetahuinya? Bahkan jika mereka tidak dikenal atau mudah retak sekarang, mereka dapat (dan kemungkinan akan) ada di masa depan.

Alih-alih menyimpannya di aplikasi Anda, gunakan database eksternal. Buat layanan web kecil yang membandingkan jawaban untuk apa yang ada di database Anda. Lalu biarkan aplikasi Anda melakukan panggilan ke layanan web itu setiap kali harus diverifikasi. Masalah utama adalah bahwa, karena memerlukan akses internet, Anda akan kehilangan beberapa kecepatan dan potensi penggunaan. lisensi aplikasi Anda seharusnya hanya berlaku untuk aplikasi itu sendiri, bukan layanan web.

Anda juga bisa memasukkan jawaban Anda ke dalam basis data kecil dan memasukkannya ke dalam program Anda. Sejauh yang saya tahu, GPL hanya berlaku untuk kode sumber, bukan data apa pun yang disimpan aplikasi Anda. Tapi saya mungkin salah tentang itu.

Nzall
sumber
1
"Sejauh yang saya tahu, GPL hanya berlaku untuk kode sumber, bukan data apa pun yang disimpan aplikasi Anda". Nah, GPL mengatakan, "Anda harus melisensikan seluruh pekerjaan, secara keseluruhan, di bawah Lisensi ini kepada siapa saja yang memiliki salinan." Jadi Anda mungkin berpikir sekarang kita perlu memutuskan apakah data merupakan bagian dari "seluruh pekerjaan". Tetapi sebenarnya, tentu saja semua pembatasan GPL (termasuk yang itu) hanya berlaku untuk pemegang lisensi. Sangat menyenangkan bagi pemberi lisensi untuk tetap menjaga semangat GPL, tetapi mereka tidak perlu khawatir tentang kunjungan dari polisi hak cipta.
Peter Ford
1

Ingatlah bahwa bahkan jika Anda menyimpan database di server web jarak jauh, database tersebut masih dapat diduplikasi hanya dengan menuliskan semua pasangan kunci / nilai yang benar yang telah dilihat. Dan secara umum, aplikasi seluler harus mencoba untuk tidak memberikan kesalahan atau berhenti berfungsi karena jaringannya mati (gunakan pesan yang antri, dan "perbarui bila Anda bisa").

Jadi, jika Anda menginginkan database lokal, tetapi tidak suka ide itu didekripsi secara terang-terangan, Anda dapat menggunakan filter bloom (untuk menghindari berbicara dengan jaringan atau memiliki database yang didekripsi secara lokal). Ini adalah bagaimana pemeriksa ejaan digunakan untuk bekerja ketika ruang memori benar-benar ketat.

Jadi, jika Anda menambahkan pasangan pertanyaan / jawaban ke dalam filter seperti:

Hash (NormalizeString (Pertanyaan [n])) + Hash (NormalizeString (Jawab [n]))

Jika Anda bertanya apakah "Capitol of Virginia? Richmond" ada di set, itu akan menjawab "pasti tidak", atau "hampir pasti ya". Jika Anda mendapatkan terlalu banyak false positive, maka buat database lebih besar.

Anda bisa memiliki database yang sangat besar di ruang yang kecil, dengan asumsi bahwa pengguna akan mengeja Pertanyaan dan Jawaban persis seperti yang Anda harapkan. Menjaga basis data kecil membantu dengan pembaruan, karena mereka mungkin harus ditransfer melalui jaringan nirkabel.

rampok
sumber