重构此分组密码密钥功能

时间:2009-06-15 16:10:33

标签: python encryption

我发现了一个简单的纯python河豚实现,可满足我对特定项目的需求。

只有一部分困扰我:

def initialize(key):
    """
    Use key to setup subkeys -- requires 521 encryptions
    to set p and s boxes.  key is a hex number corresponding
    to a string of 32 up to 448 1s and 0s -- keylen says
    how long
    """    

    # Note that parray and sboxes are globals that have been pre-initialized.

    hexkey = hex(key)[2:]
    if hexkey[-1]=='L':
       hexkey = hexkey[:-1]

    if len(hexkey)%2==1:
        hexkey = '0'+hexkey

    lenkey = len(hexkey)/8    
    if lenkey==0:
        pos=0

    # XOR key segments with P-boxes

    for i in range(18):
        if lenkey>0:
            pos = (i%lenkey)*8  # offset into key gives subkey

        subkey = eval('0x'+hexkey[pos:pos+8]+'L')
        parray[i] ^= subkey  # immediate XOR -- Python 2.0+ syntax


    # encrypt 0-data, then keep re-encrypting and reassigning P-boxes

    output = 0L
    for i in range(0,17,2):
        output = bfencrypt(output)
        parray[i], parray[i+1] = output>>32, output & 0xFFFFFFFFL

    # re-encrypt and reassign through all the S-boxes        

    for i in range(4):
        for j in range(0,255,2):
            output = bfencrypt(output)
            sbox[i][j],sbox[i][j+1] = output>>32, output & 0xFFFFFFFFL

    # print "Initialization complete"

subkey = eval('0x'+hexkey[pos:pos+8]+'L') ?请告诉我有更好的方法。

有没有办法重构这个以使用实际的整数类型而不是字符串中的十六进制值?

4 个答案:

答案 0 :(得分:5)

是。使用基数为16的int()。

>>> int('ffffffff',16)
4294967295L

这样:

subkey = int(hexkey[pos:pos+8], 16)

应该做同样的事情而不需要eval。

实际上,在给定整数的情0xffffffff并在循环中将键右移32位。例如:

subkeys = []
while key:
    subkeys.append(key & 0xffffffff)
    key >>= 32

if not subkeys: subkeys = [0] # Handle 0 case
subkeys.reverse() # Use same order as before (BUT SEE BELOW)

但是,这个初始化过程看起来有点奇怪 - 它使用从左边开始的十六进制数字,没有零填充来舍入到8个十六进制数字的倍数(因此数字0x123456789将被分成{ {1}}和0x12345678,而不是更习惯的0x90x00000001。它也会重复这些数字,而不是将其视为单个大数字。您应该检查此代码实际上是在执行正确的算法。

答案 1 :(得分:3)

请勿使用此代码,更不要试图改进它了。

使用互联网上的加密代码可能会导致软件出现严重的安全问题。有关该主题,请参阅Jeff Atwood's little series

在最高抽象级别使用经过验证的加密库要好得多。理想情况下,它可以在C中实现所有键处理,并在使用后负责销毁密钥材料。

在Python中执行加密的一个问题是,由于Python字符串的性质和垃圾收集过程,您无法控制内存中密钥材料的扩散。

答案 2 :(得分:1)

另一种选择是“int('0x111',0)”。 int的第二个参数是基数。 “0”表示“使用通常的规则:没有前缀是十进制,0前缀是八进制,0x是十六进制 - 就像eval”。

这是“模拟”用于启动字符串的eval操作的首选方法。

答案 3 :(得分:0)

您可以使用长函数执行此操作:

subkey = long(hexkey[pos:pos+8], 16)  

来自help(long)

  

类长(对象)
   | long(x [,base]) - >整数
   |
   |如果可能,将字符串或数字转换为长整数。浮动的    |点参数将被截断为零(这不包括
   |浮点数的字符串表示!)转换时    |字符串,使用可选的基础。当时,提供基数是错误的    |转换非字符串。