2009-06-15 4 views
1

특정 프로젝트에 대한 필자의 요구를 충족시키는 간단한 순수 파이썬 복어 구현을 발견했습니다.이 블록 암호 키 기능을 리 팩터 처리합니다.

날 귀찮게 그것의 한 부분있다 :

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')은? 더 좋은 방법이 있다고 말해주세요.

문자열의 16 진수 값 대신 실제 정수 유형을 사용하도록 리팩터링하는 방법이 없습니까?

답변

5

예. 그래서 16

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

의베이스() INT를 사용

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

는 평가를 필요없이 같은 일을해야한다.

[편집] 사실는 정수 주어, 일반적으로는 모든 문자열 표현으로 변환해야 할 것입니다 왜 아무 이유도 없다 - 단순히 0xffffffff과 변화와 AND 연산하여 각 32 비트 값을 추출 할 수 있습니다 루프에서 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) 

그러나,이 초기화 과정은 조금 이상한 것 같다 - 그렇게 수 0x123456789 분할 될 수 8 16 진수의 배수 (반올림 할 수없는 제로 패딩으로, 왼쪽에서 시작하는 16 진수를 사용하고 0x123456780x9로, 또한 오히려 하나의 큰 숫자로 치료하는 것보다이 번호를 반복하지 않고 0x000000010x23456789 더 관습보다..이 코드가 실제로 올바른 알고리즘을 수행하고 있음을 확인해야합니다.

+0

이 코드는 schneier의 테스트 벡터 인 http://www.schneier.com/code/vectors.txt와 정확하게 일치합니다. 즉, 나는이 문자열 슬라이스의 어리 석음을 엉망이 아닌 schneier의 C 코드 (매우 복잡하지 않음)에 대해 다시 작성하려고합니다. –

+0

사용 된 특정 키가 될 수 있습니까? 선행 제로 니블 (94 % 가능성)이 없으면 문자열은 8 진수 숫자의 배수가 될 것이므로 실제로 차이가 없습니다. 그렇지 않으면 다른 경계에서 일반 내부 표현으로 분할됩니다. – Brian

1

을 대안이다 "int ('0x111', 0)"int의 두 번째 인수가 기본입니다. "0"은 "일반적인 규칙을 사용합니다. 접두사는 십진수이며, 접두어 0은 8 진수이고 0x는 헥사입니다 - 마치 eval과 같습니다.

문자열을 지정하는 경우 eval 연산을 "에뮬레이트"하는 것이 좋습니다.

0

당신은 긴 기능이 작업을 수행 할 수 있습니다

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

help(long)에서 :

클래스 긴 (객체)
| long (x [, base]) -> 정수
|
| 가능한 경우 문자열 또는 숫자를 긴 정수로 변환하십시오. 플로팅
| 점 인수가 0으로 잘립니다 (이 경우
| 부동 소수점 숫자의 문자열 표현이 변환되지 않습니다.)
| 문자열의 경우 선택적 기본을 사용하십시오. 기지를 공급하는 것은 오류 일 때
| 비 문자열 변환.

3

이 코드를 사용하지 마십시오.

인터넷에서 발견 된 암호 코드를 사용하면 소프트웨어에 심각한 보안 오류가 발생할 가능성이 있습니다. 주제에 관한 내용은 Jeff Atwood's little series을 참조하십시오.

가장 높은 추상화 수준에서 입증 된 암호화 라이브러리를 사용하는 것이 훨씬 낫습니다. 이상적으로는 C에서 모든 키 처리를 구현하고 사용 후 키 재료를 파기하는 것입니다.

파이썬에서 암호화를 수행하는 한 가지 문제는 파이썬 문자열과 가비지 수집 프로세스의 특성으로 인해 메모리에서 주요 자료의 확산을 제어 할 수 없다는 것입니다.

관련 문제