如何用Python通过RSA公钥加密JWT数据?解决类型错误问题
解决Python RSA加密JWT时的TypeError问题
错误原因分析
抛出的TypeError: can't concat str to bytes核心原因是:PyCryptodome的PKCS1_OAEP加密方法要求输入必须是字节流(bytes),但你传入的JWT字符串是str类型,导致底层拼接字节与字符串时出错。
此外代码还有三个隐性问题:
- 分段加密长度设置不合理:PKCS1_OAEP的最大明文分段长度为
密钥位数//8 - 42(比如2048位密钥对应214字节),硬写20既浪费性能也不符合RSA加密规范。 - 结果拼接方式错误:加密后的分段是bytes类型,不能用字符串的
"".join(),会引发类型错误;且PHP返回的是Base64编码结果,Python代码需对应处理。 main函数中key变量未定义,需补充合法的RSA公钥内容。
修正后的代码
from Crypto.Cipher import PKCS1_OAEP from Crypto.PublicKey import RSA import base64 def rsa_long_encrypt(key_, msg, length=None): key = RSA.importKey(key_) cipher = PKCS1_OAEP.new(key) # 计算PKCS1_OAEP允许的最大明文分段长度 max_block_size = key.size_in_bytes() - 42 if length is None or length > max_block_size: length = max_block_size # 将字符串转换为UTF-8字节流 msg_bytes = msg.encode('utf-8') res = [] for i in range(0, len(msg_bytes), length): msg_to_en = msg_bytes[i:i+length] ciphertext = cipher.encrypt(msg_to_en) res.append(ciphertext) # 拼接字节分段并Base64编码,与PHP输出格式对齐 encrypted_bytes = b''.join(res) return base64.b64encode(encrypted_bytes).decode('utf-8') if __name__ == "__main__": # 替换为实际使用的RSA公钥(需带完整的BEGIN/END标识) public_key = """-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... (此处省略完整公钥内容) -----END PUBLIC KEY-----""" message = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' enres = rsa_long_encrypt(public_key, message) print(enres)
关键修改说明
- 字符串转字节:用
encode('utf-8')将JWT字符串转为字节流,满足encrypt()方法的参数要求。 - 动态计算分段长度:根据密钥自动计算最大允许的明文长度,避免硬编码导致的兼容性问题。
- 结果格式对齐:用
b''.join()拼接字节分段,再通过base64.b64encode()编码为字符串,与PHP输出的Base64格式匹配。 - 补充公钥定义:在
main函数中添加了公钥示例,需替换为实际的RSA公钥内容。
一致性验证注意事项
要确保Python代码与PHP代码使用相同的RSA公钥、相同的哈希算法(PKCS1_OAEP默认用SHA-1,若PHP使用SHA-256等其他哈希,需在Python中指定:PKCS1_OAEP.new(key, hashAlgo=SHA256.new())),才能得到一致的加密结果。
内容的提问来源于stack exchange,提问作者mosa lorans
相关产品推荐
相关产品推荐

