การรักษาความลับของสตริงในซอร์สโค้ด (เปิด)


50

ฉันได้พัฒนาแอพสำหรับ Android และตั้งใจที่จะเผยแพร่มันด้วย GPL - ฉันต้องการให้มันเป็นโอเพนซอร์ส อย่างไรก็ตามลักษณะของแอปพลิเคชั่น (เกม) คือมันจะถามปริศนาและมีคำตอบที่เข้ารหัสลงในทรัพยากรสตริง ฉันไม่สามารถเผยแพร่คำตอบได้! ฉันได้รับคำสั่งให้ดูที่การเก็บรหัสผ่านอย่างปลอดภัย - แต่ฉันไม่พบสิ่งที่เหมาะสม

เป็นไปได้ไหมที่จะเผยแพร่ซอร์สโค้ดของฉันด้วยอาร์เรย์สตริงที่ซ่อนเข้ารหัสหรือถูกบดบัง บางทีการอ่านคำตอบจากฐานข้อมูลออนไลน์

ปรับปรุง

โซลูชันของ Yuval Filmus ด้านล่างใช้งานได้ เมื่อฉันอ่านครั้งแรกฉันยังไม่แน่ใจว่าจะทำอย่างไร ฉันพบโซลูชันบางอย่างสำหรับตัวเลือกที่สอง: การจัดเก็บโซลูชันแฮชในแหล่งที่มาและคำนวณแฮชทุกครั้งที่ผู้ใช้คาดเดา การทำเช่นนี้ใน JavaScript มีห้องสมุดการเข้ารหัสลับ js ที่http://code.google.com/p/crypto-js/ สำหรับ Android ให้ใช้ฟังก์ชันMessageDigest มีแอปพลิเคชัน (บน fdroid / github) เรียกว่าHashPassซึ่งทำสิ่งนี้


11
ฉันสงสัยว่าเรื่องนี้อยู่ที่นี่เพียงใด มันอาจจะเหมาะสมกว่าความปลอดภัยของข้อมูลในทุกกรณี
ราฟาเอล

2
@YuvalFilmus อย่าถูกหลอกด้วยการโหวต "คำถามยอดนิยม" แต่จุดที่ถ่าย
Raphael

4
รายละเอียดที่สำคัญที่ขาดหายไปคือ: คุณต้องการตรวจสอบคำตอบของผู้ใช้หรือไม่หรือต้องการพิมพ์คำตอบที่ถูกต้องด้วยหรือไม่? และคุณต้องการฟัซซีนหรือไม่หรือมีเพียงชุดคำตอบที่ถูกต้องชัดเจน (ซึ่งคุณสามารถตรวจสอบคำตอบของผู้ใช้กับชุดนี้ทีละชุด)
ไฮด์

4
คำตอบทั้งหมดจะถามว่าคุณต้องการแก้ไขปัญหาอะไร ทำไมคุณไม่เผยแพร่คำตอบ?
Rhymoid

1
รหัสของคุณต้องทำอะไรกับสตริงเหล่านี้ มันจำเป็นต้องสามารถถอดรหัสได้หรือไม่? หรือความสามารถในการเปรียบเทียบสตริงกับพวกเขาเพียงพอหรือไม่
David Schwartz

คำตอบ:


83

คุณมีอย่างน้อยสองตัวเลือกขึ้นอยู่กับปัญหาที่คุณต้องการแก้ไข

หากคุณต้องการให้ผู้อ่านโค้ดของคุณไม่ได้รับคำตอบโดยไม่ตั้งใจหรืออย่างน้อยก็ต้องการทำให้มันยากขึ้นเล็กน้อยเพื่อให้ผู้ใช้ไม่ถูกล่อลวงคุณสามารถเข้ารหัสโซลูชันและเก็บคีย์เป็นส่วนหนึ่งของรหัสของคุณ ผลลัพธ์ของการคำนวณบางอย่าง (เพื่อทำให้ยากยิ่งขึ้น)

