2010-07-01 3 views
8

2.6에서 파이썬 프로젝트를 작업하고 있는데 파이썬 3의 향후 지원이 있습니다. 특히 digest-md5 알고리즘을 사용하고 있습니다. 이 가져 오기를 실행하지 않고 파이썬 2.6에서파이썬 : 문자열을 바이트로 연결하기

는 :

from __future__ import unicode_literals 

나는 이와 같은 코드의 조각을 쓸 수 있어요 : 문제없이

a1 = hashlib.md5("%s:%s:%s" % (self.username, self.domain, self.password)).digest() 
a1 = "%s:%s:%s" %(a1, challenge["nonce"], cnonce) 

, 내 인증이 잘 작동합니다.

UnicodeDecodeError : 나는 unicode_literals와 동일한 코드 라인을 때 나는 예외가 가져온 'UTF8'코덱이 위치 0 바이트 0xa8을 디코딩 할 수 없습니다 예기치 않은 코드 바이트

가 지금은 비교적 새로운 해요 파이썬 그래서 나는 이것을 알아 내는데 조금 갇혀있다. 형식 문자열에서 % s을 % r (으)로 바꾸면 문자열을 연결할 수 있지만 인증이 작동하지 않습니다. 내가 읽었던 digest-md5 스펙은 16 옥텟 바이너리 다이제스트가이 다른 문자열에 추가되어야한다고 말한다.

의견이 있으십니까?

+1

Python 3.x는 문자열을 바이트 배열에서 명확히 구분합니다. 필요에 따라 바이트 배열을 얻기 위해'% s : % s : % s "과'b' 패턴을 앞에 붙일 수도 있지만 잘못된 결과를 줄 수도 있습니다. 어쨌든이 코드의 목적은 무엇입니까? – Philipp

+0

이것은 xmpp 서버에 대해 인증 할 때 사용하는 digest-md5 알고리즘에 사용되는 더 큰 코드 단편입니다.이 코드는 특정 문제를 일으키는 특정 부분입니다. b와 함께 서식 문자열이 미리 보류되어 있어도 동일한 문제가 발생합니다. 다음은 digest-md5를 만드는 방법에 대한 추가 정보입니다. http://web.archive.org/web/20050224191820/http://cataclysm.cx/wip/digest-md5-crash.html – Macdiesel

답변

5

당신이 관찰 된 행동에 대한 이유는 from __future__ import unicode_literals 파이썬 문자열과 함께 작동하는 방식으로 전환한다는 것입니다 : 2에서

  • 을 .x 계열의 경우 u이없는 문자열은 각각 \ x00- \ xff (범위 포함) 범위의 바이트 시퀀스로 처리됩니다. u 접두어가 붙은 문자열은 ucs-2로 인코딩 된 유니 코드 시퀀스입니다.
  • unicode_literals뿐만 아니라 u 접두어가없는 문자열은 UCS-2 또는 UCS-4로 인코딩 된 유니 코드 문자열입니다 (파이썬 컴파일시 사용되는 컴파일러 플래그에 따라 다름). b 접두사가있는 문자열은 데이터 형식이 bytes 인 리터럴이며 이전 3.x 비 유니 코드 문자열과 비슷합니다.

두 버전의 Python에서는 바이트 문자열과 유니 코드 문자열을 변환해야합니다. 기본적으로 수행되는 변환은 시스템의 기본 문자 집합에 따라 다릅니다. 귀하의 경우 이것은 UTF-8입니다. 아무것도 설정하지 않으면 ascii이어야하며 \ x7f 이상의 모든 문자는 거부됩니다.

hashlib.md5 (...). digest()가 반환하는 메시지 요약은 바이트 문자열이며, 전체 연산의 결과가 바이트 문자열이되기를 원한다고 가정합니다.당신이 바이트 문자열 : 또는

a1 = hashlib.md5("%s:%s:%s" % (self.username, self.domain, self.password)).digest() 
# note that UTF-8 may not be the encoding required by your counterpart, please check 
a1 = b"%s:%s:%s" %(a1, challenge["nonce"].encode("UTF-8"), cnonce.encode("UTF-8")) 

에 넌스 및 cnonce - 문자열을 변환하는 것이 원하는 경우, 당신은 유니 코드 문자열에 digest()에 대한 호출에서 나오는 바이트 문자열을 변환 할 수 있습니다 (권장하지 않음). UCS-2의 하위 8 비트가 ISO-8859-1과 같기 때문에 다음과 같이 사용자 요구에 부응 할 수 있습니다.

a1 = hashlib.md5("%s:%s:%s" % (self.username, self.domain, self.password)).digest() 
a1 = "%s:%s:%s" %(a1.decode("ISO-8859-1"), challenge["nonce"], cnonce) 
+0

첫 번째 솔루션은 코드로 작업했습니다. 귀하의 통찰력있는 답변에 감사드립니다. – Macdiesel

1

unicode_literals를 가져 오면 "% s : % s : % s"이 (가) 유니 코드 문자열이되었습니다. 해시 출력은 "일반"문자열입니다. 파이썬은 일반 문자열을 유니 코드 문자열로 디코드하려고 시도했으나 예상대로 실패했습니다. 해시 출력은 노이즈처럼 보입니다. 여기에 코드를 변경 : 나는 cnonce을 가정하고있어 challenge["nonce"] 일반 문자열

a1 = a1 + str(':') + str(challenge["nonce"]) + str(':') + str(cnonce) 

. (필요한 경우), 사용 문자열로 자신의 전환을 통해보다 효율적으로 제어 할하려면

a1 += str(':') + challenge["nonce"].encode('UTF-8') + str(':') + cnonce.encode('UTF-8') 
+0

이 해결책과 설명 공장. 고맙습니다. – Macdiesel

관련 문제