Giữ bí mật chuỗi trong mã nguồn (mở)


50

Tôi đã hoàn thành việc phát triển một ứng dụng cho Android và dự định xuất bản nó với GPL - tôi muốn nó là nguồn mở. Tuy nhiên, bản chất của ứng dụng (một trò chơi) là nó hỏi các câu đố và có các câu trả lời được mã hóa vào tài nguyên chuỗi. Tôi không thể công bố câu trả lời! Tôi được yêu cầu xem xét việc lưu trữ mật khẩu một cách an toàn - nhưng tôi không tìm thấy bất cứ điều gì phù hợp.

Có thể xuất bản mã nguồn của tôi với một chuỗi chuỗi bị ẩn, mã hóa hoặc bị che khuất không? Có lẽ bằng cách đọc các câu trả lời từ một cơ sở dữ liệu trực tuyến?

Cập nhật

Giải pháp của Yuval Filmus dưới đây đã có hiệu quả. Khi tôi đọc nó lần đầu tiên tôi vẫn không biết phải làm thế nào. Tôi tìm thấy một số giải pháp, cho tùy chọn thứ hai: lưu trữ giải pháp băm trong nguồn và tính toán hàm băm mỗi khi người dùng đoán. Để làm điều này trong javascript, có thư viện crypto-js tại http://code.google.com.vn/p/crypto-js/ . Đối với Android, hãy sử dụng chức năng MessageDigest . Có một ứng dụng (trên fdroid / github) được gọi là HashPass thực hiện điều này.


11
Tôi tự hỏi làm thế nào ontopic đây là ở đây; nó có thể phù hợp hơn với Bảo mật thông tin trong mọi trường hợp.
Raphael

2
@YuvalFilmus Đừng để bị lừa bởi phiếu "Câu hỏi nóng". Nhưng điểm lấy.
Raphael

4
Các chi tiết quan trọng còn thiếu ở đây là: Bạn có muốn xác minh câu trả lời của người dùng hay bạn cũng muốn có thể in câu trả lời đúng? Và, bạn có cần bất kỳ fuzzines nào không, hay chỉ có một bộ câu trả lời đúng giới hạn rõ ràng (để bạn có thể kiểm tra câu trả lời của người dùng đối với bộ này từng cái một)?
hyde

4
Tất cả các câu trả lời đang hỏi những gì bạn muốn giải quyết vấn đề. Tại sao bạn không thể công bố câu trả lời?
Rhymoid

1
Mã của bạn cần gì để có thể làm được với các chuỗi này? Có cần phải có thể giải mã chúng? Hoặc là có thể so sánh các chuỗi với họ đủ?
David Schwartz

Câu trả lời:


83

Bạn có ít nhất hai lựa chọn, tùy thuộc vào vấn đề bạn muốn giải quyết.

Nếu bạn muốn người đọc vô tội trong mã của bạn không vô tình nhận được câu trả lời hoặc ít nhất bạn muốn làm cho nó hơi khó khăn để người dùng không bị cám dỗ, bạn có thể mã hóa các giải pháp và lưu trữ khóa như một phần của mã của mình, có lẽ là một kết quả của một số tính toán (để làm cho nó thậm chí còn khó khăn hơn).

Nếu bạn muốn ngăn người dùng truy xuất câu trả lời, bạn có thể sử dụng hàm một chiều hoặc trong thuật ngữ máy tính, hàm băm . Lưu trữ một hash của câu trả lời, và họ bạn có thể kiểm tra xem câu trả lời là đúng mà không có nó là có thể suy ra câu trả lời nào cả mà không tìm thấy nó lần đầu tiên. Điều này có nhược điểm là khó kiểm tra câu trả lời gần với câu trả lời đúng, mặc dù có một số giải pháp thậm chí cho vấn đề này.


