2017-01-10 101 views
7

나는 CRC32 계산을 많이하지 않고 내 머리를 잡으려고 노력했다. 내가 얻는 값이 내가 얻는 것과 일치하지 않는다.라이브러리를 사용하지 않고 파이썬에서 CRC32 계산

파이썬에는 이러한 체크섬 (즉, zlib 및 binascii)을 생성 할 수있는 라이브러리가 있지만, CRC 기능이 마이크로 파이썬에 존재하지 않으므로이를 사용할 수 없다는 점을 알고 있습니다.

import binascii 
import zlib 
from array import array 

poly = 0xEDB88320 

table = array('L') 
for byte in range(256): 
    crc = 0 
    for bit in range(8): 
     if (byte^crc) & 1: 
      crc = (crc >> 1)^poly 
     else: 
      crc >>= 1 
     byte >>= 1 
    table.append(crc) 

def crc32(string): 
    value = 0xffffffffL 

    for ch in string: 
     value = table[(ord(ch)^value) & 0x000000ffL]^(value >> 8) 

    return value 

teststring = "test" 

print "binascii calc: 0x%08x" % (binascii.crc32(teststring) & 0xffffffff) 
print "zlib calc:  0x%08x" % (zlib.crc32(teststring) & 0xffffffff) 
print "my calc:  0x%08x" % (crc32(teststring)) 

그런 다음 나는 다음과 같은 출력을 얻을 : 내 사람이하지 않는

binascii calc: 0xd87f7e0c 
zlib calc:  0xd87f7e0c 
my calc:  0x2780810c 

binascii 및 ZLIB 계산이 동의

지금까지 나는 다음과 같은 코드가 있습니다. 나는 계산 된 바이트의 표가 정확한지를 생각한다. 따라서 문제는 각 바이트가 계산되는 루틴이어야하며 누군가 올바른 방향으로 나를 가리킬 수 있습니까?

미리 감사드립니다.

답변

5

난 당신의 코드를 자세히 못 봤어, 내가 오류의 정확한 원인을 정확히 파악할 수는 없지만, 당신은 쉽게 원하는 출력 얻을 수를 조정할 수 있습니다

import binascii 
from array import array 

poly = 0xEDB88320 

table = array('L') 
for byte in range(256): 
    crc = 0 
    for bit in range(8): 
     if (byte^crc) & 1: 
      crc = (crc >> 1)^poly 
     else: 
      crc >>= 1 
     byte >>= 1 
    table.append(crc) 

def crc32(string): 
    value = 0xffffffffL 
    for ch in string: 
     value = table[(ord(ch)^value) & 0xff]^(value >> 8) 

    return -1 - value 

# test 

data = (
    '', 
    'test', 
    'hello world', 
    '1234', 
    'A long string to test CRC32 functions', 
) 

for s in data: 
    print repr(s) 
    a = binascii.crc32(s) 
    print '%08x' % (a & 0xffffffffL) 
    b = crc32(s) 
    print '%08x' % (b & 0xffffffffL) 
    print 

출력

을 여기
'' 
00000000 
00000000 

'test' 
d87f7e0c 
d87f7e0c 

'hello world' 
0d4a1185 
0d4a1185 

'1234' 
9be3e0a3 
9be3e0a3 

'A long string to test CRC32 functions' 
d2d10e28 
d2d10e28 

는 불통 crc32binascii.crc32가 동일한 결과를 제공하는지 확인 두개 이상의 시험이다.

from random import seed, randrange 

print 'Single byte tests...', 
for i in range(256): 
     s = chr(i) 
     a = binascii.crc32(s) & 0xffffffffL 
     b = crc32(s) & 0xffffffffL 
     assert a == b, (repr(s), a, b) 

print('ok') 

seed(42) 

print 'Multi-byte tests...' 
for width in range(2, 20): 
    print 'Width', width 
    r = range(width) 
    for n in range(1000): 
     s = ''.join([chr(randrange(256)) for i in r]) 
     a = binascii.crc32(s) & 0xffffffffL 
     b = crc32(s) & 0xffffffffL 
     assert a == b, (repr(s), a, b) 
print('ok') 

출력

Single byte tests... ok 
Multi-byte tests... 
Width 2 
Width 3 
Width 4 
Width 5 
Width 6 
Width 7 
Width 8 
Width 9 
Width 10 
Width 11 
Width 12 
Width 13 
Width 14 
Width 15 
Width 16 
Width 17 
Width 18 
Width 19 
ok 
주석에서 설명한 바와 같이

원래 코드에서 에러의 원인이 CRC-32 알고리즘은 초기 CRC 버퍼를 반전하고 있다는 것이다 최종 버퍼 내용을 반전시킵니다. 따라서 value은 0 대신에 0xffffffff으로 초기화되며 value^0xffffffff을 반환해야합니다. ~value & 0xffffffff, 즉 반전 value으로 작성하고 그 결과의 하위 32 비트를 선택할 수도 있습니다.

+0

당신은 선생님입니다. 빠른 답장과 해결책을 보내 주셔서 대단히 감사합니다! – Cooper

+0

@Cooper 걱정할 필요가 없습니다. 나는 100 % 비트 닝 연산을 이용한 산술 연산으로 인한 비틀기에 대해 확신하지 못한다. 제대로 작동하려면 _ 나타나지만, 어떤 경우에는 잘못된 대답을 줄 수도 있습니다. OTOH, 나는''\ xff \ xff \ xff \ xff ''를 넘겨 줄 때'ffffffff'를 리턴했음을 확인했다. 그래서 그것은 좋은 신호이다. :) –

+0

@Cooper 이러한 추가 테스트가 끝나면 자신감이 높아졌습니다. :) 그것은 어떤 입력에 대해 잘못된 결과를 반환한다면 나는 놀랄 것입니다. –