在python中解密ActiveSupport :: MessageEncryptor加密值

时间:2015-01-14 18:23:06

标签: python ruby-on-rails

我有一个rails项目,它具有存储在远程Postgresql数据库中的敏感字符串类型值。我使用ActiveSupport :: MessageEncryptor(http://api.rubyonrails.org/classes/ActiveSupport/MessageEncryptor.html)函数加密了这些字符串。我有用于加密它们的密钥,并试图找到一种方法从数据库中检索它们并在python脚本中解密它们。

我打开任何有关如何使用rails和python以任何其他方式实现此目的的建议。非常感谢有关如何在python中解密这些值的任何建议。

谢谢,

1 个答案:

答案 0 :(得分:0)

因此,我们通过大量尝试和尝试以及互联网上一些过时或类似代码的大量帮助,设法解决了这个问题。

不同库使用的版本:

Rails 版本(从中加密消息):5.2.x
Python 版本我们正在使用:3.8

我们也在使用 Django rest 框架(3.12.2)。

脚本中使用的库版本(这让我们有点难,因为一些库的新版本没有按预期工作,没有详细说明原因):

pycryptodomex3.9.7
cryptography3.3.1
rubymarshal1.2.7

实际的加密器/解密器

# pylint: disable=missing-module-docstring,too-few-public-methods
import base64
import hashlib
import os

from Cryptodome.Cipher import AES
from cryptography.hazmat.primitives.ciphers import Cipher
from rubymarshal.reader import loads
from rest_framework.response import Response
from rest_framework import status
from rubymarshal.writer import writes
from dotenv import load_dotenv

load_dotenv()

class MyRailsEncryptor():
    """
    This is a class for providing encryption/decryption functionality.
    """
    @classmethod
    def get_encrypted_data(cls, data):
        """
        This method handles encryption algorithm takes in data and return encrypted data
        """
        key = cls.get_key()
        iv = os.urandom(16)
        auth_tag = os.urandom(16)
        cipher = AES.new(key, AES.MODE_GCM, iv)
        ciphertext = cipher.encrypt(writes(data))
        ciphertext = base64.b64encode(ciphertext)
        iv = base64.b64encode(iv)
        auth_tag = base64.b64encode(auth_tag)

        blob = f'{ciphertext.decode("utf-8")}--{iv.decode("utf-8")}--{auth_tag.decode("utf-8")}' 
        return blob

    @classmethod
    def get_decrypted_data(cls, data):
        """
        This method handles decryption algorithm takes in encrypted_data and return decrypted plain text
        """
        key = cls.get_key()
        ciphertext, iv, auth_tag = data.split("--")
        ciphertext = base64.b64decode(ciphertext)
        iv = base64.b64decode(iv)
        cipher = AES.new(key, AES.MODE_GCM, iv)
        try:
            decrypted_data = cipher.decrypt(ciphertext)
        except AssertionError as err:
            return Response({"Assertion Error": err.message_dict}, status=status.HTTP_400_BAD_REQUEST)
        plaintext = loads(decrypted_data)
        return plaintext

    @classmethod
    def get_key(cls):
        """
        Returns key generated by Encryption key and Encryption secret using hashlib on rails methodology
        """
        return hashlib.pbkdf2_hmac('sha1', os.getenv("ENCRYPTION_KEY").encode(),
                            os.getenv("ENCRYPTION_SECRET").encode(), 65536, 32)

密钥显然是由加密方同步/提供的,这也包含了一种加密方法,尽管我们只需要解密。