9
Một điều tôi muốn nói thêm là nếu bạn cần bảo mật hơn nữa, mỗi câu trả lời có lẽ nên được muối bằng một loại muối khác nhau. Điều này tránh một cuộc tấn công từ điển chống lại tất cả các câu trả lời cùng một lúc. Nếu bạn muốn xem người tiền điện tử "thực sự" làm điều đó như thế nào, hãy xem hệ thống String-to-Key trong OpenPGP .
Bút danh

1
Giữ băm trong mã có nghĩa là tất cả thông tin là tĩnh và muối / bất cứ điều gì khác cũng sẽ có sẵn. Tôi tin là kết quả sẽ hợp lý nếu không gian câu trả lời đủ lớn (như phạm vi đầy đủ của các giá trị nguyên 32 bit), nếu không (ví dụ trong trường hợp có nhiều câu hỏi trắc nghiệm), bảng cầu vồng sẽ nhanh chóng đưa ra câu trả lời đúng.
Alexei Levenkov

3
Như Alexei chỉ ra, nếu các đầu vào khả dĩ của bạn trải rộng trong một không gian nhỏ, việc lưu trữ các câu trả lời trong mã sẽ mở chúng cho bất kỳ kẻ tấn công xác định nào - và tôi đoán hầu hết các câu đố sẽ có không gian trạng thái khá nhỏ, trong đó câu trả lời của chúng thường phải hoặc từ hoặc số tương đối nhỏ. Bạn có thể băm hoặc mã hóa để tránh những lỗi vô tội, nhưng không ngăn được ai đó nhận được câu trả lời ai thực sự muốn nó. (Ngoài ra, họ chỉ có thể hỏi ai đó đã giải câu đố của bạn!)
Chris Hayes

4
Để chống lại những gì Chris đang đề cập, bạn có thể chọn một quá trình băm rất chậm, giả sử phải mất 100ms (đó là cách tiếp cận được thực hiện bởi một số tiêu chuẩn PK). Điều này vẫn còn rất nhanh từ quan điểm của người dùng, nhưng làm cho việc liệt kê trở nên khó khăn hơn nhiều.
Yuval Filmus

12
@YuvalFilmus Một lần nữa, đến một mức độ. Nếu câu đố của bạn kết thúc trong "Jan, Joe hay Jane là tội phạm?" sau đó sẽ rất dễ dàng để liệt kê ngay cả khi bạn thực hiện băm mất một phút. Trừ khi toàn bộ trò chơi được viết với ý nghĩ này và tất cả các câu hỏi đều cực kỳ mở, điều này sẽ gây ra vấn đề. Nhưng có, nếu câu hỏi của bạn kết thúc mở mà không gian trạng thái đủ lớn, câu trả lời có thể được bảo vệ.
Chris Hayes

28

Bạn có hai ba lựa chọn:

Giữ câu trả lời tách biệt với phần còn lại của mã nguồn

Nếu bạn muốn mã của mình là nguồn mở, tuy nhiên không muốn câu trả lời là nguồn mở, thì bạn mở mã nguồn cho ứng dụng mà không có câu hỏi & câu trả lời, với câu hỏi và câu trả lời là một "plugin" nguồn đóng riêng biệt hoặc tập tin dữ liệu. Ứng dụng Android của bạn sẽ kết hợp cả hai thứ này lại với nhau thành một ứng dụng.

Đặt câu trả lời trong mã nguồn của bạn

Ngoài ra, nếu bạn coi các câu hỏi và câu trả lời là một phần cốt lõi của những gì bạn muốn mở nguồn thì bạn nên đặt câu trả lời vào mã nguồn, tốt nhất là không bị xáo trộn để người khác có thể đọc và sửa đổi chúng . Làm xáo trộn mã nguồn để không thể hiểu và sửa đổi nó không thực sự phù hợp với các nguyên tắc của mã nguồn mở.

Đặt câu trả lời trên một máy chủ trên internet

