对伪随机函数的帮助?

0 投票
1 回答
555 浏览
提问于 2025-04-17 20:15

我现在正在做一个加密项目,我在程序中正确实现了一个凯撒加密函数,但我需要实现另一种加密方法。

说明:我们将使用一种叫做伪随机偏移的修改版。我们不需要事先分发一本书,只需要一个密码,而密码更短,也不需要写下来。然后这个密码会用来给Python的随机数生成器提供种子,如上所述。你应该从凯撒加密的代码开始,但不是在函数开始时创建一个偏移量,而是为每个字符创建一个新的偏移量。

下面是我凯撒加密的代码。有没有人能给我一个关于代码中某个字符的例子,这样我可以跟着理解发生了什么?我刚学Python,还在学习中。

def Caesarian(fin, fout, encrypt_or_decrypt_choice, alphabet):
    # Determine the offset by generating a random number in the correct range.
    # This will be the same random number, if the password sent to random.seed is the same.
    offset = random.randrange(1,len(alphabet))
    if encrypt_or_decrypt_choice=='d':
        offset = -offset
    print "Using the secret offset of", offset

    # Read every line of the input file.
    for line1 in fin:
        # Alter each character of the line1, putting the result into line2.
        line2 = ""
        for c in line1:
            if c in alphabet:
                pos1 = alphabet.find(c)
                pos2 = (pos1+offset)%len(alphabet)
                line2 += alphabet[pos2]
        # Write each resulting line2 to the output file.
        fout.write(line2)

1 个回答

3

在凯撒密码中,你会把每个字符按一个固定的量进行移动。

维杰尼尔密码是对凯撒密码的一种改进,它会在一个小组内按固定的量移动每个字母。比如,假设一个密钥是123,这就意味着“先移动一个,再移动两个,然后移动三个,然后再重复”,所以消息“aaaaaa”会被加密成“bcdbcd”。

维杰尼尔密码和凯撒密码有一个共同的弱点——可以计算出哪些字母组合最常见,然后利用这些信息来优化暴力破解密钥的过程。

你要构建的东西稍微复杂一点——一个简单的流密码。这里的目标是用不同的量来加密每个字符——所以这几乎是一次性密码本,但没有传输一个非常大的密钥的麻烦。

现在看看Python的random模块:

>>> import random
>>> random.choice(range(100))
42
>>> random.choice(range(100))
46
>>> random.choice(range(100))
92

如你所见,每个值都是不同的。如果我们重新运行Python,我们会得到一系列不同的数字。如果这些数字是真正随机的,它们对于这种加密方法就没什么用,因为接收者无法重现相同的数字流。

给伪随机数生成器设置种子可以让我们固定初始状态,这样结果就可以预测了:

>>> random.seed(5)
>>> random.choice(range(100))
62
>>> random.choice(range(100))
74

现在如果我重新设置种子,我们会得到完全相同的数字:

>>> random.seed(5)
>>> random.choice(range(100))
62
>>> random.choice(range(100))
74

要迁移你的原始代码,你需要把offset的初始计算改成设置种子,然后为每个字符更新偏移量。

(这是我尝试更新的代码):

def streamCipher(fin, fout, encrypt_or_decrypt_choice, alphabet, seed):
    # Seed random with the shared secret
    random.seed(seed)

    # Read every line of the input file.
    for line1 in fin:
        # Alter each character of the line1, putting the result into line2.
        line2 = ""
        for c in line1:
            if c in alphabet:
                # Determine the offset by generating a random number in the correct range.
                # This will return the same sequence of random numbers, if the seed is the same.
                offset = random.randrange(1,len(alphabet))
                if encrypt_or_decrypt_choice=='d':
                    offset = -offset
                pos1 = alphabet.find(c)
                pos2 = (pos1+offset)%len(alphabet)
                line2 += alphabet[pos2]
        # Write each resulting line2 to the output file.
        fout.write(line2)

撰写回答