You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby与JavaScript带盐加解密:Rails5.0对接JS前端方案问询

Rails 5 + Backbone/Marionette: Salted Encryption/Decryption for Light Security

Hey there! Let's break down a practical, easy-to-implement solution for your salted encryption/decryption flow. Since you're targeting a light security use case, we'll stick to standard, battle-tested tools that play nicely with your Rails and Backbone/Marionette stack.

Symmetric encryption (AES) is perfect here because it lets you encrypt on the Rails backend and decrypt on the JS frontend with the same core secret. Adding salt via PBKDF2 ensures we avoid rainbow table attacks, which is ideal for your needs.

Step 1: Rails Backend Encryption (With Salt)

We'll use Ruby's built-in openssl library (no extra gems needed!) to handle encryption. We'll generate a random salt per encryption, derive a unique key from your master secret and the salt, then encrypt the data with AES-256-CBC.

# app/services/encryption_service.rb
class EncryptionService
  MASTER_KEY = ENV.fetch('ENCRYPTION_MASTER_KEY') # Store this in .env, never hardcode!

  def self.encrypt(data)
    # Generate a random 16-byte salt
    salt = SecureRandom.hex(16)
    # Derive a 256-bit encryption key using PBKDF2 (10k iterations for balance of speed/security)
    derived_key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(MASTER_KEY, salt, 10000, 32)
    
    # Initialize AES-CBC cipher
    cipher = OpenSSL::Cipher.new('AES-256-CBC')
    cipher.encrypt
    cipher.key = derived_key
    iv = cipher.random_iv # Generate random initialization vector (critical for security!)

    # Encrypt the data
    encrypted_data = cipher.update(data.to_s) + cipher.final

    # Bundle salt, IV, and encrypted data into a single string (we'll split this on the frontend)
    [salt, Base64.encode64(iv), Base64.encode64(encrypted_data)].join('|')
  end
end

# Usage example in your controller/model
encrypted_string = EncryptionService.encrypt('sensitive-light-data')

Step 2: Frontend Backbone/Marionette Decryption

For the JS side, we'll use crypto-js—a widely used library that supports AES and PBKDF2, and integrates seamlessly with Backbone/Marionette.

First, install the library:

npm install crypto-js --save

Then add this decryption utility to your frontend code:

// app/utils/decryption-utils.js
import CryptoJS from 'crypto-js';

export function decrypt(encryptedString, masterKey) {
  // Split the bundled string into salt, IV, and encrypted data
  const [saltHex, ivBase64, encryptedDataBase64] = encryptedString.split('|');
  
  // Convert salt from hex to CryptoJS WordArray
  const salt = CryptoJS.enc.Hex.parse(saltHex);
  // Derive the same key as Rails (match iteration count and key size!)
  const derivedKey = CryptoJS.PBKDF2(masterKey, salt, {
    keySize: 32,
    iterations: 10000,
    hasher: CryptoJS.algo.SHA1
  });
  
  // Parse IV and encrypted data from Base64
  const iv = CryptoJS.enc.Base64.parse(ivBase64);
  const encryptedData = CryptoJS.enc.Base64.parse(encryptedDataBase64);
  
  // Decrypt using AES-CBC (match padding mode with Rails—Pkcs7 is default for OpenSSL)
  const decryptedBytes = CryptoJS.AES.decrypt(
    { ciphertext: encryptedData },
    derivedKey,
    { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
  );
  
  // Convert decrypted bytes back to a UTF-8 string
  return decryptedBytes.toString(CryptoJS.enc.Utf8);
}

// Usage example in a Marionette view/Backbone model
import { decrypt } from '../utils/decryption-utils';

const masterKey = 'your-master-key-from-backend'; // Get this securely (e.g., post-login)
const originalData = decrypt(encryptedStringFromRails, masterKey);

Critical Security Notes for Light Scenarios

  • Never hardcode your master key: Store it in Rails environment variables (use dotenv or Figaro). For the frontend, fetch it securely after user authentication (e.g., include it in a JWT token or a protected API response—always use HTTPS!).
  • Randomize salt and IV: We do this by default in the code above—never reuse the same salt/IV for multiple encryptions, as it weakens security.
  • Stick to HTTPS: All data (encrypted or not) should be transmitted over HTTPS to prevent man-in-the-middle attacks.
  • Keep it simple: Since this is a light security use case, avoid overcomplicating with exotic algorithms—AES-CBC is more than sufficient.

Alternate Option: Attr_Encrypted Gem (Model-Level Encryption)

If you're primarily encrypting model fields in Rails and need to pass the encrypted data to the frontend, you can use the attr_encrypted gem. It abstracts a lot of the encryption logic, but you'll still need crypto-js on the frontend to decrypt. Just make sure to configure the gem to use PBKDF2 with salt, then mirror the key derivation logic in JS as we did above.


内容的提问来源于stack exchange,提问作者Jonathan Clark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:53:34