Kết hợp ngẫu nhiên
Bạn cần một thuật toán cho phép mỗi người chơi đóng góp vào số ngẫu nhiên cuối cùng theo cách mà anh ta có thể thay đổi kết quả cuối cùng thành mọi giá trị có thể, bất kể những người khác đã đóng góp vào số ngẫu nhiên nào. Bằng cách này, thậm chí tất cả những người chơi khác có thể cố gắng làm việc cùng nhau với một người chơi, nhưng không thể quyết định kết quả (hoặc bằng bất kỳ cách nào ảnh hưởng đến nó).
Làm thế nào để làm điều đó? Hãy tưởng tượng chúng ta muốn mô phỏng một con xúc xắc gồm 6 mặt. Nếu chúng ta chơi một mình, chúng ta sử dụng một trình tạo số ngẫu nhiên tạo ra một số ngẫu nhiên lớn r. Sau đó, chúng tôi nhận được giá trị cuối cùng bằng cách tính toán result = (r mod 6)+1
. Điều tương tự làm việc cho nhiều người chơi, đó là vai trò súc sắc của họ. Hãy tưởng tượng bạn có một hộp (hoặc urn). Mỗi người chơi chạy trình tạo số ngẫu nhiên (được che giấu) và ghi số đó (r1, r2, r3, ... rn) vào một tờ giấy và đặt nó vào hộp. Bây giờ người chơi lấy tất cả các số ra khỏi hộp và tính tổng của chúng để tạo ra số ngẫu nhiên của các nhóm r = r1+r2+r3+r4+...+rn
. Điều này được sử dụng để tính toán kết quả bằng cách sử dụng result = (r mod 6)+1
. Nếu những người chơi khác gian lận (bằng cách làm việc cùng nhau), một người chơi vẫn có thể thay đổi kết quả thành bất kỳ giá trị nào.
Tại sao lại như vậy? Hãy tưởng tượng chúng tôi có 3 người chơi. Người chơi 1 và Người chơi 2 cố gắng gian lận và làm việc cùng nhau với Người chơi 3. Người chơi 1 và Người chơi 2 chỉ đóng góp r1
và r2
tổng hợp r
. Vì vậy, những gì họ có thể quyết định là kết quả của r1+r2
. Giá trị ((r1+r2+r3) mod 6) + 1
giống như (((r1 mod 6) + (r2 mod 6) + (r3 mod 6)) mod 6) + 1
. Vì Người chơi 1 và 2 có thể quyết định r1 và r2, họ có thể quyết định phần (r1 mod 6) + (r2 mod 6)
chúng ta hãy gọi phần này c
. Kết quả cuối cùng là sau đó ((c + (r3 mod 6)) mod 6) + 1
.
Vì vậy, bất cứ điều gì người chơi 1 và 2 đang thử r3 đều có thể thay đổi kết quả thành bất kỳ giá trị nào từ 1 đến 6 mà không thay đổi xác suất. Nếu bạn không tin, hãy thử c = 0 và r3 = 0 .. 5, mang lại cho bạn kết quả từ 1 đến 6. Hãy thử c = 1 và r3 = 0 .. 5, nó sẽ cho bạn kết quả 2,3, 4,5,6,1. Hãy thử c = 2, r3 = 0 .. 5. Bạn sẽ nhận được: 3,4,5,6,1,2.
Để mô tả hiện tượng này, hãy tưởng tượng Wheel of Fortune của một game show. Nó có 6 vùng (0, 1, 2, 3, 4, 5) khóa "kỹ thuật số". Bạn có thể nhấn nút để chuyển tiếp một vùng (từ 0 đến 1, từ 1 đến 2, từ 2 đến 3, ... từ 5 đến 0, v.v.). Trò chơi bắt đầu với bánh xe ở vị trí "0" và mỗi người chơi đang ghi lại (che giấu) bất kỳ số dương nào. Bây giờ họ phải bỏ bút chì, vì vậy bất cứ ai cũng có thể thay đổi số và mỗi người chơi phải hiển thị cho tất cả những người khác số của mình. Bây giờ mỗi người chơi nhấn nút nhiều lần như anh ta đã viết trên tờ giấy của mình. Và chúng tôi nhận được số ngẫu nhiên cuối cùng của chúng tôi (0..5). Trò chơi này sẽ rất lâu và sẽ rất khó chịu, nếu chúng ta không nhớ làm theo: mỗi lần nhấn nút 6 lần thì bánh xe lại ở cùng một vị trí. Vì vậy, mỗi người chơi chỉ cần tính số của mình "(r1+r2+r3) mod 6 = ((r1 mod 6) + (r2 mod 6) + (r3 mod 6)) mod 6
.
Trao đổi giá trị
Bây giờ qua mạng, chúng tôi không có "hộp" để đặt các giá trị ngẫu nhiên của người chơi (bên thứ ba đáng tin cậy). Chúng tôi cũng không thể kiểm tra những người chơi đã bỏ bút chì của họ đi. Vì vậy, chúng ta cần một thuật toán khác cho điều đó.
Kolrabi đã giải thích nó. Bạn có thể cho phép tính giá trị băm (ví dụ băm SHA1) của giá trị ngẫu nhiên theo từng người chơi trước. Sau đó, tất cả họ phải phát hành giá trị băm của mình cho những người khác. Nếu bạn làm đúng, không ai có thể "nhanh chóng" tính được số ngẫu nhiên từ đó. Vì vậy, không ai có thể lấy hàm băm của người khác để thay đổi kết quả cuối cùng theo cách xác định (Hãy tưởng tượng: anh ta là người chơi cuối cùng và anh ta chỉ quay bánh xe về phía trước theo số lần của mình. Nhưng anh ta không biết vị trí của Bánh xe là khi anh ta bắt đầu xoay nó - vì vậy anh ta không thể quyết định kết quả).
Nếu tất cả mọi người đều có băm của tất cả những người khác, mọi người đều kiểm tra rằng anh ta có băm giống nhau từ tất cả những người khác. Không biết nếu điều này thực sự cần thiết. Nhưng, sau đó tất cả mọi người có cùng băm.
Bây giờ, trao đổi các số ngẫu nhiên. Mọi người kiểm tra xem các số có khớp với giá trị băm không (bằng cách tính giá trị băm của tất cả các số và kiểm tra xem chúng có bằng giá trị băm mà người chơi đã trao đổi trước đó không).
Nếu không có vấn đề nào ở trên (tất cả đã trao đổi băm chính xác, băm khớp với các giá trị ngẫu nhiên), bạn có thể tính kết quả bằng cách tính tổng các giá trị ngẫu nhiên và tính toán "mod x" + 1, cung cấp cho bạn kết quả của một con xúc xắc với x hai bên. Kết quả này phải là (Tôi không phải là mật mã) được phân phối ngẫu nhiên miễn là ít nhất một người chơi đã sử dụng trình tạo số ngẫu nhiên tạo ra các giá trị phân bố đều.
Điều gì có nghĩa là "Nếu bạn làm đúng"?
Bạn phải ngăn chặn rằng bất kỳ người chơi nào cũng có thể tính toán các giá trị ngẫu nhiên từ giá trị băm. Có ít nhất hai cách người chơi có thể làm điều đó:
Anh ta chỉ thử qua tất cả các giá trị 0, 1, 2, 3 ... và tính toán các giá trị băm. Nếu hàm băm khớp, anh ta đã tìm thấy giá trị cho hàm băm. Để ngăn cách tiếp cận này thành công, phạm vi số ngẫu nhiên của bạn phải rất lớn (không chỉ từ 0 đến 5 hoặc 0 đến 65535, mà người chơi có thể nhanh chóng kiểm tra trong thời gian ngắn). Một số 32 bit sẽ ổn. Đây là lý do tại sao người chơi nên trao đổi đầu ra bộ tạo số ngẫu nhiên thô chứ không phải giá trị "mod 6". Nếu trình tạo số ngẫu nhiên của bạn không cung cấp cho bạn các giá trị khổng lồ tạo ra nhiều số ngẫu nhiên và kết hợp chúng thành một số lớn duy nhất (sử dụng các thao tác thay đổi bit để kết hợp chúng; hãy hỏi, nếu bạn cần làm điều đó và không biết cách làm nó ... điều quan trọng là phải làm điều này đúng!). Nhưng, trong hầu hết các trường hợp, phạm vi giá trị ngẫu nhiên của trình tạo đủ lớn ...
Phương pháp thứ hai sẽ là sử dụng bảng tra cứu. Nếu bạn biết rằng các số nằm trong một phạm vi đặc biệt, bạn có thể tính toán tất cả các giá trị băm trước và lưu trữ chúng vào cơ sở dữ liệu, được sắp xếp theo thứ tự bảng chữ cái. Sau đó, bạn có thể chỉ cần tra cứu băm để có được giá trị. Để ngăn chặn điều này, bạn có thể thực hiện hai điều: a) phạm vi số (như trên) phải rất lớn để không thể lưu trữ cơ sở dữ liệu như vậy. b) trao đổi một chuỗi ngẫu nhiên (được đóng góp trong các phần của tất cả người chơi, không cần phải che giấu) trong mỗi vòng mới. Chuỗi ngẫu nhiên đó sẽ được thêm vào tất cả các giá trị khi tính toán giá trị băm. Vì vậy, bạn không thể xây dựng cơ sở dữ liệu trước khi bạn biết chuỗi ngẫu nhiên này - hoặc bạn phải xây dựng cơ sở dữ liệu cho bất kỳ chuỗi ngẫu nhiên nào như vậy, điều này sẽ cần nhiều sức mạnh tính toán và lưu trữ hơn.
Một khả năng gian lận khác là "thay đổi" số ngẫu nhiên thành một số khác khớp với cùng giá trị băm. Cách tiếp cận sẽ giống như trên. Mặc dù trong hầu hết các trường hợp, rất khó để tìm một số khác có cùng giá trị băm, nhưng điều này có thể được tính toán trước, nếu bạn chỉ sử dụng hàm băm của số đó. Do đó, bạn nên trao đổi chuỗi tiền tố ngẫu nhiên (hoặc hậu tố) phải được thêm vào khi tính giá trị băm. Tôi không chắc chắn 100%, nhưng tôi nhớ có một số kỹ thuật cho thuật toán băm MD5 để nhanh chóng tính toán các giá trị khớp khác cho cùng một hàm băm, nếu bạn được cung cấp một giá trị dẫn đến hàm băm đó. Vì vậy, tốt hơn không sử dụng MD5. Tôi không biết về kiểu tấn công này cho SHA1, nhưng có thể có một cuộc tấn công.
Nếu bạn đã thực hiện đúng như trên, bạn nên cải thiện hơn nữa tính bảo mật của phương thức bằng cách giới hạn thời gian trao đổi giá trị băm và giá trị. Chỉ khi việc trao đổi được thực hiện trong một khoảng thời gian giới hạn, nó sẽ có hiệu lực. Điều này đảm bảo rằng không bên nào có đủ thời gian để áp dụng một trong những 'hack' ở trên. Nếu mất quá nhiều thời gian, thủ tục phải được lặp lại.
Những gì vẫn cần phải được giải quyết
Một trong các bên vẫn có thể ảnh hưởng đến kết quả bằng cách áp dụng các kỹ thuật trên. Trong hầu hết các trường hợp (ví dụ 99,99999% các trường hợp tùy thuộc vào tham số), thời gian sẽ quá ngắn. Nhưng, có đủ cơ hội một bên có thể may mắn phá vỡ băm. Ví dụ: Người chơi chỉ có thể thử ngẫu nhiên các số để tìm giá trị "ngẫu nhiên" khác có cùng giá trị băm mà anh ta đã gửi cho người chơi khác (cách tiếp cận cuối cùng) càng lâu càng tốt (để không hết thời gian chờ anh ta). Đặc biệt, nếu người chơi cho phép tất cả những người khác gửi cho anh ta các giá trị ngẫu nhiên trước, anh ta sẽ biết loại giá trị nào sẽ mang lại cho anh ta chiến thắng lớn nhất. Vì vậy, anh chỉ có thể thử những cái này. Người chơi ác sau đó sẽ để mọi thứ hết thời gian và khởi động lại (để có cơ hội khác mà không mất) hoặc chỉ để trò chơi tiếp tục và sử dụng vòng xúc xắc tiếp theo cho lần thử khác. Bạn có thể quyết định rằng, nếu người chơi không cung cấp giá trị băm hoặc ngẫu nhiên trong thời gian chờ sẽ tự động mất. Vì vậy, điều này làm giảm vấn đề, nhưng nó vẫn làm tăng cơ hội của người chơi bằng một số lượng rất nhỏ.
Điểm yếu này đặc biệt nghiêm trọng, nếu số lượng cơ hội bổ sung rất nhỏ này đủ để làm phiền ... Ví dụ: nếu một người chơi có thể theo cách này sẽ quyết định một kết quả phức tạp và giành được rất nhiều tiền. Để tưởng tượng, giả sử bạn áp dụng thuật toán này cho trò chơi xổ số trong đó một trong những "người chơi" là Máy chủ Ngân hàng. Hiện tại, chúng tôi bỏ qua rằng nếu chúng tôi có nhiều người chơi, lượng truyền dữ liệu sẽ không thực tế (mỗi người phải nói với tất cả người khác, giá trị băm và giá trị ngẫu nhiên của nó; kết quả là N * (N-1) / 2 các tin nhắn cần được trao đổi, hơn 1 triệu cho chỉ N = 2000 người chơi và tăng theo phương trình bậc hai). Được rồi, trở lại vấn đề. Nếu chỉ một người chơi sẽ "phá vỡ" hàm băm của mình và có thể quyết định kết quả, anh ta có thể giành được một số triệu đô la bất hợp pháp từ Jack Pot ... Hiểu chưa?
Nếu bạn có một ứng dụng quan trọng như vậy, bạn phải tính toán cơ hội, rằng ít nhất một người chơi sẽ bẻ khóa mã băm của mình trong thời gian đó. Sau đó nhân số này với chiến thắng tối đa có thể có của tất cả người chơi, không thuộc quyền kiểm soát của bạn (ví dụ: người chơi ngân hàng đáng tin cậy). Điều này sẽ cung cấp cho bạn sự mất mát tối đa mỗi vòng. Trong ví dụ xổ số, ngân hàng xổ số sẽ mất số tiền lớn này mỗi vòng, nếu tất cả người chơi sẽ cố gắng gian lận. Do đó, cơ hội xổ số sẽ cần phải được điều chỉnh theo cách - hay xác suất thành công của một 'hack' phải được giảm thêm.
Để giảm xác suất bạn có thể: a) giảm thời gian chờ, b) sử dụng hàm băm phức tạp hơn, c) sử dụng số dài hơn, OR: d) phân phối kết quả qua nhiều vòng.
Phân phối kết quả qua nhiều vòng sẽ hoạt động chỉ bằng cách quyết định - một phần - của "kết quả" trong một vòng và thực hiện nhiều vòng. Đối với ví dụ xổ số, mỗi số có thể có vòng riêng. Bằng cách này, một kẻ lừa đảo may mắn sẽ chỉ có khả năng thay đổi một số mỗi lần anh ta phá được hàm băm. Vì vậy, anh ta sẽ phải có may mắn 6 lần liên tiếp (nếu xổ số được chọn 6 số) để trúng giải độc đắc. CẢNH BÁO: Mỗi vòng chỉ nên ảnh hưởng đến một phần đặc biệt của kết quả (ví dụ: một trong các số trong xổ số). Không chỉ trao đổi nhiều giá trị ngẫu nhiên / băm và tổng hợp chúng, như trước đây. Nếu bạn làm điều này, một người chơi gặp may mắn trong vòng cuối cùng sẽ có thể thay đổi toàn bộ kết quả (!). Nhưng, ví dụ, bạn có thể thực hiện một vòng cho mỗi "bit" của một số ngẫu nhiên.
Một vấn đề khác cần quan tâm là, một người chơi có thể "làm phiền" trò chơi bằng cách để toàn bộ thời gian hết lần này đến lần khác. Đây có thể là một vấn đề, nếu người chơi ẩn danh và bạn không thể chỉ yêu những người không chơi sòng phẳng.
OK, tôi hy vọng điều này bao gồm tất cả các vấn đề và các cuộc tấn công ...
Chúc may mắn ;-)