RC Encryption Overview
RC encryption encompasses variants like RC2, RC4, and RC5. RC2, designed by Ron Rivest, serves as a symmetric block cipher alternative to DES. It processes 64-bit input/output blocks with variable key lengths from 1 to 128 bytes, though implementations typically use 8-byte keys.
AES Symmetric Encryption Principles
AES operates as a symmetric algorithm where both frontend and backend must share identical keys for successful encryption/decryption. The standard key length is 16 bytes, with the Initialization Vector (IV) also requiring 16 bytes. For enhanced complexity with variable key lengths, consider RC algorithms.
Plaintext must be padded to 16-byte multiples before encryption. Base64 encoding automatically handles padding requiremants, preventing "Input length must be multiple of 16 when decrypting with padded cipher" errors.
Backend Java Implementation for ECB and CBC Modes
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AESUtility {
private static final String[] CIPHER_MODES = {"AES/ECB/PKCS5Padding", "AES/CBC/NoPadding"};
private static final String IV_STRING = "HBJNRU56MDk4NzK6";
private static final String ALGORITHM = "AES";
private static final String CHARSET = "UTF-8";
public static String encryptECB(String plaintext, String secretKey) {
validateKey(secretKey);
try {
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(CHARSET), ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER_MODES[0]);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(CHARSET));
return Base64.getEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
throw new RuntimeException("Encryption failed: " + e.getMessage());
}
}
public static String decryptECB(String ciphertext, String secretKey) {
validateKey(secretKey);
try {
byte[] decodedData = Base64.getDecoder().decode(ciphertext);
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(CHARSET), ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER_MODES[0]);
cipher.init(Cipher.DECRYPT_MODE, keySpec);
return new String(cipher.doFinal(decodedData), CHARSET);
} catch (Exception e) {
throw new RuntimeException("Decryption failed: " + e.getMessage());
}
}
public static String encryptCBC(String data, String keyValue) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_MODES[1]);
int blockSize = cipher.getBlockSize();
byte[] inputBytes = data.getBytes(CHARSET);
int paddedLength = inputBytes.length;
if (paddedLength % blockSize != 0) {
paddedLength += blockSize - (paddedLength % blockSize);
}
byte[] paddedData = new byte[paddedLength];
System.arraycopy(inputBytes, 0, paddedData, 0, inputBytes.length);
SecretKeySpec keySpec = new SecretKeySpec(keyValue.getBytes(CHARSET), ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(IV_STRING.getBytes(CHARSET));
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] result = cipher.doFinal(paddedData);
return Base64.getEncoder().encodeToString(result);
} catch (Exception e) {
throw new RuntimeException("CBC encryption error: " + e.getMessage());
}
}
public static String decryptCBC(String encryptedData, String keyValue) {
try {
byte[] decodedBytes = Base64.getDecoder().decode(encryptedData);
Cipher cipher = Cipher.getInstance(CIPHER_MODES[1]);
SecretKeySpec keySpec = new SecretKeySpec(keyValue.getBytes(CHARSET), ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(IV_STRING.getBytes(CHARSET));
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] original = cipher.doFinal(decodedBytes);
return new String(original, CHARSET);
} catch (Exception e) {
throw new RuntimeException("CBC decryption error: " + e.getMessage());
}
}
private static void validateKey(String key) {
if (StringUtils.isEmpty(key)) {
throw new IllegalArgumentException("Secret key cannot be empty");
}
}
}
Frontend Vue Implemantation with CBC Mode
Install crypto-js: npm install crypto-js
Configuration File (encryptionConfig.js)
export const SECRET_KEY = 'MTIzNDU2Nzg5MEFC'
export const INIT_VECTOR = 'QUJDRURGMDk4NzY1'
export const ENABLE_PARAM_ENCRYPTION = true
export const ENABLE_RESULT_ENCRYPTION = true
export const EXCLUDED_PATHS = [
'.*/orc/.*',
'.*/fastdfs/.*',
'.*/eempFastdfs/.*'
]
Encryption Utility (cryptoHandler.js)
import CryptoJS from 'crypto-js'
import { SECRET_KEY, INIT_VECTOR } from './encryptionConfig.js'
const encryptionKey = CryptoJS.enc.Utf8.parse(SECRET_KEY)
const initializationVector = CryptoJS.enc.Utf8.parse(INIT_VECTOR)
export default {
encryptData(input) {
let sourceData
if (typeof input === 'string') {
sourceData = CryptoJS.enc.Utf8.parse(input)
} else if (typeof input === 'object') {
sourceData = CryptoJS.enc.Utf8.parse(JSON.stringify(input))
}
const encrypted = CryptoJS.AES.encrypt(sourceData, encryptionKey, {
iv: initializationVector,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
})
return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
},
decryptData(encryptedText) {
if (!encryptedText) return ''
const base64Data = CryptoJS.enc.Base64.parse(encryptedText)
const base64String = CryptoJS.enc.Base64.stringify(base64Data)
const decrypted = CryptoJS.AES.decrypt(base64String, encryptionKey, {
iv: initializationVector,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
}