Skip to content

Instantly share code, notes, and snippets.

@sh4dowb
Last active April 17, 2021 18:14
Show Gist options
  • Save sh4dowb/4d39cc0f6a30f7df43e202d9ffb26e2c to your computer and use it in GitHub Desktop.
Save sh4dowb/4d39cc0f6a30f7df43e202d9ffb26e2c to your computer and use it in GitHub Desktop.
Decrypt Ruby's ActiveSupport::MessageEncryptor on Python 3
import hashlib
import base64
from Crypto import Random
from Crypto.Cipher import AES
import rubymarshal.reader
from pbkdf2 import PBKDF2
SECRET = "asdasd"
ITERATIONS = 65536
KEYLENGTH = 32
saltdic = {} # dont generate key again if it exists
def decrypt_secret(encrypted):
global saltdic
salt = encrypted.split('.')[0]
parts = encrypted.split('.')[1].split(b"--")
if salt not in saltdic:
key = PBKDF2(SECRET, salt, ITERATIONS).read(KEYLENGTH)
saltdic[salt] = key
key = saltdic[salt]
ciphertext = base64.b64decode(parts[0])
iv = base64.b64decode(parts[1])
aes = AES.new(key, AES.MODE_GCM, iv)
decrypted = aes.decrypt(ciphertext)
data = rubymarshal.reader.loads(decrypted)
return data
ruby_encrypted_message = "" # "salt.base64message--base64salt--base64signature"
# we dont check for signature
print(decrypt_secret(ruby_encrypted_message)) # plaintext
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment