Python2.7中PyCrypto encrypt()函数的数据转换与类型疑问
encrypt() in Python 2.7: Data Types & XOR Operations Hey there! Let's work through your questions since you're new to Python 2.7 and PyCrypto—this stuff can feel confusing at first, but we'll break it down clearly.
1. Is os.urandom(16) output the same as a byte string?
Absolutely! In Python 2.7, the bytes type is identical to the str type (a key difference from Python 3, where they're separate). When you call os.urandom(16), you get back a 16-byte str object (a sequence of raw bytes), so this is perfect to use as your IV—no conversion needed here.
2. Preparing your plaintext blocks for encrypt()
You mentioned block_list is 16-byte chunks of your plaintext (with no padding). In Python 2.7, as long as your original plaintext is a str (byte string), splitting it into 16-byte blocks will give you exactly the format encrypt() expects.
- If your plaintext is a Unicode string (e.g.,
u"my message"), encode it to a byte string first using something likeplaintext.encode('utf-8')before splitting into blocks. - Since you're skipping padding, double-check that your total plaintext length is a multiple of 16 bytes—otherwise
encrypt()will throw an error.
3. XORing plaintext blocks with ciphertext blocks
PyCrypto's encrypt() function returns a byte string (str in Python 2.7), so you can directly perform XOR operations between your plaintext blocks and ciphertext blocks. The catch is you can't XOR the strings directly—you need to convert each byte to an integer, do the XOR, then convert back to a byte.
Here's a simple helper function to handle block XOR:
def xor_blocks(block_a, block_b): # Ensure both blocks are the same length (critical for valid XOR!) assert len(block_a) == len(block_b), "Blocks must be identical length" # Iterate over each byte pair, XOR them, and join back into a string return ''.join(chr(ord(byte_a) ^ ord(byte_b)) for byte_a, byte_b in zip(block_a, block_b))
Example workflow
Let's put this all together with AES (a common choice in PyCrypto):
from Crypto.Cipher import AES import os # Generate a 16-byte key (for AES-128) encryption_key = os.urandom(16) # Generate your 16-byte IV (required for modes like CBC) iv = os.urandom(16) # Your plaintext (32 bytes, so two 16-byte blocks—no padding needed) plaintext = "This is a 32-byte test message here!" # Split into 16-byte blocks block_list = [plaintext[i:i+16] for i in range(0, len(plaintext), 16)] # Initialize the cipher (using CBC mode as an example) cipher = AES.new(encryption_key, AES.MODE_CBC, iv) # Encrypt each block and perform your XOR operation processed_blocks = [] for plain_block in block_list: cipher_block = cipher.encrypt(plain_block) # XOR the plaintext block with the encrypted block xored_block = xor_blocks(plain_block, cipher_block) processed_blocks.append(xored_block) # Combine all processed blocks into your final output final_output = ''.join(processed_blocks)
Quick reminders
- In Python 2.7,
str= byte string—this is what PyCrypto expects for both input and output ofencrypt(). - Always ensure your blocks match the cipher's block size (16 bytes for AES) when skipping padding.
- If working with Unicode text, encode it to a byte string first (e.g., UTF-8) before passing to
encrypt().
内容的提问来源于stack exchange,提问作者Saara