Với cả hai giải pháp trên, người nào đó đã tải xuống ứng dụng của bạn để tìm ra câu trả lời mà không cần chơi chương trình của bạn trong bất kỳ trường hợp nào - bất kể bạn che giấu / mã hóa câu trả lời của mình như thế nào, nếu chương trình của bạn có thể xác định câu trả lời mà không cần thêm thông tin, vì vậy một con người có thể kiểm tra ứng dụng biên dịch của bạn.

Nếu bạn thực sự muốn đảm bảo rằng không ai có thể tìm ra câu trả lời thì lựa chọn thực sự duy nhất là không cung cấp cho họ câu trả lời và yêu cầu ứng dụng gọi dịch vụ web, v.v ... bất cứ khi nào họ muốn biết câu trả lời. Ứng dụng sẽ gửi câu trả lời mà người dùng đã nhập và dịch vụ web sẽ cho ứng dụng biết câu trả lời có đúng hay không, theo cách đó, người dùng không có cách nào trả lời câu trả lời là gì cho đến khi họ đã có câu trả lời đúng của brute-buộc dịch vụ web, mà bạn có thể phát hiện và bảo vệ chống lại).

Nếu bạn đang tìm cách làm xáo trộn câu trả lời của mình, điều đó gợi ý cho tôi rằng bạn không thực sự muốn mở nguồn câu trả lời của mình ngay từ đầu, vì vậy bạn nên xem xét các lựa chọn đầu tiên.

Nếu điều quan trọng là người dùng không thể tìm thấy câu trả lời trước thì tùy chọn thứ ba là lựa chọn thực sự duy nhất của bạn, tuy nhiên tôi đang loay hoay nghĩ về một kịch bản mà điều này đáng để nỗ lực, nhất là vì nó ngăn người dùng của bạn từ việc sử dụng ứng dụng của bạn mà không cần kết nối Internet.


8
Q & A thậm chí không phải là một plugin, nó có thể là một tệp dữ liệu đơn giản. Các tệp dữ liệu đầu vào không nhất thiết phải là một phần của phần mềm được cấp phép và có thể được bảo vệ theo giấy phép riêng của chúng. Miễn là bạn cung cấp tệp dữ liệu mẫu (khác nhau) để sử dụng với mã nguồn, bạn sẽ không cản trở việc sử dụng miễn phí nguồn hoặc chương trình được biên dịch từ nguồn đã nói và do đó không vi phạm GPL.
Doktor J

Tôi không chắc rằng điều đó thực sự giải quyết được vấn đề của anh ấy - cho dù câu trả lời được mã hóa và mã hóa cứng trong mã hay được phân phối dưới dạng tệp riêng biệt, mã vẫn cần có thể giải mã câu trả lời, vì vậy, bất kỳ ai tải xuống ứng dụng của anh ấy đều có thể làm gì mã nguồn làm để có được câu trả lời. (trừ khi chúng được băm, như được đề xuất trong câu trả lời khác)
Johnny

1
Nếu mục tiêu là kiểm tra câu trả lời và không yêu cầu chúng được hiển thị thì nó có thể được thực hiện giống như mật khẩu với hàm băm một chiều.
JamesRyan

@Justin, cảm ơn bạn đã trả lời và nhận xét của bạn về việc liệu nó có tạo thành nguồn mở hay không. Tôi nghĩ rằng việc ẩn các câu trả lời không nhằm mục đích làm xáo trộn mã nguồn, hoặc cách ứng dụng hoạt động, mà là để duy trì tính tích hợp của thách thức. Mật mã học, như hóa ra, là một phương tiện tuyệt vời để phân phối các câu đố mà không cần phải ở đó khi người dùng đoán ('đây có phải là nó không?')
Nevermore

4

