您现在的位置是:网站首页 > 加密与哈希文章详情

加密与哈希

加密与哈希的基本概念

加密和哈希是信息安全领域的两个核心概念,虽然它们都涉及数据转换,但目的和机制完全不同。加密是一种可逆过程,通过算法和密钥将明文转换为密文,只有持有正确密钥的人才能解密还原原始数据。哈希则是单向过程,将任意长度的输入通过哈希函数转换为固定长度的输出,理论上无法逆向推导原始输入。

// 加密示例
const crypto = require('crypto');
const algorithm = 'aes-256-cbc';
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);

function encrypt(text) {
  let cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
  let encrypted = cipher.update(text);
  encrypted = Buffer.concat([encrypted, cipher.final()]);
  return { iv: iv.toString('hex'), encryptedData: encrypted.toString('hex') };
}

// 哈希示例
function hash(text) {
  return crypto.createHash('sha256').update(text).digest('hex');
}

Node.js中的加密模块

Node.js内置的crypto模块提供了完整的加密功能支持。该模块包含对称加密、非对称加密、哈希、HMAC、数字签名等实现。使用时需要先通过require引入:

const crypto = require('crypto');

crypto模块支持多种算法:

  • 哈希算法:SHA-1、SHA-256、SHA-512等
  • 加密算法:AES、DES、RC4等
  • 非对称加密:RSA、DSA等

典型应用场景包括:

  1. 密码存储(使用哈希)
  2. 数据传输加密
  3. 数字签名验证
  4. 随机数生成

对称加密的实现

对称加密使用相同密钥进行加密和解密,AES是最常用的对称加密算法。Node.js中实现AES加密:

const crypto = require('crypto');

// AES-256-CBC加密
function aesEncrypt(text, key) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
  let encrypted = cipher.update(text);
  encrypted = Buffer.concat([encrypted, cipher.final()]);
  return iv.toString('hex') + ':' + encrypted.toString('hex');
}

// AES-256-CBC解密
function aesDecrypt(text, key) {
  const parts = text.split(':');
  const iv = Buffer.from(parts.shift(), 'hex');
  const encryptedText = Buffer.from(parts.join(':'), 'hex');
  const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
  let decrypted = decipher.update(encryptedText);
  decrypted = Buffer.concat([decrypted, decipher.final()]);
  return decrypted.toString();
}

// 使用示例
const key = 'my32lengthsupersecretkeynooneknows1';
const encrypted = aesEncrypt('Hello World', key);
console.log(encrypted); // 输出加密结果
console.log(aesDecrypt(encrypted, key)); // 输出解密后的原文

非对称加密的应用

非对称加密使用公钥和私钥对,RSA是典型代表。Node.js中生成RSA密钥对:

const { generateKeyPair } = require('crypto');

generateKeyPair('rsa', {
  modulusLength: 4096,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
    cipher: 'aes-256-cbc',
    passphrase: 'top secret'
  }
}, (err, publicKey, privateKey) => {
  if (err) throw err;
  console.log(publicKey);
  console.log(privateKey);
});

使用RSA加密解密:

const { publicEncrypt, privateDecrypt } = require('crypto');

const encryptedData = publicEncrypt(
  publicKey,
  Buffer.from('Secret message')
);

const decryptedData = privateDecrypt(
  {
    key: privateKey,
    passphrase: 'top secret'
  },
  encryptedData
);

console.log(decryptedData.toString());

哈希函数的深入解析

哈希函数将任意长度数据映射为固定长度值,具有以下特性:

  1. 确定性:相同输入总是产生相同输出
  2. 快速计算:容易计算哈希值
  3. 抗碰撞性:难以找到两个不同输入产生相同哈希
  4. 单向性:无法从哈希值反推原始输入

Node.js中常用哈希算法:

const crypto = require('crypto');

// SHA-256哈希
const hash = crypto.createHash('sha256');
hash.update('some data to hash');
console.log(hash.digest('hex'));

// 更安全的scrypt哈希
crypto.scrypt('password', 'salt', 64, (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));
});

密码哈希的最佳实践

存储用户密码时,直接使用普通哈希函数不够安全,应采用专门技术:

  1. 加盐(Salt):为每个密码生成随机盐值
  2. 迭代哈希:多次应用哈希函数增加计算成本
  3. 使用专门算法:如PBKDF2、bcrypt、scrypt

Node.js实现PBKDF2:

const crypto = require('crypto');

function hashPassword(password) {
  const salt = crypto.randomBytes(16).toString('hex');
  const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex');
  return { salt, hash };
}

