如何在R语言中解密通过Python Fernet算法加密的字符串?
在R中解密Python Fernet加密的字符串
问题背景
我用Python的Fernet算法加密了字符串,现在需要在R语言中解密该值。已知:
- 原始密钥:
ThisIsTheRealKeyItIsAVeryGoodOne - 示例加密字符串:
gAAAAABkCluAsIXI905vOlZsut1CvVtboIZ2_NHalTQLbsZv_ogl0reBBWg4v0UlTcg5aqMRzBfFxKBGVGUHYqepeNQb8wpfgQ== - 目标解密结果:
hello
解决方案
使用R的openssl包处理加密和解密逻辑,步骤如下:
1. 安装并加载依赖包
install.packages("openssl") library(openssl)
2. 处理密钥,拆分加密与签名密钥
Fernet的密钥需要先转成URL-safe的Base64编码,再解码为32字节的原始密钥,然后拆分为前16字节的AES加密密钥,和后16字节的HMAC签名密钥:
# 原始密钥 raw_key <- charToRaw("ThisIsTheRealKeyItIsAVeryGoodOne") # 生成URL-safe的Base64编码(和Python的base64.urlsafe_b64encode行为一致) b64_key <- base64_encode(raw_key, url = TRUE) # 解码为32字节的Fernet密钥 fernet_key <- base64_decode(b64_key, url = TRUE) # 拆分加密密钥(前16字节)和签名密钥(后16字节) encryption_key <- fernet_key[1:16] signing_key <- fernet_key[17:32]
3. 解码并拆分Fernet Token
Fernet Token是Base64编码的字节流,拆分出版本、时间戳、IV、密文和HMAC校验值:
# 示例加密字符串 encrypted_str <- "gAAAAABkCluAsIXI905vOlZsut1CvVtboIZ2_NHalTQLbsZv_ogl0reBBWg4v0UlTcg5aqMRzBfFxKBGVGUHYqepeNQb8wpfgQ==" # 解码为原始字节 token_bytes <- base64_decode(encrypted_str, url = TRUE) # 拆分各部分:版本(1字节)、时间戳(8字节)、IV(16字节)、密文(剩余字节-32)、HMAC(32字节) version <- token_bytes[1] timestamp <- token_bytes[2:9] iv <- token_bytes[10:25] ciphertext <- token_bytes[26:(length(token_bytes)-32)] received_hmac <- token_bytes[(length(token_bytes)-31):length(token_bytes)]
4. 验证HMAC签名
确保Token未被篡改,用签名密钥计算HMAC并与Token中的HMAC对比:
# 计算待签名的内容:版本+时间戳+IV+密文 sign_data <- c(version, timestamp, iv, ciphertext) # 计算HMAC-SHA256 computed_hmac <- hmac_sha256(sign_data, signing_key) # 验证签名是否一致 if (!identical(computed_hmac, received_hmac)) { stop("Token签名验证失败,可能已被篡改或密钥错误") }
5. 解密得到明文
使用AES-CBC算法,配合加密密钥和IV,采用PKCS7填充解密:
# AES-CBC解密,PKCS7填充是默认行为 decrypted_raw <- aes_cbc_decrypt(ciphertext, key = encryption_key, iv = iv) # 转成字符串 plaintext <- rawToChar(decrypted_raw) # 输出结果 cat("解密结果:", plaintext, "\n")
运行以上代码后,会输出解密结果: hello,即为目标明文。
内容的提问来源于stack exchange,提问作者MrFlick
相关产品推荐
相关产品推荐