Nếu đối tượng che khuất các chuỗi khỏi việc đọc mã nguồn thông thường nhưng vẫn mở chúng để người khác có thể dễ dàng thực hiện các thay đổi của riêng họ - ví dụ: nếu bạn đang xuất bản nguồn thành một cuộc phiêu lưu văn bản và không muốn bất kỳ văn bản mô tả nào xuất hiện mà sẽ tạo thành một spoiler, sau đó sử dụng một cái gì đó có thể đảo ngược như rot13.

Trên thực tế, bạn có thể quay13 tất cả các tệp dịch của mình và lật chúng lại một cách nhanh chóng.

Đó là giữ tinh thần cởi mở. Băm "ma thuật" ngẫu nhiên không thực sự thân thiện với lập trình viên.


4
Hãy nhớ rằng nhiều người GeoCaching trong số chúng ta đọc rot13 gần như trôi chảy như bản gốc.
yo '

4

Nguồn mở yêu cầu mã nguồn phải được công khai và có sẵn, không phải dữ liệu trò chơi. Vì vậy, bạn có thể dễ dàng đặt dữ liệu vào một tệp khác và không xuất bản dữ liệu đó. Thêm một số tiền điện tử nếu bạn muốn ngăn chặn việc đọc tệp thông thường. Tôi nghi ngờ một loại tiền điện tử mạnh là cần thiết cho ứng dụng của bạn.


1
Theo nghĩa nào bạn có thể "không công bố" dữ liệu trò chơi? Trò chơi phải có khả năng truy cập dữ liệu đó để bất kỳ ai có bản sao của trò chơi đều có bản sao dữ liệu. Đó chính xác là những gì xuất bản: công khai.
David Richerby

1
@DavidR Richby Phụ thuộc vào những gì bạn muốn xuất bản và kết thúc. Trò chơi đó hoặc công cụ của bạn có thể được sử dụng để tạo ra nhiều trò chơi tương tự? Cho phép mọi người thao túng trò chơi của bạn, kiểm tra mã cho lỗ hổng bảo mật quặng chỉ sử dụng lại các thành phần? Nếu giao diện của bạn đơn giản như "CSV với q & a + chương trình = trò chơi" thì tôi nghĩ chỉ có thể xuất bản được chương trình chứ không phải CSV.
Raphael

1
@Raphael Nhưng phân phối một trò chơi bao gồm tệp thực thi và tệp dữ liệu văn bản thuần túy không đạt được mục tiêu làm cho câu trả lời trở nên bí mật. Nếu bạn muốn đề xuất một phiên bản mã hóa của tệp dữ liệu, điều đó tốt, miễn là mọi người hiểu rằng đây chỉ là bảo mật bởi sự tối nghĩa (khóa nằm trong nguồn). Nhưng sau đó chúng ta đi vào câu hỏi liệu bản rõ của tệp dữ liệu có cấu thành mã nguồn theo nghĩa của GPL hay không, tại thời điểm đó, câu hỏi trở thành vấn đề giải thích GPL, thay vì khoa học máy tính.
David Richerby

@DavidR Richby: Đồng ý. Tuy nhiên, mặc dù IANAL, tôi rất nghi ngờ rằng một tệp dữ liệu bao gồm câu đố và câu trả lời của họ sẽ được coi là một phần thiết yếu và không thể thay thế của chương trình mà nó không thể được cấp phép riêng - đặc biệt nếu bạn bao gồm tệp dữ liệu mẫu không được mã hóa trong phân phối nguồn, cùng với các hướng dẫn sửa đổi và mã hóa nó nếu cần, để làm rõ rằng bất kỳ ai có mã nguồn thực sự có thể tạo các tệp dữ liệu tùy chỉnh của riêng họ và sử dụng chúng với chương trình.
Ilmari Karonen

4

Tại sao bạn sẽ lưu trữ câu trả lời của mình trong mã nguồn GPL nếu bạn không muốn người dùng biết chúng? Ngay cả khi bây giờ chúng không được biết đến hoặc dễ dàng bị bẻ khóa, chúng có thể (và có thể sẽ) trong tương lai.

