Laravel Decrypter

July 30, 2022

One of Laravel's security features is Encryption. This feature creates a convenient interface for encrypting and decrypting via OpenSSL.

The documentation on the topic Encrypting A Value, explained that developers can use encryptString function from Crypt module likes:


namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;

class DigitalOceanTokenController extends Controller
     * Store a DigitalOcean API token for the user.
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
    public function storeSecret(Request $request)
            'token' => Crypt::encryptString($request->token),

All the ciphertext results are encrypted with AES-256-CBC chiper. And on some occasional event, there is a requirement to decrypt the value from non-technical people who do not code.

So, I try to create laravel_decrypt. A tool written in Rust and using egui for the user interface.


Egui is an easy-to-use immediate mode GUI which can be compiled and targetted into multiple platforms (Mac, Windows, Linux, and Web), example:

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("My egui Application");
            ui.horizontal(|ui| {
                ui.label("Your name: ");
            ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
            if ui.button("Click each year").clicked() {
                self.age += 1;
            ui.label(format!("Hello '{}', age {}",, self.age));


For doing encryption aes, base64, block-modes and serde_json creates are used.

Chipertext wrapped in base64 encoding, after decoding it will output JSON object with three keys: iv, value, and mac.

pub fn parse_ciphertext(ciphertext: &str) -> Result<LaravelEncryptedData, String> {
    let payload = match base64::decode(ciphertext) {
        Ok(v) => v,
        Err(_) => return Err("failed to decode base64".to_owned()),
    match serde_json::from_slice(&payload) {
        Ok(v) => Ok(v),
        Err(e) => Err(e.to_string()),

To convert it to plain text without authentication, we need key, ciphertext, and iv.

pub fn decrypt(key: Vec<u8>, ciphertext: Vec<u8>, iv: Vec<u8>) -> Result<String, String> {
    let cipher = match Aes256Cbc::new_from_slices(&key, &iv) {
        Ok(v) => v,
        Err(e) => return Err(e.to_string()),
    let data = match cipher.decrypt_vec(&ciphertext) {
        Ok(v) => v,
        Err(e) => return Err(e.to_string()),

For full source-code, you can visit

Return to blog