You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python中实现RSA密钥生成、消息签名、接收方公钥加密及Base64编码的完整流程并解决相关错误?

如何在Python中实现RSA密钥生成、消息签名、接收方公钥加密及Base64编码的完整流程并解决相关错误?

我尝试用朋友的公钥recipient_public_key加密新生成的密钥,然后将最终结果用Base64编码。这个流程也可以通过安装相关工具后用Kleopatra这类工具分步完成,但我不想使用这类工具。

任务要求

生成一个1024位的RSA密钥对,使用你的用户名作为标识。针对以下消息,仅签名不加密:

待签名消息:This is my secret message

在一个文本文件中包含以下内容:你的公钥、上述消息、消息的Base64编码签名。然后用接收方的公钥加密这个文件,将最终输出Base64编码后打印出来。

我的尝试与遇到的问题

最开始我用Python的相关库(比如python-gnupg、pycryptodome)生成了以我的名字作为用户名的1024位RSA密钥对,尝试按要求签名消息,但遇到了如下错误:

ValueError: Plaintext is too long.

第一种实现方式(使用pycryptodome和pgpy)

# !pip install pycryptodome
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
import base64
import pgpy # Import pgpy

# Step 1: Generate RSA key pair
key = RSA.generate(1024)
private_key = key.export_key()
public_key = key.publickey().export_key()

# Step 2: Save your public key for submission
with open("my_public_key.pem", "wb") as f:
    f.write(public_key)

# Step 3: Prepare the message with your name
message = "This is my secret messgae"
message_bytes = message.encode()

# Step 4: Sign the message with the private key
hash_message = SHA256.new(message_bytes)
signature = pkcs1_15.new(key).sign(hash_message)

# Step 5: Base64 encode the signature
signature_base64 = base64.b64encode(signature)

# Step 6: Save the public key, message, and signature in a file
with open("final-msg.txt", "wb") as f:
    f.write(public_key + b"\n" + message_bytes + b"\n" + signature_base64)

# Step 7: Encrypt the final message with the provided public key
recipient_public_key_pem = """-----BEGIN PGP PUBLIC KEY BLOCK-----
.............
-----END PGP PUBLIC KEY BLOCK-----"""

# Step 7: Encrypt the final message with the provided public key

# **Increased key size to 2048 bits**
key = RSA.generate(2048)  
private_key = key.export_key()
public_key = key.publickey().export_key()

# Use pgpy to import the PGP key
recipient_key, _ = pgpy.PGPKey.from_blob(recipient_public_key_pem) 

# Re-initialize cipher_rsa with the new key
cipher_rsa = PKCS1_OAEP.new(key) 

# Encrypt final-msg.txt with the recipient's public key
with open("final-msg.txt", "rb") as f:
    final_msg = f.read()
encrypted_message = cipher_rsa.encrypt(final_msg)

# Step 8: Base64 encode the encrypted message
encrypted_message_base64 = base64.b64encode(encrypted_message)

# Step 9: Save the base64 encoded encrypted message
with open("final_msg_base64.txt.gpg", "wb") as f:
    f.write(encrypted_message_base64)

print("Encryption completed. The Base64-encoded encrypted message is saved in 'final_msg_base64.txt.gpg'")

第二种实现方式(遵循DRY原则,使用python-gnupg)

# !pip install python-gnupg
import gnupg
import base64

# Initialize GPG
gpg = gnupg.GPG()

# 1. Generate an RSA Key Pair
input_data = gpg.gen_key_input(
    key_type="RSA",
    key_length=1024,
    name_real="Alice Bob",             # Replace with your name
    name_email="Alice.Bob@gmail.com",  # Replace with your email
    expire_date=0  # Key does not expire
)
key = gpg.gen_key(input_data)
print(f"Generated Key Fingerprint: {key.fingerprint}")

# 2. Create the message
message = f"This is my secret message"
with open("msg.txt", "w") as f:
    f.write(message)

