HomeAboutLinkArchivehi灯泡

Node Crypto

Node

Console

使用 chalk 库(推荐)

Crypto 加密

模块导入和特性检查
const crypto = require('crypto');.

// 1. 检查支持的特性
console.log('支持的哈希算法:', crypto.getHashes());
console.log('支持的加密算法:', crypto.getCiphers());
console.log('支持的曲线:', crypto.getCurves());
console.log('支持的Diffie-Hellman组:', crypto.getDiffieHellman('modp14'));

// 2. 随机字节生成
const randomBytes = crypto.randomBytes(32); // 32字节 = 256位
console.log('随机字节 (hex):', randomBytes.toString('hex'));
console.log('随机字节 (base64):', randomBytes.toString('base64'));

// 3. 伪随机字节(性能更好,但安全性较低)
const pseudoRandomBytes = crypto.pseudoRandomBytes(32);
哈希算法(Hash)
// 1. MD5(不推荐用于安全用途)
const md5 = crypto.createHash('md5');
md5.update('Hello World');
console.log('MD5:', md5.digest('hex')); // b10a8db164e0754105b7a99be72e3fe5

// 2. SHA-256(推荐)
const sha256 = crypto.createHash('sha256');
sha256.update('Hello World');
console.log('SHA-256:', sha256.digest('hex'));

// 3. 流式处理大文件
function hashFile(filePath, algorithm = 'sha256') {
  return new Promise((resolve, reject) => {
    const hash = crypto.createHash(algorithm);
    const fs = require('fs');
    const stream = fs.createReadStream(filePath);
    
    stream.on('data', (chunk) => hash.update(chunk));
    stream.on('end', () => resolve(hash.digest('hex')));
    stream.on('error', reject);
  });
}

// 4. 同时计算多个哈希
function multiHash(data) {
  const algorithms = ['md5', 'sha1', 'sha256', 'sha512'];
  const results = {};
  
  for (const algo of algorithms) {
    const hash = crypto.createHash(algo);
    hash.update(data);
    results[algo] = hash.digest('hex');
  }
  
  return results;
}

HMAC(密钥哈希)
加密和解密

对称加密(AES).

加密模式和填充.

非对称加密(RSA)

密钥生成和加密.

性能优化:混合加密.

密码学安全函数

密码哈希(bcrypt替代).

时序安全比较

什么是时序攻击?

想象一下:有个保险箱的密码是 6位数字。你偷看别人开保险箱,发现:

如果第一个数字就错了,他立即就发现打不开.

如果第二个数字才错,他稍微慢一点发现打不开.

如果前五个数字都对,最后一个错了,他最慢才发现打不开.

这样,你通过观察时间长短,就能慢慢猜出正确密码!

这就是时序攻击(Timing Attack).

攻击者通过测量程序运行的时间差异,来推测敏感信息。

const crypto = require('crypto');

function timingSafeCompare(a, b) {
  const aBuffer = Buffer.from(a);
  const bBuffer = Buffer.from(b);
  
  // crypto.timingSafeEqual 总是花费相同时间!
  return crypto.timingSafeEqual(aBuffer, bBuffer);
}

时序安全比较(安全).

实际应用场景

用户会话验证.

密码重置令牌.

场景3:API签名验证.

什么时候需要用时序安全比较?

必须使用的情况:

密码验证(对比哈希值).

API密钥验证.

会话令牌验证.

重置密码令牌.

数字签名验证.

任何涉及密钥/令牌比较的地方.

不需要使用的情况:

比较非敏感数据(如用户名、邮箱格式).

数据库查询条件(数据库本身可能有时序问题).

业务逻辑判断(如检查订单状态).

时序安全比较的核心要点:

固定时间:无论比较的数据是否匹配,执行时间都相同.

防止信息泄露:攻击者无法通过测量时间来推测正确值.

关键场景:所有涉及密钥、令牌、密码等敏感信息的比较.

