前后端通信安全实践:AES与RSA加密解密详解及签名机制应用(PHP/JavaScript)

13
发布时间:2025-02-22 14:58:36

前后端通信安全概述

在前后端通信中,安全性是一个重要的考虑因素。前端代码是公开的,用户可以通过调试工具查看甚至修改代码,因此无法保证绝对的安全性。开发者能做的仅仅是增加攻击者的破解成本。

安全隐患

  1. 明文硬编码漏洞:如果将密钥(key)、盐值(salt)等敏感信息直接写入代码中,这些信息很容易被审查代码的人发现。
  2. 调用漏洞:即使加密逻辑被混淆,其他模块的代码可能是明文的,攻击者可以直接调用未加密的函数绕过加密逻辑。
  3. 硬破解:无论开发者如何加密或混淆代码,攻击者都可以通过耐心分析控制台日志还原执行逻辑。
  4. 通信获取:如果密钥或配置通过接口传递,这个过程本身也可能被拦截。

安全建议

  • 混淆所有代码(HTML、JavaScript等),可以使用在线工具或NPM插件。
  • 避免硬编码密钥和盐值,推荐动态生成或从安全渠道获取。
  • 定期更换密钥和盐值,使用随机且较长的字符串。
  • 在不影响业务的前提下,及时作废旧的数据验证策略。

AES 加密与解密

AES(Advanced Encryption Standard)是一种对称加密算法,广泛用于数据加密和保护。它有两个重要参数:keyiv

参数说明

  • Key:加密的核心,确保只有持有相同密钥的人才能解密数据。推荐随机生成一个32字节的字符串。
  • IV(Initialization Vector):初始化向量,用于初始化加密算法的状态,确保相同的明文在不同加密过程中产生不同的密文。

PHP 加密,JavaScript 解密

PHP 实现 AES-256-CBC 加密

function aesEncrypt($str, $key, $iv) {
    return base64_encode(openssl_encrypt($str, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv));
}

$str = '{"code":0,"msg":"success","data":{"lists":{"k1":"v1","k2":"v2"}}}';
$key = 'abcdabcdabcdabcdabcdabcdabcdabcd'; // 32字节密钥
$iv = 'abcdabcdabcdabcd'; // 16字节IV
echo aesEncrypt($str, $key, $iv);

JavaScript 实现 AES-256-CBC 解密

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
function decrypt(str, key, iv) {
    return CryptoJS.AES.decrypt(str, CryptoJS.enc.Utf8.parse(key), { 
        iv: CryptoJS.enc.Utf8.parse(iv), 
        padding: CryptoJS.pad.Pkcs7 
    }).toString(CryptoJS.enc.Utf8);
}
console.log(decrypt('naQ3ZnyGetarkvugVeNaroUe9Hrk+KW3sKXSs42QJ6tPER1zcxvS8E2xsCJG0UaJ5WMFhFgLjD6z3wbqPLFgRFIl+BaGqINmdPbm9B+DXMs=', 
    'abcdabcdabcdabcdabcdabcdabcdabcd', 
    'abcdabcdabcdabcd'));
</script>

JavaScript 加密,PHP 解密

JavaScript 实现 AES-256-CBC 加密

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
function encrypt(str, key, iv) {
    return CryptoJS.AES.encrypt(str, CryptoJS.enc.Utf8.parse(key), { 
        iv: CryptoJS.enc.Utf8.parse(iv), 
        mode: CryptoJS.mode.CBC, 
        padding: CryptoJS.pad.Pkcs7 
    }).toString();
}
console.log(encrypt('{"name":"张三", "age": 20}', 'abcdabcdabcdabcdabcdabcdabcdabcd', 'abcdabcdabcdabcd'));
</script>

PHP 实现 AES-256-CBC 解密

function aesDecrypt($str, $key, $iv) {
    return openssl_decrypt(base64_decode($str), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
}

$str = 'aZlC1imJbcUQblRR0QsMPGF+8Kbja/1fU+tdcTyAUVw=';
$key = 'abcdabcdabcdabcdabcdabcdabcdabcd'; // 32字节密钥
$iv = 'abcdabcdabcdabcd'; // 16字节IV
echo aesDecrypt($str, $key, $iv);

RSA 加密与解密

RSA 是一种非对称加密算法,适合小数据量的加密场景。由于其计算复杂度较高,不适用于大文件或大数据量的加密。

RSA 的局限性

  1. 长度限制:对于2048位的RSA密钥,最大可加密的数据长度为245字节(2048位 / 8 - 11)。对于4096位的RSA密钥,最大可加密的数据长度为511字节。
  2. 性能问题:随着密钥长度的增加,加密和解密的速度会显著降低。

PHP 公钥加密,JavaScript 私钥解密

PHP 实现 RSA 加密

function encryptRsa($str, $pub_key) {
    $encrypt_str = '';
    if (!openssl_public_encrypt($str, $encrypt_str, $pub_key)) {
        return '';
    }
    return base64_encode($encrypt_str);
}

echo encryptRsa(
    json_encode(['code' => 0, 'msg' => 'success', 'data' => ['lists' => [1, 2, 3]]]),
    file_get_contents('public.key')
);

JavaScript 实现 RSA 解密

<script src="https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/3.3.2/jsencrypt.min.js"></script>
<script>
function decryptRsa(str, private_key) {
    var encrypt = new JSEncrypt();
    encrypt.setPrivateKey(private_key);
    return encrypt.decrypt(str);
}
console.log(decryptRsa('接口返回的base64编码过的字符串', '私钥字符串'));
</script>

JavaScript 公钥加密,PHP 私钥解密

JavaScript 实现 RSA 加密

<script src="https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/3.3.2/jsencrypt.min.js"></script>
<script>
function encryptRsa(data, public_key) {
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey(public_key);
    return encrypt.encrypt(data);
}
console.log(encryptRsa('要加密的字符串', '公钥字符串'));
</script>

PHP 实现 RSA 解密

function decryptRsa($str, $private_key) {
    openssl_private_decrypt(base64_decode($str), $res, $private_key);
    return $res;
}

echo decryptRsa(
    '被解密的base64字符串',
    file_get_contents('private.key')
);

数据签名与完整性检查

为了防止数据在传输过程中被篡改,可以使用签名机制。

签名流程

  1. 生成签名:在服务端对数据进行哈希运算,并附加一个自定义的“盐”值。
  2. 验签:接收方重新计算签名并与原始签名对比。

示例代码

$hacker_data = 'b.af997aac21a6eeaa354fa4d46eed2c58';
list($init_data, $sign) = explode('.', $hacker_data);

// 验签
if (md5($init_data . '自定义的盐') !== $sign) {
    return '验签不通过,拦截掉本次请求';
}

常见术语解释

  1. 信息摘要:通过特定算法对数据进行处理,生成固定长度的字符串,用于验证数据完整性。
  2. 哈希算法:将任意长度的数据映射为固定长度值的算法,如MD5、SHA-1、SHA-256等。
  3. 哈希碰撞:两个不同的输入经过哈希函数后得到相同的输出,概率极低但并非不可能。
  4. 彩虹表:预计算的哈希值表,用于快速查找明文密码。
  5. 加盐:在密码或数据中添加随机字符串,增加破解难度。

本文被 PHP编程 专题收录