# 3. Sign the message
#signed_data = gpg.sign(message, default_key=key.fingerprint, detach=True)
signed_data = gpg.sign(message, keyid=key.fingerprint, detach=True) 

# Write the signature data to a file in binary mode
with open("msg.sig", "wb") as f:  # Open in binary write mode ("wb")
    f.write(signed_data.data)  # Write the bytes directly

# 4. Base64 encode the signature
with open("msg.sig", "rb") as sig_file:
    signature_base64 = base64.b64encode(sig_file.read()).decode("utf-8")
    with open("msg-base64.sig", "w") as encoded_sig_file:
        encoded_sig_file.write(signature_base64)

# 5. Export your public key
public_key = gpg.export_keys(key.fingerprint)
with open("my_public_key.asc", "w") as pubkey_file:
    pubkey_file.write(public_key)

# 6. Concatenate the public key, message, and Base64-encoded signature
with open("final-msg.txt", "w") as final_file:
    final_file.write(public_key)
    final_file.write("\n" + message + "\n")
    final_file.write(signature_base64)

# 7. Import recipient's public key
recipient_public_key ="""-----BEGIN PGP PUBLIC KEY BLOCK-----

..........
-----END PGP PUBLIC KEY BLOCK-----"""
# Replace with the actual provided public key
import_result = gpg.import_keys(recipient_public_key)
print("Imported Recipient's Public Key:", import_result.fingerprints)

# 8. Encrypt the final message with the recipient's public key
with open("final-msg.txt", "rb") as final_msg_file:
    # Use encrypt instead of encrypt_file
    encrypted_data = gpg.encrypt(
        final_msg_file.read(),  # Read the file content
        import_result.fingerprints,  # Pass recipients as positional argument
        output="final-msg.txt.gpg" 
    )
    if encrypted_data.ok:
        print("Message encrypted successfully.")
    else:
        print(f"Encryption failed: {encrypted_data.status}") # Print the error status
        print(encrypted_data.stderr)                         # Print any error details to help with debugging
        
# Only proceed to base64 encoding if encryption was successful
if encrypted_data.ok:        
    # 9. Base64 encode the encrypted file
    with open("final-msg.txt.gpg", "rb") as encrypted_file:
        encrypted_base64 = base64.b64encode(encrypted_file.read()).decode("utf-8")
        with open("final_msg_base64.txt.gpg", "w") as encoded_encrypted_file:
            encoded_encrypted_file.write(encrypted_base64)

    # Output the Base64 encoded result
    print("Base64 Encoded Encrypted Message:")
    print(encrypted_base64)
else:
    print("Skipping base64 encoding due to encryption failure.")

运行第二种方式后,我得到了如下错误输出:

WARNING:gnupg:potential problem: ERROR: key_generate 83918950
WARNING:gnupg:gpg returned a non-zero error code: 2
WARNING:gnupg:potential problem: FAILURE: sign 17
WARNING:gnupg:gpg returned a non-zero error code: 2
WARNING:gnupg:gpg returned a non-zero error code: 2
WARNING:gnupg:gpg returned a non-zero error code: 2
Generated Key Fingerprint: 
Imported Recipient's Public Key: ['1AB8693860852A6B0EE7DD81B8F979BA0A99A039']
Encryption failed: invalid recipient
[GNUPG:] KEY_CONSIDERED 1AB8693860852A6B0EE7DD81B8F979BA0A99A039 0
gpg: 8D7830FB995B0A91: There is no assurance this key belongs to the named user
[GNUPG:] INV_RECP 10 1AB8693860852A6B0EE7DD81B8F979BA0A99A039
[GNUPG:] FAILURE encrypt 53
gpg: [stdin]: encryption failed: Unusable public key

Skipping base64 encoding due to encryption failure.

我现在的疑问是:如何正确实现用目标接收方的公钥recipient_public_key加密包含密钥、消息和签名的文件,然后Base64编码,让接收方可以用自己的密钥解密并读取消息?


备注:内容来源于stack exchange,提问作者Mario

火山引擎 最新活动