JS常见加解密算法

内容分享4小时前发布
0 0 0

AES:

  1. 现代最安全的对称加密算法,
  2. 速度快适合:大量数据加密(文件、长文本)、本地存储加密
  3. 注意:密钥管理至关重大,提议定期更换
import React, { useState } from 'react';
import CryptoJS from 'crypto-js';

/**
 * AES加密解密通用组件
 * 支持CBC模式,128/192/256位密钥
 */
const AESCrypto = ({ defaultKey, defaultIv }) => {
  const [data, setData] = useState('');
  const [key, setKey] = useState(defaultKey || '1234567890abcdef'); // 默认16位密钥
  const [iv, setIv] = useState(defaultIv || 'abcdef1234567890');   // 默认16位初始向量
  const [encryptedData, setEncryptedData] = useState('');
  const [decryptedData, setDecryptedData] = useState('');

  // 验证密钥长度
  const validateKey = () => {
    if ([16, 24, 32].indexOf(key.length) === -1) {
      alert('密钥长度必须为16位(128位)、24位(192位)或32位(256位)');
      return false;
    }
    if (iv.length !== 16) {
      alert('初始向量必须为16位');
      return false;
    }
    return true;
  };

  // 加密
  const handleEncrypt = () => {
    if (!data) return alert('请输入要加密的数据');
    if (!validateKey()) return;

    try {
      const keyHex = CryptoJS.enc.Utf8.parse(key);
      const ivHex = CryptoJS.enc.Utf8.parse(iv);
      
      const encrypted = CryptoJS.AES.encrypt(data, keyHex, {
        iv: ivHex,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      });
      
      setEncryptedData(encrypted.ciphertext.toString());
    } catch (error) {
      alert('加密失败: ' + error.message);
    }
  };

  // 解密
  const handleDecrypt = () => {
    if (!encryptedData) return alert('请先加密获取密文');
    if (!validateKey()) return;

    try {
      const keyHex = CryptoJS.enc.Utf8.parse(key);
      const ivHex = CryptoJS.enc.Utf8.parse(iv);
      const encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedData);
      const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
      
      const decrypt = CryptoJS.AES.decrypt(srcs, keyHex, {
        iv: ivHex,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      });
      
      setDecryptedData(decrypt.toString(CryptoJS.enc.Utf8));
    } catch (error) {
      alert('解密失败: ' + error.message);
    }
  };

  return (
    <div className="crypto-component">
      <h3>AES加密解密</h3>
      <div className="input-group">
        <label>原始数据:</label>
        <textarea 
          value={data} 
          onChange={(e) => setData(e.target.value)}
          placeholder="请输入要加密的数据"
        />
      </div>
      
      <div className="input-group">
        <label>密钥 ({[16,24,32]}位):</label>
        <input 
          type="text" 
          value={key} 
          onChange={(e) => setKey(e.target.value)}
          maxLength="32"
        />
      </div>
      
      <div className="input-group">
        <label>初始向量 (16位):</label>
        <input 
          type="text" 
          value={iv} 
          onChange={(e) => setIv(e.target.value)}
          maxLength="16"
        />
      </div>
      
      <div className="button-group">
        <button onClick={handleEncrypt}>加密</button>
        <button onClick={handleDecrypt}>解密</button>
      </div>
      
      <div className="result-group">
        <label>加密结果:</label>
        <textarea value={encryptedData} readOnly />
      </div>
      
      <div className="result-group">
        <label>解密结果:</label>
        <textarea value={decryptedData} readOnly />
      </div>

      <style jsx>{`
        .crypto-component {
          border: 1px solid #e0e0e0;
          border-radius: 8px;
          padding: 16px;
          margin: 16px 0;
        }
        .input-group, .result-group {
          margin-bottom: 12px;
        }
        label {
          display: block;
          margin-bottom: 4px;
          font-weight: 500;
        }
        input, textarea {
          width: 100%;
          padding: 8px;
          border: 1px solid #ddd;
          border-radius: 4px;
        }
        textarea {
          min-height: 80px;
          resize: vertical;
        }
        .button-group {
          display: flex;
          gap: 8px;
          margin: 16px 0;
        }
        button {
          padding: 8px 16px;
          border: none;
          border-radius: 4px;
          cursor: pointer;
          background: #007bff;
          color: white;
        }
        button:hover {
          background: #0056b3;
        }
      `}</style>
    </div>
  );
};

