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

R调用Python传敏感参数:RSA加密解密失败技术问询

解决R与Python间RSA加密解密的二进制数据传递问题

你碰到的这个问题其实挺典型的——核心就是二进制加密数据在跨进程传递时的格式混乱,再加上原代码里的几个小错误(比如密钥用反了、填充不匹配),导致解密完全不对。我来帮你一步步修正:

先说说原代码的几个关键问题

  • 直接把R中PKI.encrypt返回的原始二进制数据传给Python:命令行参数只能传字符串,二进制数据会被自动转成R的原始字符串表示(比如raw(n) 0xXX 0xXX...),Python拿到的根本不是真实的加密字节。
  • RSA密钥用反了:RSA的正确逻辑是公钥加密,私钥解密,你原代码用私钥加密,不仅失去了加密的意义(公钥是公开的,任何人都能解密),还会导致填充逻辑不匹配。
  • 填充方式没明确指定:R和Python默认的填充规则可能不一致,直接解密就会触发填充错误。

修正后的完整代码

R端代码(main.R)

# main.R
library(PKI)
library(base64enc)

# 生成2048位RSA密钥对
key_pair <- PKI.genRSAkey(2048L)
# 保存私钥给Python解密用
PKI.save.key(key_pair, target = "privkey.pem", private = TRUE)
# 提取公钥用于加密(正确流程:公钥加密,私钥解密)
pubkey <- PKI.save.key(key_pair, target = NULL, private = FALSE)
pubkey <- PKI.load.key(pubkey)

# 要加密的敏感数据,转成原始字节
msg <- charToRaw("password")
# 用公钥加密,指定PKCS#1 v1.5填充(和Python端统一)
msg_encrypted <- PKI.encrypt(msg, pubkey, type = "PKCS1")
# 把二进制加密数据转成Base64字符串,避免命令行传递时的二进制转义问题
msg_encrypted_b64 <- base64encode(msg_encrypted)

# 调用Python脚本,传递Base64编码的加密字符串
result <- system2("python", args = c("dostuff.py", msg_encrypted_b64), stdout = TRUE)
print(result)

Python端代码(dostuff.py)

# dostuff.py
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
import sys

# 加载R生成的私钥
private_key = RSA.import_key(open("privkey.pem").read())
# 初始化PKCS#1 v1.5解密器(和R端的填充方式一致)
cipher = PKCS1_v1_5.new(private_key)

# 接收命令行传入的Base64加密字符串,解码回二进制数据
encrypted_b64 = sys.argv[1]
encrypted_data = base64.b64decode(encrypted_b64)

# 解密数据,转成UTF-8字符串
decrypted_data = cipher.decrypt(encrypted_data, sentinel=None).decode("utf-8")
print(f"Decryption returned: {decrypted_data}")

关键说明

  1. Base64编码的必要性:二进制数据在命令行传递时会被shell解析转义,Base64把二进制转成纯ASCII字符串,完美解决跨进程传递的格式损坏问题。
  2. 密钥流程修正:公钥加密保证只有持有私钥的一方能解密,这才是RSA加密的正确用法。
  3. 填充方式统一:两端都明确使用PKCS#1 v1.5填充,避免出现"binascii.Error: Incorrect padding"这类填充错误。

前置依赖安装

  • R端:运行前先安装需要的包
    install.packages(c("PKI", "base64enc"))
    
  • Python端:安装pycryptodome(替代过时的pycrypto
    pip install pycryptodome
    

现在运行你的脚本,应该就能得到预期的password了!

内容的提问来源于stack exchange,提问作者Wassadamo

火山引擎 最新活动