หากคุณต้องการที่จะป้องกันไม่ให้ผู้ใช้จากการเรียกคำตอบที่คุณสามารถใช้ฟังก์ชั่นทางเดียวหรือในศัพท์แสงคอมพิวเตอร์เป็นฟังก์ชันแฮช เก็บแฮชของคำตอบและคุณสามารถทดสอบว่าคำตอบนั้นถูกต้องหรือไม่หากไม่สามารถสรุปคำตอบได้เลยโดยไม่ต้องค้นหาก่อน นี่เป็นข้อเสียที่ยากที่จะตรวจสอบคำตอบที่ใกล้เคียงกับคำตอบที่ถูกต้องแม้ว่าจะมีวิธีแก้ปัญหาบางอย่างแม้แต่กับปัญหานี้


9
สิ่งหนึ่งที่ฉันเพิ่มคือถ้าคุณต้องการความปลอดภัยมากขึ้นคำตอบแต่ละข้อควรจะเค็มด้วยเกลือที่แตกต่างกัน วิธีนี้จะช่วยป้องกันการโจมตีจากพจนานุกรมสำหรับคำตอบทั้งหมดในครั้งเดียว หากคุณต้องการที่จะเห็นว่า "ของจริง" คนเข้ารหัสลับทำมันจะดูที่ระบบ String การสำคัญในการ OpenPGP
นามแฝง

1
การเก็บรหัสแฮชในโค้ดหมายถึงข้อมูลทั้งหมดเป็นแบบสแตติกและเกลือ / สิ่งอื่น ๆ ก็จะพร้อมใช้งานเช่นกัน ฉันเชื่อว่าผลลัพธ์จะสมเหตุสมผลถ้าพื้นที่คำตอบมีขนาดใหญ่พอ (เช่นค่าเต็มจำนวน 32- บิตค่าจำนวนเต็ม) มิฉะนั้น (เช่นในกรณีของคำถามแบบเลือกตอบ) ตารางรุ้งจะให้คำตอบที่ถูกต้องอย่างรวดเร็ว
Alexei Levenkov

3
ดังที่ Alexei ชี้ให้เห็นหากอินพุตที่เป็นไปได้ของคุณขยายพื้นที่เล็ก ๆ การจัดเก็บคำตอบในรหัสจะเปิดพวกเขาขึ้นไปที่ผู้โจมตีที่กำหนดไว้ - และฉันเดาว่าปริศนาส่วนใหญ่จะมีช่องว่างของรัฐค่อนข้างน้อย ทั้งคำหรือตัวเลขที่ค่อนข้างเล็ก คุณสามารถแฮชหรือเข้ารหัสเพื่อหลีกเลี่ยงข้อผิดพลาดที่ไร้เดียงสา แต่ไม่มีใครขัดขวางไม่ให้รับคำตอบที่ต้องการได้จริงๆ (ยิ่งไปกว่านั้นพวกเขาสามารถถามคนที่แก้ปริศนาของคุณได้แล้ว)
Chris Hayes

4
หากต้องการต่อต้านสิ่งที่ Chris กำลังพูดถึงคุณสามารถเลือกกระบวนการแฮชที่ช้ามากพูดว่าใช้เวลา 100 มิลลิวินาที (นั่นคือวิธีการที่ดำเนินการโดยมาตรฐาน PK บางอย่าง) นี่ยังเร็วมากจากมุมมองของผู้ใช้ แต่ทำให้การแจงนับยากขึ้น
Yuval Filmus

12
@YuvalFilmus อีกครั้งในระดับหนึ่ง หากปริศนาของคุณจบลงใน "แจนโจหรือเจนเป็นอาชญากร?" จากนั้นก็จะเป็นเรื่องง่ายมากที่จะระบุแม้ว่าคุณจะใช้เวลาหนึ่งนาทีในการแฮช เว้นแต่ว่าเกมทั้งหมดเขียนขึ้นด้วยความคิดนี้และคำถามทุกข้อเป็นคำถามที่เปิดกว้างมากนี่จะเป็นปัญหา แต่ใช่ถ้าคำถามของคุณเป็นแบบปลายเปิดที่พื้นที่ของรัฐมีขนาดใหญ่พอคำตอบสามารถป้องกันได้
Chris Hayes

28

คุณมีสองสามตัวเลือก:

