はじめに
Railsでバックエンドタスクを実行するには、Sidekiq, Resque, Delayed Job, Action Jobなどが有名です。
私は、RailsアプリケーションをAWSで構築することがほとんどなので、バックエンドタスクはlambdaで処理させることが多いです。
今回は、Rails側で暗号化した文字列をlambda(python)で取得をして、復号する方法について書きます。
ケース
- Railsアプリケーション側で、文字列を暗号化して、データベースへ格納。
- CloudWatchのスケジューリングイベントでlambdaを定期実行。
- データベースから取り出した文字列を復号してSESでメール送信。
こんな感じです。
環境はrails5.0です。
Rails
文字列を暗号化するために、MessageEncryptorという便利なものがActiveSupportにはあります。今回これは使えません。(後で説明します)
今回は、自力で暗号化し、複合します。
Encryptable.rb
module Encryptable
SECRET = 'hogehogehogehogehogehogehogehoge'
IV = 'hogehogehogehoge'
CIP_NAME = 'aes-256-cbc'
def encrypt(value)
b64data = Base64::strict_encode64(value)
cip = OpenSSL::Cipher.new(CIP_NAME)
cip.encrypt
cip.key = SECRET
cip.iv = IV
encrypted = cip.update(b64data)
encrypted << cip.final
"#{Base64::strict_encode64(encrypted)}"
end
def decrypt(value)
data = Base64::strict_decode64(value)
cip = OpenSSL::Cipher.new(CIP_NAME)
cip.decrypt
cip.key = SECRET
cip.iv = IV
decrypted = cip.update(data)
decrypted << cip.final
"#{Base64::strict_decode64(decrypted)}".encode('UTF-8','UTF-8')
end
Lambda側
Decryptable.py
import base64
from Crypto.Cipher import AES
SECRET = 'hogehogehogehogehogehogehogehoge'
IV = 'hogehogehogehoge'
def decrypt(encrypted_value):
data = base64.b64decode(encrypted_value)
cip = AES.new(SECRET, AES.MODE_CBC, IV)
b64_decrypted_data = cip.decrypt(data)
decrypted_data = base64.b64decode(b64_decrypted_data)
return decrypted_data
MessageEncryptorが使えない。
MessageEncryptorのソースを見るとわかりますが、
シリアライズにMarshalが使われています。
このために、MessageEncryptorで暗号化した文字列には、型情報などがruby特有のマーシャリング方式で追加されるので、
Python側で復号できません。