2009-06-15 75 views
1

我发现了一个简单的纯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')?请告诉我有更好的方法来做到这一点。

是不是有一种方法来重构这个在字符串中使用实际整数类型而不是十六进制值?

回答

5

是的。使用int()以16

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

这样一个基地:

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

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

[编辑]事实上,通常没有理由你需要转换为字符串表示在所有给定一个整数 - 你可以简单地提取出通过取与各32位值与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) 

然而,这个初始化过程似乎有点奇怪 - 它使用从左边开始,16进制数,没有填零舍入到8个十六进制数字的倍数(所以数量0x123456789将被拆分到0x123456780x9,而不是更习惯0x000000010x23456789,也重复这些数字,而不是将其作为一个庞大的数字。您应该检查该代码实际上执行正确的算法。

+0

它对schneier的测试向量正确执行:http://www.schneier.com/code/vectors.txt。也就是说,我将重写它与schneier的c代码(这不是很复杂),而不是混淆了这个字符串片段的愚蠢。 – 2009-06-15 21:54:23

1

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

这是“模仿”用于发布字符串的eval操作的首选方法。

0

您可以用长功能做到这一点:

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

help(long)

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

3

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

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

在最高级别的抽象层次上使用经过验证的加密库会好得多。理想情况下,它实现了C中的所有关键处理,并在使用后关注销毁关键材料。

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