Thay vì lưu trữ chúng trong ứng dụng của bạn, hãy sử dụng cơ sở dữ liệu bên ngoài. Tạo một dịch vụ web nhỏ để so sánh các câu trả lời với những gì trong cơ sở dữ liệu của bạn. Sau đó, hãy để ứng dụng của bạn thực hiện cuộc gọi đến dịch vụ web đó bất cứ khi nào nó phải xác minh. Vấn đề chính là, vì nó yêu cầu truy cập internet, bạn sẽ mất một số cơ sở người dùng tiềm năng. giấy phép ứng dụng của bạn chỉ nên áp dụng cho chính ứng dụng, không phải cho dịch vụ web.

Bạn cũng có thể chỉ cần đặt câu trả lời của bạn trong một cơ sở dữ liệu nhỏ và đưa nó vào chương trình của bạn. Theo tôi biết, GPL chỉ áp dụng cho mã nguồn, không phải bất kỳ dữ liệu nào mà ứng dụng của bạn lưu trữ. Tôi có thể sai về điều đó, mặc dù.


1
"Theo như tôi biết, GPL chỉ áp dụng cho mã nguồn, không phải bất kỳ dữ liệu nào mà ứng dụng của bạn lưu trữ". Vâng, GPL nói "Bạn phải cấp phép cho toàn bộ tác phẩm, theo toàn bộ, theo Giấy phép này cho bất kỳ ai sở hữu một bản sao." Vì vậy, bạn có thể nghĩ rằng bây giờ chúng ta cần quyết định xem dữ liệu có phải là một phần của "toàn bộ công việc" hay không. Nhưng trên thực tế, chắc chắn tất cả các hạn chế của GPL (bao gồm cả hạn chế đó) chỉ áp dụng cho người được cấp phép. Thật tốt cho những người cấp phép cũng tuân theo tinh thần của GPL, nhưng họ không cần phải lo lắng về chuyến thăm từ cảnh sát bản quyền.
Peter Ford

1

Hãy nhớ rằng ngay cả khi bạn lưu trữ cơ sở dữ liệu trong một máy chủ web từ xa, cơ sở dữ liệu vẫn có thể được sao chép bằng cách viết ra tất cả các cặp khóa / giá trị chính xác đã được nhìn thấy. Và nói chung, các ứng dụng di động nên cố gắng không đưa ra lỗi hoặc ngừng hoạt động vì mạng bị hỏng (sử dụng tin nhắn xếp hàng và "cập nhật khi bạn có thể").

Vì vậy, nếu bạn muốn có một cơ sở dữ liệu cục bộ, nhưng không thích ý tưởng về việc nó được giải mã một cách trắng trợn, bạn có thể sử dụng bộ lọc nở (để tránh nói chuyện với mạng hoặc có một cơ sở dữ liệu được giải mã lớn cục bộ). Đây là cách trình kiểm tra chính tả được sử dụng để làm việc khi không gian bộ nhớ thực sự chật hẹp.

Vì vậy, nếu bạn thêm các cặp câu hỏi / câu trả lời vào bộ lọc như:

Hash (NormalizeString (Câu hỏi [n])) + Hash (NormalizeString (Trả lời [n]))

Nếu bạn hỏi liệu "Capitol of Virginia? Richmond" có trong tập hợp không, nó sẽ trả lời "chắc chắn là không" hoặc "gần như chắc chắn là có". Nếu bạn nhận được quá nhiều dương tính giả, thì hãy làm cho cơ sở dữ liệu lớn hơn.

Bạn có thể có một cơ sở dữ liệu rộng lớn trong một không gian nhỏ, giả sử rằng người dùng sẽ đánh vần Câu hỏi và Trả lời chính xác như bạn mong đợi. Giữ cơ sở dữ liệu nhỏ giúp cập nhật, bởi vì chúng có thể phải được chuyển qua mạng không dây.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.