แยกคำตอบออกจากส่วนที่เหลือของรหัสต้นฉบับ

หากคุณต้องการให้โค้ดของคุณเป็นโอเพ่นซอร์ส แต่ไม่ต้องการคำตอบให้เป็นโอเพ่นซอร์สคุณจะต้องเปิดซอร์สโค้ดสำหรับแอปพลิเคชันโดยไม่มีคำถาม & คำตอบโดยที่คำถาม & คำตอบจะเป็น "ปลั๊กอิน" แยกต่างหาก หรือไฟล์ข้อมูล แอพ Android ของคุณจะรวมทั้งสองอย่างนี้เข้าด้วยกันในแอพเดียว

ใส่คำตอบในซอร์สโค้ดของคุณ

อีกทางเลือกหนึ่งถ้าคุณคิดว่าคำถามและคำตอบเป็นส่วนสำคัญของสิ่งที่คุณต้องการเปิดแหล่งที่มาคุณควรใส่คำตอบลงในซอร์สโค้ดโดยที่ไม่ต้องงงงวยเพื่อให้ผู้อื่นสามารถอ่านและแก้ไขได้ การทำให้งงงวยซอร์สโค้ดเพื่อให้ไม่สามารถเข้าใจและแก้ไขไม่ได้จริง ๆ แล้วสอดคล้องกับหลักการของโอเพนซอร์ส

ใส่คำตอบบนเซิร์ฟเวอร์บนอินเทอร์เน็ต

ด้วยวิธีแก้ปัญหาทั้งสองข้างต้นเป็นไปได้สำหรับคนที่ดาวน์โหลดแอปของคุณเพื่อค้นหาคำตอบโดยไม่ต้องเล่นโปรแกรมของคุณไม่ว่าในกรณีใด - ไม่ว่าคุณจะทำให้งงงวย / เข้ารหัสคำตอบถ้าโปรแกรมของคุณสามารถระบุคำตอบโดยไม่มีข้อมูลเพิ่มเติม มนุษย์สามารถตรวจสอบแอพที่รวบรวมของคุณ

หากคุณจริงๆต้องการเพื่อให้แน่ใจว่าไม่มีใครสามารถหาคำตอบแล้วเพียงตัวเลือกที่แท้จริงคือไม่ได้ที่จะให้พวกเขามีคำตอบและมี app เรียกใช้บริการเว็บ ฯลฯ ... เมื่อใดก็ตามที่พวกเขาต้องการที่จะรู้คำตอบ แอปควรส่งคำตอบที่ผู้ใช้ป้อนและบริการบนเว็บควรบอกแอพว่าคำตอบนั้นถูกต้องหรือไม่วิธีที่ผู้ใช้ไม่มีวิธีบอกคำตอบว่าจนกว่าคำตอบนั้นจะถูกต้อง (สั้น การบังคับใช้เว็บเซอร์วิสซึ่งคุณสามารถตรวจจับและป้องกัน)

หากคุณกำลังมองหาวิธีที่จะทำให้งงงวยคำตอบของคุณแนะนำให้ฉันว่าคุณไม่ต้องการที่จะเปิดแหล่งที่มาของคำตอบของคุณในสถานที่แรกดังนั้นคุณควรพิจารณาตัวเลือกแรก

หากจำเป็นอย่างยิ่งที่ผู้ใช้จะไม่สามารถหาคำตอบล่วงหน้าได้ตัวเลือกที่สามคือทางเลือกที่แท้จริงของคุณ แต่ฉันพยายามดิ้นรนที่จะนึกถึงสถานการณ์ที่น่าจะคุ้มค่ากับความพยายามไม่ใช่อย่างน้อยเพราะมันป้องกันผู้ใช้ของคุณ จากการใช้แอพของคุณโดยไม่ต้องเชื่อมต่ออินเทอร์เน็ต


