离大谱,直播当众现场写代码编程并抽奖居然也有黑幕?

直播抽奖

之前,我写了一篇文章介绍了公平抽奖的方法,python公平抽奖

其中,介绍到,对于公平没有黑幕的抽奖,一个较好的方法是,选择一个不可操控的内容如股票价格,或者彩票开奖号码作为随机数种子,以此来生成随机数,是较为公平的。因为,一旦这些内容被公布,那么结果也会随之产生,是公开可验证的。

有人看完这篇文章以后,提出了这样一个疑问,“这个方法虽然有道理,但是太慢了,例如,我们需要花时间去等待股票市场出结果,无法做到随时随地,立刻得到抽奖结果,所以是不方便的。因此,我认为,抽奖无需这么麻烦,只需要通过python生成随机数就可以了。只需要通过直播现场编程,然后当着所有人的面运行程序,确保不会重复运行,然后用直播中的结果,作为最终结果就可以了。不需要那么麻烦。”

总结来说就是,他认为,只需要通过直播的方式,在有观众监督的情况下,运行python代码,并得到结果,就是安全可靠,无“黑幕”的了,但是,真的是这样吗?

篡改程序文件

原理

python允许用户编写与标准库同名的模块,例如,如果在当前目录下存在一个名为random.py的文件,就会优先加载这个文件,而不是标准库中的random模块。

如果有人提前编写了一个伪造的random.py,用于实现固定输出或其他不公平逻辑,即使抽奖的代码表面上使用了标准库的random模块,实际上使用的却是伪造的模块。

并且,大多数情况下,抽奖的人公开展示了代码,并且当面进行了运行,就足以表明他们采用了“公平的方式”进行抽奖,通常不可能有人对其设备和运行环境进行详细而细致的检查,所以,这样的作弊行为是容易实现的。况且,由于绝大多数人对代码和运行环境的内在机制并不了解,看到结果是随机产生的,他们通常不会怀疑其中是否存在幕后操纵。

而在抽奖电脑上进行篡改代码是一种隐蔽且直接的操作,普通人很难察觉。即使检查相关代码,也看不出什么问题,因为伪造的模块可能隐藏在文件系统的其他地方。

创建同名文件

假设,我们在当前目录下创建一个文件,起名为random.py,此时,在该文件中定义一个randint

# 一个简单的模拟案例,已经事先选定了让42中奖
def randint(a, b):
    if a <= 42 <= b:
        return 42
    else:
        return a

# 假装接受一个随机数种子
# 但是什么都不做
def seed(a=None, version=2):
    return 

此时,如果按照平常的方式使用randint,那么

import random
import time

random.seed(time.time())
user = random.randint(1, 100)
print("中奖用户是:", user)

按照原本的python内置库,是可以选取1-100的任意用户的。但是引入了新的同名文件以后,就只会选取内定用户。

将伪造代码藏到解析路径中

由于此时random.py就在当前目录,看起来还是比较可疑,容易暴露的,因此,可以将其转移到其他位置。

通过sys.path查看import的解析路径。

import sys

print(sys.path)

然后将random.py文件,移动到解析路径的其他位置,此时,在当前目录就不会再显示该文件,但是依然可以被替换解析。

如何证明调用的是标准库

标准库哈希值

如果为了证明调用的是标准库,可以使用hashlib,对random进行校验,确保其没有被篡改。

import hashlib
import random

def verify_module(module):
    current_hash = hashlib.md5(open(module.__file__, "rb").read()).hexdigest()
    return current_hash

# 注意:实际上,对于不同版本的python,该值可能是不同的
print(verify_module(random))

打印模块加载路径

另一个直接的方法是,通过打印模块加载路径,表明模块使用的是正常路径下的标准库,而不是从其他非常规路径加载来的。

import random
print("random路径:", random.__file__)

新的问题

此时有人会提出疑问:既然已经篡改了random模块的内容,自然也可以篡改__file__,这样的证明有什么用呢?那又要如何证明__file__没被篡改呢?

当然,这种质疑是对的,确实__file__自然也是可以被篡改的,因为,这样的检测方法,只能在作弊者没有想到的情况下,突然出击,才能发挥作用,如果作弊者已经考虑到了,那么是不可靠的。

总结

如果没有可靠的第三方作为监督,并且经过严密的预防措施,即使是通过直播的方式,当面编写代码,并且现场运行代码给所有人看,结果也未必是可靠的。

不过,因为担心存在“黑幕”,而不愿意参加抽奖也并不明智,因为,“抽了不一定中,但是不抽一定不中。”

P.S. 相比于普通的random.randint(),并且设置时间作为随机数种子,直接使用系统随机数可能更好。

import random

secure_random = random.SystemRandom().randint(1, 2)
print(secure_random)

该方法不需要设置随机数种子,因为其并不依赖于python内部的随机数生成器,而是使用更可靠的操作系统提供的随机数生成器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值