2010-07-01 41 views
8

Tôi đang làm việc trên một dự án python trong 2.6 cũng có hỗ trợ trong tương lai cho python 3 đang làm việc. Cụ thể là tôi đang làm việc trên một thuật toán digest-md5.Python: ghép nối các byte với một chuỗi

Trong python 2,6 mà không cần chạy nhập khẩu này:

from __future__ import unicode_literals 

tôi có thể viết một đoạn mã như thế này:

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

Nếu không có bất kỳ vấn đề, xác thực của tôi hoạt động tốt. Khi tôi cố gắng cùng một dòng mã với unicode_literals import tôi nhận được một ngoại lệ:

UnicodeDecodeError: 'utf8' giải mã không thể giải mã byte 0xa8 ở vị trí 0: bất ngờ mã byte

Bây giờ tôi là tương đối mới để python vì vậy tôi là một chút khó khăn trong việc tìm ra điều này. nếu tôi thay thế% s trong chuỗi định dạng là% r Tôi có thể ghép chuỗi, nhưng xác thực không hoạt động. Thông số digest-md5 mà tôi đã đọc nói rằng thông số phân giải nhị phân 16 octet phải được nối thêm vào các chuỗi khác.

Mọi suy nghĩ?

+1

Python 3.x tách rõ ràng chuỗi khỏi mảng byte. Tùy thuộc vào nhu cầu của bạn, nó * có thể * làm việc để thêm vào các mẫu '"% s:% s:% s "' với 'b' để lấy một mảng byte, nhưng điều đó cũng có thể cho kết quả sai. Mục đích của mã này là gì? – Philipp

+0

Đây là đoạn trích của một đoạn mã lớn hơn được sử dụng cho thuật toán digest-md5 mà tôi đang sử dụng để xác thực đối với máy chủ xmpp và đây là đoạn mã cụ thể đang gây ra cho tôi một số vấn đề. Trước khi chờ chuỗi định dạng bằng b vẫn gây ra cùng một vấn đề. Dưới đây là một số thông tin khác về cách tạo một digest-md5 http://web.archive.org/web/20050224191820/http://cataclysm.cx/wip/digest-md5-crash.html – Macdiesel

Trả lời

5

Lý do cho hành vi mà bạn quan sát là from __future__ import unicode_literals chuyển cách Python làm việc với chuỗi:

  • Trong 2 Chuỗi .x, các chuỗi không có tiền tố u được coi là chuỗi byte, mỗi chuỗi có thể nằm trong phạm vi \ x00- \ xff (bao gồm). Các chuỗi có tiền tố u là các chuỗi unicode được mã hóa ucs-2.
  • Trong Python 3.x - cũng như trong tương lai unicode_literals, các chuỗi không có tiền tố u là các chuỗi unicode được mã hóa theo UCS-2 hoặc UCS-4 (phụ thuộc vào cờ trình biên dịch được sử dụng khi biên dịch Python). Các chuỗi có tiền tố b là các chữ cái cho loại dữ liệu bytes tương tự như các chuỗi không phải là unicode trước 3.x.

Trong cả hai phiên bản Python, chuỗi byte và chuỗi unicode phải được chuyển đổi. Chuyển đổi được thực hiện theo mặc định phụ thuộc vào bộ ký tự mặc định của hệ thống của bạn; trong trường hợp của bạn là UTF-8. Nếu không đặt bất kỳ thứ gì, nó phải là ascii, từ chối tất cả các ký tự ở trên \ x7f.

Thông báo được trả về bởi hashlib.md5 (...). Digest() là một chuỗi byte và tôi giả sử bạn muốn kết quả của toàn bộ hoạt động là chuỗi byte.Nếu bạn muốn điều đó, chuyển đổi các nonce và cnonce-strings để byte-strings .:

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")) 

Ngoài ra, bạn có thể chuyển đổi các byte dây đến từ các cuộc gọi đến digest() thành một chuỗi unicode (không khuyến khích). Vì bit 8 bit dưới của UCS-2 tương đương với ISO-8859-1, điều này có thể đáp ứng nhu cầu của bạn:

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

Giải pháp đầu tiên làm việc với mã. Cảm ơn bạn vì câu trả lời sâu sắc của bạn. – Macdiesel

1

Vấn đề là "% s:% s:% s" đã trở thành chuỗi unicode khi bạn đã nhập unicode_literals. Đầu ra của băm là một chuỗi "thông thường". Python đã cố gắng giải mã chuỗi thông thường thành chuỗi unicode và không thành công (như mong đợi. Đầu ra băm được cho là trông giống như tiếng ồn). Thay đổi mã của bạn như thế này:

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

Tôi giả định cnoncechallenge["nonce"] là chuỗi thông thường. Để có thêm quyền kiểm soát chuyển đổi của họ để dây (nếu cần), sử dụng:

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

Giải pháp và giải thích này cũng công trinh. Cảm ơn bạn. – Macdiesel

Các vấn đề liên quan