8
คำถามและคำตอบไม่จำเป็นต้องเป็นปลั๊กอิน แต่อาจเป็นไฟล์ข้อมูลแบบง่าย ไฟล์ข้อมูลที่ป้อนเข้านั้นไม่จำเป็นต้องเป็นส่วนหนึ่งของซอฟต์แวร์ลิขสิทธิ์และสามารถอยู่ภายใต้สิทธิการใช้งานแยกต่างหากของตนเอง ตราบใดที่คุณให้ไฟล์ข้อมูลตัวอย่าง (แตกต่างกัน) เพื่อใช้กับซอร์สโค้ดคุณจะไม่ขัดขวางการใช้งานซอร์สหรือโปรแกรมที่รวบรวมจากซอร์สดังกล่าวโดยไม่เสียค่าใช้จ่ายดังนั้นจึงไม่ควรเป็นการละเมิด GPL
Doktor J

ฉันไม่แน่ใจว่าจริงๆแก้ปัญหาของเขา - ไม่ว่าคำตอบจะถูกเข้ารหัสและเข้ารหัสในรหัสหรือกระจายเป็นไฟล์แยกต่างหากรหัสยังคงต้องสามารถถอดรหัสคำตอบดังนั้นใครก็ตามที่ดาวน์โหลดแอปของเขาสามารถทำสิ่งที่ ซอร์สโค้ดทำเพื่อให้ได้คำตอบ (เว้นแต่พวกเขาจะถูกแฮชตามคำแนะนำในคำตอบอื่น)
จอห์นนี่

1
หากเป้าหมายคือการตรวจสอบคำตอบและไม่ต้องการให้แสดงก็สามารถทำได้เช่นเดียวกับรหัสผ่านที่มีแฮชแบบทางเดียว
JamesRyan

