如何用Python解密经R语言sodium包加密的密钥?
问题:用Python复刻R语言sodium包的decrypt_access_key函数
我有一套用R语言sodium包实现的、通过密码加解密访问密钥的函数:
encrypt_access_key <- function(access_key, password) { key <- sha256(charToRaw(password)) nonce <- random(24) # 生成随机nonce encrypted <- data_encrypt(charToRaw(access_key), key, nonce) list( encrypted_access_key = base64encode(encrypted), nonce = base64encode(nonce) ) } decrypt_access_key <- function(encrypted_access_key, nonce, password) { key <- sha256(charToRaw(password)) encrypted_raw <- base64decode(encrypted_access_key) nonce_raw <- base64decode(nonce) rawToChar(data_decrypt(encrypted_raw, key, nonce_raw)) }
我需要编写一个Python函数复刻上述decrypt_access_key的功能,但尝试均未成功。以下是可直接复现的解密示例:
decrypt_access_key(encrypted_access_key = "QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w==", nonce = "LpO7fBaCs1iobxDxVmOPFycTe/BCifqh", password = "Example123")
我尝试的失败Python代码
import base64 from Crypto.Cipher import ChaCha20_Poly1305 from Crypto.Protocol.KDF import PBKDF2 import hashlib def decrypt_access_key(encrypted_access_key, nonce, password): # 解码base64编码的内容 encrypted_access_key_bytes = base64.b64decode(encrypted_access_key) nonce_bytes = base64.b64decode(nonce) # 使用PBKDF2推导密钥 key = hashlib.pbkdf2_hmac('sha256', password.encode(), b'', 100000) # 用ChaCha20-Poly1305解密 cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce_bytes) decrypted = cipher.decrypt(encrypted_access_key_bytes) return decrypted.decode('utf-8') # 示例调用 encrypted_access_key = 'QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w==' nonce = 'LpO7fBaCs1iobxDxVmOPFycTe/BCifqh' password = 'Example123' decrypted_access_key = decrypt_access_key(encrypted_access_key, nonce, password) print(decrypted_access_key)
正确的Python实现
失败原因主要有三点:
- 密钥推导错误:R中是直接对密码的原始字节做SHA256哈希,而非PBKDF2
- 加密算法混淆:R的
data_encrypt默认使用XChaCha20-Poly1305(对应24字节nonce),不是普通的ChaCha20-Poly1305 - 密文结构处理错误:
data_encrypt返回的是「密文 + 16字节Poly1305校验标签」,解密时需要拆分这两部分
以下是修正后的代码:
import base64 import hashlib from Crypto.Cipher import ChaCha20_Poly1305 def decrypt_access_key(encrypted_access_key, nonce, password): # 解码base64内容 encrypted_data = base64.b64decode(encrypted_access_key) nonce_bytes = base64.b64decode(nonce) # 按R的逻辑推导密钥:密码转UTF-8字节后做SHA256哈希 key = hashlib.sha256(password.encode('utf-8')).digest() # 拆分密文和Poly1305标签(最后16字节是标签) ciphertext = encrypted_data[:-16] tag = encrypted_data[-16:] # 使用XChaCha20-Poly1305解密(24字节nonce对应XChaCha20) cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce_bytes) decrypted = cipher.decrypt_and_verify(ciphertext, tag) return decrypted.decode('utf-8') # 测试示例 encrypted_access_key = 'QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w==' nonce = 'LpO7fBaCs1iobxDxVmOPFycTe/BCifqh' password = 'Example123' print(decrypt_access_key(encrypted_access_key, nonce, password)) # 输出:This is a hidden message
内容的提问来源于stack exchange,提问作者Ekapunk
相关产品推荐
相关产品推荐

