Python 3.x RSA场景下字典值更新为布尔值的代码修复问题
Hey there, let's break down what's going wrong with your code and fix it step by step.
The Two Big Issues
You're running into two problems here:
- RuntimeError: dictionary changed size during iteration: When you loop through
D.items()and add new keys (likeD[v] = True), you're altering the dictionary's size while iterating over it—Python blocks this because it can lead to unexpected behavior. - Wrong key updates: You're using the signature value
vas the key for your boolean result instead of the original message keyk, which means you're creating new entries instead of updating the existing ones you care about.
Why Your Code Triggers the Error
Let's look at the problematic loop:
for k,v in D.items(): if (v ** key[0]) % key[1] == int(k) % key[1]: D[v] = True # This adds a NEW key (the signature number) to D else: D[v] = False # Same issue: modifying the dict mid-iteration
Every time you run D[v] = ..., you're adding a new key-value pair to the dictionary. This changes its size while the loop is still running, which throws the RuntimeError. Plus, you're not updating the original keys ("1" and "2" in your example) at all—so even if the loop worked, your output wouldn't match what you expect.
The Fixed Code
The cleanest approach is to build a new dictionary for your verification results instead of modifying the original one during iteration. Here's the corrected version:
def Q1(D, key): e, N = key # Unpack the public key tuple for readability verification_results = {} for msg, signature in D.items(): # RSA verification logic: signature^e mod N should equal message mod N computed_msg = pow(signature, e, N) # Way more efficient than (v**e)%N for big numbers original_msg = int(msg) % N verification_results[msg] = computed_msg == original_msg return verification_results
What We Improved
- No more RuntimeError: We create a new dictionary to store results, so we never modify the original dict while iterating over it.
- Correct key assignments: We use the original message key (
msg) to store the boolean result, which matches your expected output format. - Efficient exponentiation: Using
pow(signature, e, N)is faster and avoids potential overflow issues that can happen with(signature ** e) % Nwhen working with large RSA values. - Better readability: Unpacking the public key into
eandNmakes the code easier to follow at a glance.
Test It With Your Example
Let's run your sample input to confirm it works:
D = {"1":2,"2":3} public_key = (5,14) print(Q1(D, public_key)) # Output: {"1": True, "2": False}
That's exactly the result you wanted!
Alternative: Modify the Original Dictionary Safely
If you need to update the original dictionary instead of returning a new one, iterate over a copy of the keys (so the loop doesn't care if the dict size changes):
def Q1(D, key): e, N = key # Iterate over a static list of the original keys for msg in list(D.keys()): signature = D[msg] computed_msg = pow(signature, e, N) original_msg = int(msg) % N D[msg] = computed_msg == original_msg return D
This works because list(D.keys()) creates a snapshot of the original keys—even if you modify the dictionary during the loop, the iteration uses the static list.
内容的提问来源于stack exchange,提问作者kaydiyoung22