export default AESCrypto;

JS常见加解密算法

DES:

  1. 老牌对称加密算法,安全性较低(56 位密钥)
  2. 适合:老旧系统兼容场景,新系统不推荐使用
  3. 3DES 是其增强版,但效率不如 AES
<!DOCTYPE html>
<html>
<head>
    <title>DES加密解密案例</title>
    <script src="https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.min.js"></script>
</head>
<body>
    <script>
        // DES加密算法 (ECB模式)
        const desKey = CryptoJS.enc.Utf8.parse("deskey"); // 8位密钥

        // 加密函数
        function desEncrypt(plaintext) {
            const srcs = CryptoJS.enc.Utf8.parse(plaintext);
            const encrypted = CryptoJS.DES.encrypt(srcs, desKey, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
            return encrypted.toString();
        }

        // 解密函数
        function desDecrypt(ciphertext) {
            const decrypt = CryptoJS.DES.decrypt(ciphertext, desKey, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
            return CryptoJS.enc.Utf8.stringify(decrypt).toString();
        }

        // 测试
        const original = "这是DES加密测试数据";
        const encrypted = desEncrypt(original);
        const decrypted = desDecrypt(encrypted);

        console.log("DES测试:");
        console.log("原始数据:", original);
        console.log("加密后:", encrypted);
        console.log("解密后:", decrypted);
    </script>
</body>
</html>

JS常见加解密算法

RSA:

  1. 非对称加密,公钥加密私钥解密
  2. 适合:小数据加密(如 AES 密钥传输)、数字签名、身份认证
  3. 注意:加密内容不宜过长(受密钥长度限制)
<!DOCTYPE html>
<html>
<head>
    <title>DES加密解密案例</title>
    <script src="https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.min.js"></script>
</head>
<body>
    <script>
        // DES加密算法 (ECB模式)
        const desKey = CryptoJS.enc.Utf8.parse("deskey"); // 8位密钥

        // 加密函数
        function desEncrypt(plaintext) {
            const srcs = CryptoJS.enc.Utf8.parse(plaintext);
            const encrypted = CryptoJS.DES.encrypt(srcs, desKey, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
            return encrypted.toString();
        }

        // 解密函数
        function desDecrypt(ciphertext) {
            const decrypt = CryptoJS.DES.decrypt(ciphertext, desKey, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
            return CryptoJS.enc.Utf8.stringify(decrypt).toString();
        }

        // 测试
        const original = "这是DES加密测试数据";
        const encrypted = desEncrypt(original);
        const decrypted = desDecrypt(encrypted);

        console.log("DES测试:");
        console.log("原始数据:", original);
        console.log("加密后:", encrypted);
        console.log("解密后:", decrypted);
    </script>
</body>
</html>

JS常见加解密算法

哈希算法:

  1. MD5:安全性低,用于非敏感数据校验
  2. SHA-256:目前推荐的安全哈希,适合密码存储(需加盐)
  3. HMAC:带密钥的哈希,适合接口签名、防止数据篡改
<!DOCTYPE html>
<html>
<head>
    <title>RSA加密解密案例</title>
    <script src="https://cdn.jsdelivr.net/npm/jsencrypt@3.3.1/bin/jsencrypt.min.js"></script>
</head>
<body>
    <script>
        // RSA非对称加密
        const encryptor = new JSEncrypt();
        
        // 生成密钥对(实际应用中一般由服务器生成私钥,分发公钥)
        const keyPair = encryptor.getKey();
        const publicKey = keyPair.getPublicKey();  // 公钥
        const privateKey = keyPair.getPrivateKey();// 私钥

        // 加密函数(使用公钥)
        function rsaEncrypt(plaintext) {
            encryptor.setPublicKey(publicKey);
            return encryptor.encrypt(plaintext);
        }

        // 解密函数(使用私钥)
        function rsaDecrypt(ciphertext) {
            encryptor.setPrivateKey(privateKey);
            return encryptor.decrypt(ciphertext);
        }

        // 测试
        const original = "这是RSA加密测试数据(适合短文本)";
        const encrypted = rsaEncrypt(original);
        const decrypted = rsaDecrypt(encrypted);

        console.log("RSA测试:");
        console.log("原始数据:", original);
        console.log("加密后:", encrypted);
        console.log("解密后:", decrypted);
        console.log("公钥:", publicKey);
        console.log("私钥:", privateKey);
    </script>
</body>
</html>
    

JS常见加解密算法

react通用方法

方法

import CryptoJS from 'crypto-js';
import JSEncrypt from 'jsencrypt';

/**
 * AES加密解密工具
 * 密钥和向量必须为16位
 */
export const AESUtils = {
  /**
   * AES加密
   * @param {string} data - 待加密数据
   * @param {string} key - 16位密钥
   * @param {string} iv - 16位初始向量
   * @returns {string} 加密结果
   */
  encrypt: (data, key, iv) => {
    if (!data || !key || !iv) {
      throw new Error('AES加密:数据、密钥和初始向量不能为空');
    }
    if (key.length !== 16 || iv.length !== 16) {
      throw new Error('AES加密:密钥和初始向量必须为16位');
    }
    
    const keyHex = CryptoJS.enc.Utf8.parse(key);
    const ivHex = CryptoJS.enc.Utf8.parse(iv);
    
    const encrypted = CryptoJS.AES.encrypt(data, keyHex, {
      iv: ivHex,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    
    return encrypted.ciphertext.toString();
  },
  
  /**
   * AES解密
   * @param {string} encryptedData - 加密数据
   * @param {string} key - 16位密钥
   * @param {string} iv - 16位初始向量
   * @returns {string} 解密结果
   */
  decrypt: (encryptedData, key, iv) => {
    if (!encryptedData || !key || !iv) {
      throw new Error('AES解密:数据、密钥和初始向量不能为空');
    }
    if (key.length !== 16 || iv.length !== 16) {
      throw new Error('AES解密:密钥和初始向量必须为16位');
    }
    
    const keyHex = CryptoJS.enc.Utf8.parse(key);
    const ivHex = CryptoJS.enc.Utf8.parse(iv);
    const encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedData);
    const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    
    const decrypt = CryptoJS.AES.decrypt(srcs, keyHex, {
      iv: ivHex,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    
    return decrypt.toString(CryptoJS.enc.Utf8);
  }
};

/**
 * RSA加密解密工具
 */
export const RSAUtils = {
  /**
   * 生成RSA密钥对
   * @param {number} keySize - 密钥长度,默认2048
   * @returns {object} { publicKey, privateKey }
   */
  generateKeyPair: (keySize = 2048) => {
    const encryptor = new JSEncrypt({ default_key_size: keySize });
    return {
      publicKey: encryptor.getPublicKey(),
      privateKey: encryptor.getPrivateKey()
    };
  },
  
  /**
   * RSA加密
   * @param {string} data - 待加密数据
   * @param {string} publicKey - 公钥
   * @returns {string|null} 加密结果
   */
  encrypt: (data, publicKey) => {
    if (!data || !publicKey) {
      throw new Error('RSA加密:数据和公钥不能为空');
    }
    
    const encryptor = new JSEncrypt();
    encryptor.setPublicKey(publicKey);
    return encryptor.encrypt(data);
  },
  
  /**
   * RSA解密
   * @param {string} encryptedData - 加密数据
   * @param {string} privateKey - 私钥
   * @returns {string|null} 解密结果
   */
  decrypt: (encryptedData, privateKey) => {
    if (!encryptedData || !privateKey) {
      throw new Error('RSA解密:数据和私钥不能为空');
    }
    
    const encryptor = new JSEncrypt();
    encryptor.setPrivateKey(privateKey);
    return encryptor.decrypt(encryptedData);
  }
};

/**
 * 哈希算法工具
 */
export const HashUtils = {
  /**
   * MD5哈希
   * @param {string} data - 待哈希数据
   * @returns {string} 哈希结果
   */
  md5: (data) => {
    if (!data) return '';
    return CryptoJS.MD5(data).toString();
  },
  
  /**
   * SHA-1哈希
   * @param {string} data - 待哈希数据
   * @returns {string} 哈希结果
   */
  sha1: (data) => {
    if (!data) return '';
    return CryptoJS.SHA1(data).toString();
  },
  
  /**
   * SHA-256哈希
   * @param {string} data - 待哈希数据
   * @returns {string} 哈希结果
   */
  sha256: (data) => {
    if (!data) return '';
    return CryptoJS.SHA256(data).toString();
  },
  
  /**
   * SHA-512哈希
   * @param {string} data - 待哈希数据
   * @returns {string} 哈希结果
   */
  sha512: (data) => {
    if (!data) return '';
    return CryptoJS.SHA512(data).toString();
  },
  
  /**
   * HMAC-SHA256哈希
   * @param {string} data - 待哈希数据
   * @param {string} key - 密钥
   * @returns {string} 哈希结果
   */
  hmacSha256: (data, key) => {
    if (!data || !key) return '';
    return CryptoJS.HmacSHA256(data, key).toString();
  },
  
  /**
   * 带盐值的SHA-256哈希(适合密码存储)
   * @param {string} data - 待哈希数据
   * @param {string} salt - 盐值
   * @returns {string} 哈希结果
   */
  saltedSha256: (data, salt) => {
    if (!data || !salt) return '';
    // 盐值+数据的组合进行哈希
    return CryptoJS.SHA256(salt + data).toString();
  }
};

/**
 * 工具类:生成随机字符串(用于盐值、密钥等)
 * @param {number} length - 长度
 * @returns {string} 随机字符串
 */
export const RandomUtils = {
  generateRandomString: (length) => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  },
  
  // 生成16位随机密钥(适合AES)
  generateAesKey: () => {
    return RandomUtils.generateRandomString(16);
  }
};

JS常见加解密算法

使用

import React, { useState, useEffect } from 'react';
import { AESUtils, RSAUtils, HashUtils, RandomUtils } from './cryptoUtils';

const CryptoExample = () => {
  // 状态管理
  const [aesData, setAesData] = useState('测试AES加密');
  const [aesKey, setAesKey] = useState('');
  const [aesIv, setAesIv] = useState('');
  const [aesEncrypted, setAesEncrypted] = useState('');
  const [aesDecrypted, setAesDecrypted] = useState('');
  
  const [rsaData, setRsaData] = useState('测试RSA加密');
  const [rsaPublicKey, setRsaPublicKey] = useState('');
  const [rsaPrivateKey, setRsaPrivateKey] = useState('');
  const [rsaEncrypted, setRsaEncrypted] = useState('');
  const [rsaDecrypted, setRsaDecrypted] = useState('');
  
  const [hashData, setHashData] = useState('测试哈希算法');
  const [hashSalt, setHashSalt] = useState('');
  const [hashResults, setHashResults] = useState({
    md5: '',
    sha1: '',
    sha256: '',
    sha512: '',
    hmac: ''
  });
  
  // 初始化:生成随机密钥和盐值
  useEffect(() => {
    // 生成AES密钥和向量
    setAesKey(RandomUtils.generateAesKey());
    setAesIv(RandomUtils.generateAesKey());
    
    // 生成RSA密钥对
    const rsaKeys = RSAUtils.generateKeyPair();
    setRsaPublicKey(rsaKeys.publicKey);
    setRsaPrivateKey(rsaKeys.privateKey);
    
    // 生成随机盐值
    setHashSalt(RandomUtils.generateRandomString(16));
  }, []);
  
  // AES加密解密操作
  const handleAesEncrypt = () => {
    try {
      const result = AESUtils.encrypt(aesData, aesKey, aesIv);
      setAesEncrypted(result);
    } catch (error) {
      alert('AES加密失败: ' + error.message);
    }
  };
  
  const handleAesDecrypt = () => {
    try {
      const result = AESUtils.decrypt(aesEncrypted, aesKey, aesIv);
      setAesDecrypted(result);
    } catch (error) {
      alert('AES解密失败: ' + error.message);
    }
  };
  
  // RSA加密解密操作
  const handleRsaEncrypt = () => {
    try {
      const result = RSAUtils.encrypt(rsaData, rsaPublicKey);
      setRsaEncrypted(result || '加密失败,数据可能过长');
    } catch (error) {
      alert('RSA加密失败: ' + error.message);
    }
  };
  
  const handleRsaDecrypt = () => {
    try {
      const result = RSAUtils.decrypt(rsaEncrypted, rsaPrivateKey);
      setRsaDecrypted(result || '解密失败,密钥不匹配');
    } catch (error) {
      alert('RSA解密失败: ' + error.message);
    }
  };
  
  // 哈希算法操作
  const handleCalculateHashes = () => {
    setHashResults({
      md5: HashUtils.md5(hashData),
      sha1: HashUtils.sha1(hashData),
      sha256: HashUtils.sha256(hashData),
      sha512: HashUtils.sha512(hashData),
      hmac: HashUtils.hmacSha256(hashData, 'my-hmac-key'),
      saltedSha256: HashUtils.saltedSha256(hashData, hashSalt)
    });
  };
  
  return (
    <div className="crypto-example">
      <h2>React加解密工具方法示例</h2>
      
      {/* AES部分 */}
      <div className="section">
        <h3>AES加密解密</h3>
        <div className="input-group">
          <label>数据:</label>
          <input
            type="text"
            value={aesData}
            onChange={(e) => setAesData(e.target.value)}
          />
        </div>
        <div className="input-group">
          <label>16位密钥:</label>
          <input
            type="text"
            value={aesKey}
            onChange={(e) => setAesKey(e.target.value)}
            maxLength="16"
          />
        </div>
        <div className="input-group">
          <label>16位向量:</label>
          <input
            type="text"
            value={aesIv}
            onChange={(e) => setAesIv(e.target.value)}
            maxLength="16"
          />
        </div>
        <div className="button-group">
          <button onClick={handleAesEncrypt}>加密</button>
          <button onClick={handleAesDecrypt}>解密</button>
        </div>
        <div className="result-group">
          <label>加密结果:</label>
          <textarea value={aesEncrypted} readOnly />
        </div>
        <div className="result-group">
          <label>解密结果:</label>
          <textarea value={aesDecrypted} readOnly />
        </div>
      </div>
      
      {/* RSA部分 */}
      <div className="section">
        <h3>RSA加密解密</h3>
        <div className="input-group">
          <label>数据 (不宜过长):</label>
          <input
            type="text"
            value={rsaData}
            onChange={(e) => setRsaData(e.target.value)}
          />
        </div>
        <div className="result-group">
          <label>公钥:</label>
          <textarea value={rsaPublicKey} readOnly rows="4" />
        </div>
        <div className="result-group">
          <label>私钥:</label>
          <textarea value={rsaPrivateKey} readOnly rows="6" />
        </div>
        <div className="button-group">
          <button onClick={handleRsaEncrypt}>加密</button>
          <button onClick={handleRsaDecrypt}>解密</button>
        </div>
        <div className="result-group">
          <label>加密结果:</label>
          <textarea value={rsaEncrypted} readOnly />
        </div>
        <div className="result-group">
          <label>解密结果:</label>
          <textarea value={rsaDecrypted} readOnly />
        </div>
      </div>
      
      {/* 哈希算法部分 */}
      <div className="section">
        <h3>哈希算法</h3>
        <div className="input-group">
          <label>数据:</label>
          <input
            type="text"
            value={hashData}
            onChange={(e) => setHashData(e.target.value)}
          />
        </div>
        <div className="input-group">
          <label>盐值 (用于salted SHA-256):</label>
          <input
            type="text"
            value={hashSalt}
            onChange={(e) => setHashSalt(e.target.value)}
          />
        </div>
        <div className="button-group">
          <button onClick={handleCalculateHashes}>计算哈希值</button>
        </div>
        <div className="hash-results">
          <div className="hash-item">
            <label>MD5:</label>
            <div className="hash-value">{hashResults.md5}</div>
          </div>
          <div className="hash-item">
            <label>SHA-1:</label>
            <div className="hash-value">{hashResults.sha1}</div>
          </div>
          <div className="hash-item">
            <label>SHA-256:</label>
            <div className="hash-value">{hashResults.sha256}</div>
          </div>
          <div className="hash-item">
            <label>SHA-512:</label>
            <div className="hash-value">{hashResults.sha512}</div>
          </div>
          <div className="hash-item">
            <label>HMAC-SHA256:</label>
            <div className="hash-value">{hashResults.hmac}</div>
          </div>
          <div className="hash-item">
            <label>Salted SHA-256:</label>
            <div className="hash-value">{hashResults.saltedSha256}</div>
          </div>
        </div>
      </div>
      
      <style jsx>{`
        .crypto-example {
          max-width: 800px;
          margin: 0 auto;
          padding: 20px;
        }
        .section {
          margin-bottom: 30px;
          padding: 20px;
          border: 1px solid #e0e0e0;
          border-radius: 8px;
        }
        .input-group {
          margin-bottom: 15px;
        }
        label {
          display: block;
          margin-bottom: 5px;
          font-weight: bold;
        }
        input, textarea {
          width: 100%;
          padding: 8px;
          border: 1px solid #ddd;
          border-radius: 4px;
        }
        textarea {
          min-height: 60px;
          resize: vertical;
        }
        .button-group {
          margin: 15px 0;
          display: flex;
          gap: 10px;
        }
        button {
          padding: 8px 16px;
          background-color: #007bff;
          color: white;
          border: none;
          border-radius: 4px;
          cursor: pointer;
        }
        button:hover {
          background-color: #0056b3;
        }
        .result-group {
          margin-bottom: 15px;
        }
        .hash-results {
          display: grid;
          grid-template-columns: 1fr 1fr;
          gap: 10px;
        }
        .hash-item {
          margin-bottom: 10px;
        }
        .hash-value {
          word-break: break-all;
          font-family: monospace;
          font-size: 0.9em;
          padding: 5px;
          background-color: #f5f5f5;
          border-radius: 4px;
        }
      `}</style>
    </div>
  );
};

export default CryptoExample;

JS常见加解密算法

工具方法特点与使用说明

1.设计特点

  • 模块化封装:每种算法独立成一个工具对象,职责清晰
  • 参数验证:内置必要的参数检查,抛出明确的错误信息
  • 通用性强:不依赖 React 组件生命周期,可在任何地方调用
  • 安全辅助:提供随机密钥生成工具,便于创建安全的密钥和盐值

2.使用步骤

  • 安装依赖:npm install crypto-js jsencrypt
  • 导入所需工具:import { AESUtils, RSAUtils } from './cryptoUtils'
  • 直接调用方法:const encrypted = AESUtils.encrypt(data, key, iv)

3.在项目中的应用提议

  1. 密钥管理:生产环境中密钥应从后端获取,避免硬编码
  2. 错误处理:调用时使用 try/catch 捕获可能的异常
  3. 性能考量:RSA 加密解密性能较低,适合小数据加密
  4. 安全实践:

密码存储必须使用带随机盐值的哈希算法

敏感数据传输应结合 HTTPS 使用

前端只保留公钥,私钥解密操作尽量在后端进行

© 版权声明

相关文章

暂无评论

none
暂无评论...