@Justin ขอบคุณสำหรับคำตอบของคุณและความคิดเห็นของคุณเกี่ยวกับว่ามันถือเป็นโอเพนซอร์สที่น่าสนใจ ฉันคิดว่าการซ่อนคำตอบไม่ได้มีวัตถุประสงค์เพื่อทำให้งงงวยซอร์สโค้ดหรือวิธีการทำงานของแอปพลิเคชัน แต่เพื่อรักษาความท้าทายเต็มจำนวน การเข้ารหัสตามที่ปรากฎออกมาเป็นวิธีที่ยอดเยี่ยมในการแจกจ่ายปริศนาโดยไม่ต้องมีเมื่อคาดเดาของผู้ใช้ ( 'นี้มันคือมันนี้คืออะไร?)
Nevermore

4

หากวัตถุคือการปิดบังสตริงจากการอ่านซอร์สโค้ดแบบไม่เป็นทางการ แต่ให้เปิดไว้เพื่อให้ผู้อื่นสามารถทำการเปลี่ยนแปลงของตัวเองได้อย่างง่ายดายตัวอย่างเช่นถ้าคุณกำลังเผยแพร่แหล่งข้อมูลไปยังการผจญภัยของข้อความและไม่ต้องการให้ข้อความอธิบายปรากฏขึ้น ซึ่งจะเป็นสปอยเลอร์จากนั้นใช้สิ่งที่ย้อนกลับได้เช่น rot13

ในความเป็นจริงคุณสามารถ rot13 ไฟล์แปลทั้งหมดของคุณและพลิกกลับได้ทันที

นั่นคือการรักษาวิญญาณที่เปิดกว้าง แฮช "magic" แบบสุ่มไม่เหมาะกับการเขียนโปรแกรมจริงๆ


4
โปรดจำไว้ว่าผู้คน GeoCaching จำนวนมากในหมู่พวกเราอ่าน rot13 เกือบจะคล่องแคล่วเหมือนต้นฉบับ
yo '

4

โอเพ่นซอร์สต้องการให้ซอร์สโค้ดเป็นที่เปิดเผยและพร้อมใช้งานไม่ใช่ข้อมูลเกม ดังนั้นคุณสามารถใส่ข้อมูลในไฟล์อื่นได้อย่างง่ายดายและไม่เผยแพร่ข้อมูลนั้น เพิ่มการเข้ารหัสลับบางอย่างถ้าคุณต้องการป้องกันการอ่านไฟล์อย่างไม่เป็นทางการ ฉันสงสัยว่า crypto ที่แข็งแกร่งเป็นสิ่งจำเป็นสำหรับแอปพลิเคชันของคุณ


1
คุณ "ไม่เผยแพร่" ข้อมูลเกมในแง่ใด เกมจะต้องสามารถเข้าถึงข้อมูลนั้นได้ดังนั้นทุกคนที่มีสำเนาของเกมจะมีสำเนาของข้อมูล นั่นคือสิ่งที่การเผยแพร่คือการเผยแพร่สู่สาธารณะ
David Richerby

1
@DavidRicherby ขึ้นอยู่กับสิ่งที่คุณต้องการเผยแพร่และสิ้นสุด เกมนั้นหรือเอ็นจิ้นของคุณที่สามารถใช้สร้างเกมที่คล้ายกันได้หลายเกม? อนุญาตให้ผู้อื่นจัดการกับเกมของคุณตรวจสอบรหัสเพื่อหาช่องโหว่ด้านความปลอดภัยเพียงแค่ใช้ส่วนประกอบอีกครั้ง? หากอินเทอร์เฟซของคุณนั้นเรียบง่ายเหมือนกับ "CSV พร้อม q & a + program = game" ฉันคิดว่าเป็นไปได้ที่จะเผยแพร่เฉพาะโปรแกรมเท่านั้นไม่ใช่ CSV
Raphael

1
@ ราฟาเอล แต่การกระจายเกมที่ประกอบด้วยไฟล์ปฏิบัติการและไฟล์ข้อมูลข้อความธรรมดาไม่สามารถบรรลุเป้าหมายในการทำให้คำตอบเป็นความลับได้ หากคุณต้องการเสนอรุ่นที่เข้ารหัสของ datafile นั่นเป็นเรื่องดีตราบใดที่ทุกคนเข้าใจว่านี่เป็นเพียงความปลอดภัยโดยความสับสน (กุญแจอยู่ในแหล่งที่มา) แต่จากนั้นเราได้รับคำถามว่าข้อความธรรมดาของดาต้าไฟล์นั้นประกอบไปด้วยซอร์สโค้ดในแง่ของ GPL หรือไม่และ ณ จุดนั้นคำถามกลายเป็นเรื่องของการตีความ GPL มากกว่าวิทยาศาสตร์คอมพิวเตอร์
David Richerby

@DavidRicherby: เห็นด้วย ถึงแม้ว่า IANAL ฉันสงสัยอย่างมากว่าไฟล์ข้อมูลที่ประกอบด้วยปริศนาและคำตอบของพวกเขาจะถูกพิจารณาว่าเป็นส่วนที่จำเป็นและไม่สามารถถูกแทนที่ได้ของโปรแกรมที่ไม่สามารถให้สิทธิ์ใช้งานแยกต่างหาก - โดยเฉพาะอย่างยิ่งหากคุณรวมไฟล์ข้อมูลตัวอย่างที่ไม่เข้ารหัส การแจกจ่ายซอร์สพร้อมกับคำแนะนำสำหรับการแก้ไขและเข้ารหัสหากจำเป็นเพื่อให้ชัดเจนว่าใครก็ตามที่มีซอร์สโค้ดสามารถสร้างไฟล์ข้อมูลที่กำหนดเองและใช้กับโปรแกรมได้
Ilmari Karonen

4

ทำไมคุณต้องเก็บคำตอบไว้ในซอร์สโค้ด GPL ของคุณหากคุณไม่ต้องการให้ผู้ใช้ของคุณรู้ แม้ว่าตอนนี้พวกเขาจะไม่รู้จักหรือแตกง่ายพวกเขาสามารถ (และมีแนวโน้มที่จะ) ในอนาคต

แทนที่จะเก็บไว้ในแอปของคุณให้ใช้ฐานข้อมูลภายนอก ทำบริการเว็บขนาดเล็กที่เปรียบเทียบคำตอบกับสิ่งที่อยู่ในฐานข้อมูลของคุณ จากนั้นให้แอปพลิเคชันของคุณโทรไปที่เว็บเซอร์วิซนั้นเมื่อใดก็ตามที่มีการยืนยัน ปัญหาหลักคือเพราะต้องใช้อินเทอร์เน็ตคุณจะสูญเสียความเร็วและฐานผู้ใช้ที่มีศักยภาพ ใบอนุญาตแอพของคุณควรใช้กับแอปเท่านั้นไม่ใช่เว็บเซอร์

คุณสามารถใส่คำตอบลงในฐานข้อมูลขนาดเล็กแล้วใส่ลงในโปรแกรมของคุณ เท่าที่ฉันทราบ GPL จะใช้กับซอร์สโค้ดเท่านั้นไม่ใช่ข้อมูลใด ๆ ที่แอปของคุณจัดเก็บ ฉันอาจจะผิดที่แม้ว่า


1
"เท่าที่ฉันรู้ GPL จะใช้กับซอร์สโค้ดเท่านั้นไม่ใช่ข้อมูลที่แอปของคุณเก็บ" GPL บอกว่า "คุณต้องอนุญาตงานทั้งหมดโดยรวมภายใต้สัญญาอนุญาตนี้ให้กับทุกคนที่มีสิทธิ์ในการคัดลอก" ดังนั้นคุณอาจคิดว่าตอนนี้เราต้องตัดสินใจว่าข้อมูลนั้นเป็นส่วนหนึ่งของ "งานทั้งหมด" หรือไม่ แต่แท้จริงแล้วข้อ จำกัด ทั้งหมดของ GPL (รวมถึงข้อ จำกัด นั้น) จะมีผลเฉพาะกับผู้ได้รับใบอนุญาตเท่านั้น เป็นเรื่องดีที่ผู้อนุญาตจะต้องรักษาเจตนารมณ์ของ GPL ด้วยเช่นกัน แต่พวกเขาไม่จำเป็นต้องกังวลเกี่ยวกับการเยี่ยมชมจากตำรวจลิขสิทธิ์
ปีเตอร์ฟอร์ด

1

โปรดจำไว้ว่าแม้ว่าคุณจะจัดเก็บฐานข้อมูลไว้ในเว็บเซิร์ฟเวอร์ระยะไกล แต่ฐานข้อมูลยังสามารถทำซ้ำได้โดยเพียงแค่เขียนคู่คีย์ / ค่าที่ถูกต้องทั้งหมดที่เห็น และโดยทั่วไปแล้วแอปมือถือควรพยายามอย่าให้ข้อผิดพลาดหรือหยุดทำงานเนื่องจากเครือข่ายขัดข้อง (ใช้การส่งข้อความที่อยู่ในคิวและ "อัปเดตเมื่อคุณสามารถทำได้")

ดังนั้นหากคุณต้องการฐานข้อมูลท้องถิ่น แต่ไม่ชอบความคิดที่ว่ามันถูกถอดรหัสโจ๋งครึ่มคุณสามารถใช้ตัวกรองบลูม (เพื่อหลีกเลี่ยงการพูดคุยกับเครือข่ายหรือมีฐานข้อมูลที่ถอดรหัสขนาดใหญ่ในเครื่อง) นี่คือวิธีที่เครื่องมือตรวจสอบการสะกดคำทำงานเมื่อพื้นที่หน่วยความจำแน่นจริงๆ

ดังนั้นหากคุณเพิ่มคู่คำถาม / คำตอบลงในตัวกรองที่ชอบ:

แฮ (NormalizeString (คำถาม [N])) + แฮ (NormalizeString (คำตอบ [N]))

ถ้าคุณถามว่า "Capitol of Virginia? Richmond" อยู่ในฉากหรือไม่มันจะตอบว่า "ไม่แน่นอน" หรือ "เกือบจะแน่นอนใช่" หากคุณได้รับผลบวกผิดพลาดมากเกินไปทำให้ฐานข้อมูลใหญ่ขึ้น

คุณสามารถมีฐานข้อมูลขนาดใหญ่ในพื้นที่ขนาดเล็กโดยสมมติว่าผู้ใช้จะสะกดคำถามและคำตอบตามที่คุณคาดหวัง การทำให้ฐานข้อมูลเล็กช่วยในการอัพเดตเนื่องจากอาจต้องมีการถ่ายโอนผ่านเครือข่ายไร้สาย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.