function verifyPassword(password, salt, storedHash) {
  const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex');
  return hash === storedHash;
}

// 使用示例
const { salt, hash } = hashPassword('userPassword123');
console.log(verifyPassword('userPassword123', salt, hash)); // true
console.log(verifyPassword('wrongPassword', salt, hash)); // false

HMAC与数字签名

HMAC(哈希消息认证码)结合哈希函数和密钥,用于验证消息完整性和真实性:

const crypto = require('crypto');

// 创建HMAC
const hmac = crypto.createHmac('sha256', 'a secret key');
hmac.update('some data to hash');
console.log(hmac.digest('hex'));

// 数字签名
const { sign, verify } = require('crypto');
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
});

const signature = sign('sha256', Buffer.from('some data'), {
  key: privateKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
});

const isVerified = verify('sha256', Buffer.from('some data'), {
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
}, signature);

console.log('Signature verified:', isVerified);

加密与哈希的性能考量

不同算法对性能影响显著,选择时需权衡安全性和性能:

  1. 对称加密:AES-GCM比CBC模式更快更安全
  2. 哈希函数:SHA-3比SHA-2更安全但更慢
  3. 密码哈希:bcrypt和scrypt设计为计算密集型

性能测试示例:

const crypto = require('crypto');
const bench = require('benchmark');

const suite = new bench.Suite();

suite
.add('SHA-256', function() {
  crypto.createHash('sha256').update('test').digest('hex');
})
.add('SHA-512', function() {
  crypto.createHash('sha512').update('test').digest('hex');
})
.on('cycle', function(event) {
  console.log(String(event.target));
})
.run();

常见安全漏洞与防范

  1. 弱哈希:使用MD5、SHA1等已被破解的算法

    • 解决方案:使用SHA-256、SHA-3等强哈希
  2. 不安全的密钥管理:硬编码密钥或使用弱密钥

    • 解决方案:使用密钥管理系统,定期轮换密钥
  3. 加密误用:如ECB模式、不正确的IV使用

    • 解决方案:使用GCM等认证加密模式
  4. 时序攻击:通过响应时间推断敏感信息

    • 解决方案:使用恒定时间比较函数
// 安全的字符串比较
function safeCompare(a, b) {
  const aBuf = Buffer.from(a);
  const bBuf = Buffer.from(b);
  if (aBuf.length !== bBuf.length) return false;
  
  let result = 0;
  for (let i = 0; i < aBuf.length; i++) {
    result |= aBuf[i] ^ bBuf[i];
  }
  return result === 0;
}

实际应用案例分析

  1. JWT实现:结合哈希和签名
const crypto = require('crypto');

function base64UrlEncode(str) {
  return Buffer.from(str).toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
}

function createJWT(payload, secret) {
  const header = { alg: 'HS256', typ: 'JWT' };
  const encodedHeader = base64UrlEncode(JSON.stringify(header));
  const encodedPayload = base64UrlEncode(JSON.stringify(payload));
  
  const signature = crypto
    .createHmac('sha256', secret)
    .update(`${encodedHeader}.${encodedPayload}`)
    .digest('base64url');
    
  return `${encodedHeader}.${encodedPayload}.${signature}`;
}

const token = createJWT({ userId: 123 }, 'secret');
console.log(token);
  1. 文件完整性校验
const fs = require('fs');
const crypto = require('crypto');

function getFileHash(filePath, algorithm = 'sha256') {
  return new Promise((resolve, reject) => {
    const hash = crypto.createHash(algorithm);
    const stream = fs.createReadStream(filePath);
    
    stream.on('data', data => hash.update(data));
    stream.on('end', () => resolve(hash.digest('hex')));
    stream.on('error', reject);
  });
}

// 使用示例
getFileHash('package.json').then(hash => {
  console.log('File hash:', hash);
});

现代加密发展趋势

  1. 后量子密码学:抵抗量子计算机攻击的算法
  2. 同态加密:在加密数据上直接进行计算
  3. 零知识证明:验证信息真实性而不泄露信息本身
  4. 多方安全计算:多个参与方协同计算而不泄露各自输入

Node.js中实验性支持:

// 使用Web Crypto API(Node.js 15+)
const { webcrypto } = require('crypto');
const { subtle } = webcrypto;

async function generateKeys() {
  return await subtle.generateKey(
    {
      name: 'RSA-PSS',
      modulusLength: 2048,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: 'SHA-256'
    },
    true,
    ['sign', 'verify']
  );
}

generateKeys().then(keys => {
  console.log(keys);
});

上一篇: 会话管理

下一篇: CSRF防护

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步