Node.js实现:使用 crypto.timingSafeEqual().

注意长度:比较前要确保Buffer长度相同,否则要先处理.

只要是比较密钥、令牌、密码等敏感信息,就用 crypto.timingSafeEqual()!

数字证书和SSL/TLS
Let's Encrypt免费证书
证书类型表
类型	验证级别	适用场景	价格	浏览器显示
DV证书	域名验证	个人网站、博客	免费-几十美元	🔒 绿色锁
OV证书	组织验证	企业官网	$100-$500/年	🔒 绿色锁+公司名
EV证书	扩展验证	银行、电商	$500-$2000/年	🔒 绿色锁+公司名+绿色地址栏
自签名	无验证	内部系统、开发	免费	🔴 红色警告
Diffie-Hellman 密钥交换
实用工具函数

安全随机数生成。

数据完整性验证.

场景1:用户密码存储

场景2:API请求签名

场景3:安全配置文件加密

Node.js Debugger 完全指南

内置调试器基础使用.

# 方法1:直接调试
node inspect app.js

# 方法2:附加到正在运行的进程
node --inspect app.js          # 默认端口9229
node --inspect=9229 app.js     # 指定端口
node --inspect-brk app.js      # 第一行就断点

# 方法3:远程调试
node --inspect=0.0.0.0:9229 app.js  # 允许远程连接

基本调试命令

连接 Chrome DevTools
# 启动调试
node --inspect app.js

# 输出类似:
# Debugger listening on ws://127.0.0.1:9229/...
实用调试技巧
// 在代码中使用 debugger 语句
function processData(data) {
  debugger; // 手动断点
  
  // 条件调试
  if (data.length > 100) {
    console.log('数据过大');
    debugger; // 条件断点
  }
}

网络请求调试.

const http = require('http');

// 启用详细的调试信息
process.env.NODE_DEBUG = 'http';

http.createServer((req, res) => {
  console.log('请求头:', req.headers);
  debugger; // 检查请求
  res.end('Hello');
}).listen(3000);

  1. 内存泄漏调试
# 生成堆快照
node --inspect --heapsnapshot-on-signal app.js

# 或使用 Chrome DevTools Memory 面板
  1. CPU 性能分析
# 生成CPU性能文件
node --inspect --cpu-prof app.js

# 分析性能瓶颈
node --prof app.js
node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt
  1. 异步代码调试
async function fetchData() {
  debugger; // 1. 这里会暂停
  
  const response = await fetch('...');
  debugger; // 2. await 后继续调试
  
  const data = await response.json();
  debugger; // 3. 可以检查数据
  
  return data;
}

调试 Promise.

// 启用未处理Promise警告
process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理的Promise拒绝:', reason);
  debugger;
});

// 或在 async 函数中
async function test() {
  try {
    await someAsyncOperation();
  } catch (error) {
    console.error(error);
    debugger; // 错误发生时暂停
  }
}

调试内存问题.

// 记录内存使用
setInterval(() => {
  const used = process.memoryUsage();
  console.log(`内存使用:
    RSS: ${Math.round(used.rss / 1024 / 1024)}MB
    HeapTotal: ${Math.round(used.heapTotal / 1024 / 1024)}MB
    HeapUsed: ${Math.round(used.heapUsed / 1024 / 1024)}MB`);
}, 10000);

Docker 容器调试.

# Dockerfile
FROM node:16
EXPOSE 9229  # 调试端口
CMD ["node", "--inspect=0.0.0.0:9229", "app.js"]

运行并映射调试端口

docker run -p 3000:3000 -p 9229:9229 -d myapp.

📝 八、最佳实践 使用 Source Maps - 便于调试 TypeScript 或转译代码.

设置 NODE_OPTIONS - export NODE_OPTIONS="--inspect=9229".

合理使用断点 - 避免过多断点影响性能.

日志分级 - 结合调试器和日志输出.

团队标准化 - 统一的调试配置和流程.

the end.