React Router
Cryptography

非对称加密

深入理解非对称加密的原理、算法和应用

非对称加密

非对称加密是现代密码学的革命性突破,它使用一对密钥(公钥和私钥)来解决对称加密中的密钥分发问题。

非对称加密的基本原理

非对称加密的核心思想是:使用不同的密钥进行加密和解密

明文 + 公钥 = 密文
密文 + 私钥 = 明文

密钥对的概念

  • 公钥(Public Key):可以公开分享,用于加密
  • 私钥(Private Key):必须保密,用于解密
  • 数学关系:两个密钥在数学上相关,但无法从公钥推导出私钥

数学基础

1. 大整数分解问题

RSA算法基于大整数分解的困难性:给定两个大质数的乘积,很难分解出原始质数。

// 大整数分解示例(小数字演示)
function findFactors(n) {
  const factors = [];
  for (let i = 2; i <= Math.sqrt(n); i++) {
    if (n % i === 0) {
      factors.push(i);
      if (i !== n / i) {
        factors.push(n / i);
      }
    }
  }
  return factors;
}

// 示例
const n = 15;
console.log(`${n} 的因子: ${findFactors(n)}`);

// 但对于大数,分解变得极其困难
const largeNumber = 123456789012345678901234567890123456789;
// findFactors(largeNumber) 需要很长时间

2. 离散对数问题

椭圆曲线密码学基于椭圆曲线上离散对数的困难性。

// 简单的离散对数示例
function discreteLog(base, result, modulus) {
  for (let i = 0; i < modulus; i++) {
    if (Math.pow(base, i) % modulus === result) {
      return i;
    }
  }
  return null;
}

// 示例
const base = 2;
const modulus = 11;
const result = 8;
const log = discreteLog(base, result, modulus);
console.log(`${base}^${log} mod ${modulus} = ${result}`);

RSA 算法

RSA 密钥生成

// RSA 密钥生成(简化版)
function generateRSAKeys() {
  // 1. 选择两个大质数
  const p = 61;  // 实际应用中应该是大质数
  const q = 53;
  
  // 2. 计算 n = p * q
  const n = p * q;
  
  // 3. 计算欧拉函数 φ(n) = (p-1)(q-1)
  const phi = (p - 1) * (q - 1);
  
  // 4. 选择公钥 e,满足 gcd(e, φ(n)) = 1
  const e = 17;  // 通常选择 65537
  
  // 5. 计算私钥 d,满足 (e * d) mod φ(n) = 1
  const d = modInverse(e, phi);
  
  return {
    publicKey: { e, n },
    privateKey: { d, n }
  };
}

// 模逆运算
function modInverse(a, m) {
  for (let x = 1; x < m; x++) {
    if (((a % m) * (x % m)) % m === 1) {
      return x;
    }
  }
  return null;
}

RSA 加密和解密

// RSA 加密和解密
function rsaEncrypt(message, publicKey) {
  const { e, n } = publicKey;
  // 将消息转换为数字
  const m = message.split('').map(char => char.charCodeAt(0));
  
  // 加密:c = m^e mod n
  return m.map(charCode => {
    return modPow(charCode, e, n);
  });
}

function rsaDecrypt(ciphertext, privateKey) {
  const { d, n } = privateKey;
  
  // 解密:m = c^d mod n
  const decrypted = ciphertext.map(c => {
    return modPow(c, d, n);
  });
  
  // 转换回字符
  return decrypted.map(code => String.fromCharCode(code)).join('');
}

// 模幂运算
function modPow(base, exponent, modulus) {
  let result = 1;
  base = base % modulus;
  
  while (exponent > 0) {
    if (exponent % 2 === 1) {
      result = (result * base) % modulus;
    }
    exponent = Math.floor(exponent / 2);
    base = (base * base) % modulus;
  }
  
  return result;
}

// 示例
const keys = generateRSAKeys();
const message = "HELLO";
const encrypted = rsaEncrypt(message, keys.publicKey);
const decrypted = rsaDecrypt(encrypted, keys.privateKey);

console.log(`原文: ${message}`);
console.log(`加密: ${encrypted}`);
console.log(`解密: ${decrypted}`);

椭圆曲线密码学(ECC)

ECC 的优势

  • 密钥长度短:256位ECC密钥相当于3072位RSA密钥
  • 计算效率高:加密解密速度更快
  • 资源消耗少:适合移动设备和物联网

ECC 密钥生成

// 椭圆曲线参数(secp256k1,比特币使用的曲线)
const curve = {
  p: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
  a: 0,
  b: 7,
  G: {
    x: 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
    y: 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
  },
  n: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
};

// 生成私钥(随机数)
function generatePrivateKey() {
  return crypto.randomBytes(32);
}

// 从私钥生成公钥
function generatePublicKey(privateKey) {
  // 公钥 = 私钥 * G
  // 这里简化处理,实际需要椭圆曲线点乘运算
  return {
    x: privateKey * curve.G.x % curve.p,
    y: privateKey * curve.G.y % curve.p
  };
}

数字签名

RSA 数字签名

// RSA 数字签名
function rsaSign(message, privateKey) {
  // 1. 计算消息哈希
  const hash = sha256(message);
  
  // 2. 使用私钥加密哈希值
  const signature = modPow(hash, privateKey.d, privateKey.n);
  
  return signature;
}

function rsaVerify(message, signature, publicKey) {
  // 1. 计算消息哈希
  const hash = sha256(message);
  
  // 2. 使用公钥解密签名
  const decryptedHash = modPow(signature, publicKey.e, publicKey.n);
  
  // 3. 比较哈希值
  return hash === decryptedHash;
}

// SHA-256 哈希函数(简化版)
function sha256(message) {
  // 实际应用中应使用加密库
  let hash = 0;
  for (let i = 0; i < message.length; i++) {
    const char = message.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // 转换为32位整数
  }
  return Math.abs(hash);
}

ECDSA 数字签名

// ECDSA 签名(简化版)
function ecdsaSign(message, privateKey) {
  // 1. 计算消息哈希
  const hash = sha256(message);
  
  // 2. 生成随机数 k
  const k = crypto.randomBytes(32);
  
  // 3. 计算 R = k * G
  const R = pointMultiply(k, curve.G);
  
  // 4. 计算 s = k^(-1) * (hash + privateKey * R.x) mod n
  const s = modInverse(k, curve.n) * (hash + privateKey * R.x) % curve.n;
  
  return { r: R.x, s: s };
}

function ecdsaVerify(message, signature, publicKey) {
  // 1. 计算消息哈希
  const hash = sha256(message);
  
  // 2. 计算 w = s^(-1) mod n
  const w = modInverse(signature.s, curve.n);
  
  // 3. 计算 u1 = hash * w mod n
  const u1 = (hash * w) % curve.n;
  
  // 4. 计算 u2 = r * w mod n
  const u2 = (signature.r * w) % curve.n;
  
  // 5. 计算 P = u1 * G + u2 * publicKey
  const P = pointAdd(
    pointMultiply(u1, curve.G),
    pointMultiply(u2, publicKey)
  );
  
  // 6. 验证 P.x = r
  return P.x === signature.r;
}

混合加密系统

结合对称和非对称加密

// 混合加密系统
class HybridEncryption {
  constructor() {
    this.rsaKeys = generateRSAKeys();
  }
  
  // 加密:使用对称加密加密数据,用非对称加密加密对称密钥
  encrypt(data) {
    // 1. 生成随机对称密钥
    const symmetricKey = crypto.randomBytes(32);
    
    // 2. 使用对称密钥加密数据
    const encryptedData = aesEncrypt(data, symmetricKey);
    
    // 3. 使用RSA公钥加密对称密钥
    const encryptedKey = rsaEncrypt(symmetricKey.toString('hex'), this.rsaKeys.publicKey);
    
    return {
      encryptedData: encryptedData,
      encryptedKey: encryptedKey
    };
  }
  
  // 解密:使用私钥解密对称密钥,再用对称密钥解密数据
  decrypt(encryptedPackage) {
    // 1. 使用RSA私钥解密对称密钥
    const symmetricKeyHex = rsaDecrypt(encryptedPackage.encryptedKey, this.rsaKeys.privateKey);
    const symmetricKey = Buffer.from(symmetricKeyHex, 'hex');
    
    // 2. 使用对称密钥解密数据
    return aesDecrypt(encryptedPackage.encryptedData, symmetricKey);
  }
}

// 使用示例
const hybrid = new HybridEncryption();
const message = "Hello, Hybrid Encryption!";
const encrypted = hybrid.encrypt(message);
const decrypted = hybrid.decrypt(encrypted);

console.log(`原文: ${message}`);
console.log(`解密: ${decrypted}`);

实际应用场景

1. HTTPS/TLS

// TLS 握手过程(简化版)
class TLSServer {
  constructor() {
    this.certificate = this.generateCertificate();
  }
  
  // 服务器证书
  generateCertificate() {
    return {
      publicKey: this.rsaKeys.publicKey,
      domain: "example.com",
      issuer: "CA",
      validFrom: new Date(),
      validTo: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000)
    };
  }
  
  // TLS 握手
  handshake(clientHello) {
    // 1. 发送服务器证书
    const serverHello = {
      certificate: this.certificate,
      cipherSuites: ["TLS_AES_256_GCM_SHA384"],
      random: crypto.randomBytes(32)
    };
    
    // 2. 客户端验证证书并生成预主密钥
    const preMasterSecret = crypto.randomBytes(48);
    const encryptedPreMaster = rsaEncrypt(preMasterSecret, this.certificate.publicKey);
    
    // 3. 生成主密钥
    const masterSecret = this.generateMasterSecret(preMasterSecret, clientHello.random, serverHello.random);
    
    // 4. 生成会话密钥
    const sessionKeys = this.generateSessionKeys(masterSecret);
    
    return {
      serverHello: serverHello,
      sessionKeys: sessionKeys
    };
  }
}

2. 数字证书

// 数字证书结构
class DigitalCertificate {
  constructor(subject, publicKey, issuer) {
    this.version = 3;
    this.serialNumber = crypto.randomBytes(16);
    this.signatureAlgorithm = "sha256WithRSAEncryption";
    this.issuer = issuer;
    this.validity = {
      notBefore: new Date(),
      notAfter: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000)
    };
    this.subject = subject;
    this.subjectPublicKeyInfo = {
      algorithm: "rsaEncryption",
      publicKey: publicKey
    };
    this.extensions = [
      {
        id: "basicConstraints",
        critical: true,
        value: { cA: false }
      },
      {
        id: "keyUsage",
        critical: true,
        value: ["digitalSignature", "keyEncipherment"]
      }
    ];
  }
  
  // 签名证书
  sign(issuerPrivateKey) {
    const tbsCertificate = this.toDER(); // 转换为DER格式
    this.signature = rsaSign(tbsCertificate, issuerPrivateKey);
    return this;
  }
  
  // 验证证书
  verify(issuerPublicKey) {
    const tbsCertificate = this.toDER();
    return rsaVerify(tbsCertificate, this.signature, issuerPublicKey);
  }
}

3. 区块链和加密货币

// 比特币地址生成
class BitcoinWallet {
  constructor() {
    this.privateKey = crypto.randomBytes(32);
    this.publicKey = this.generatePublicKey();
    this.address = this.generateAddress();
  }
  
  // 从私钥生成公钥
  generatePublicKey() {
    // 使用椭圆曲线 secp256k1
    return generatePublicKey(this.privateKey);
  }
  
  // 从公钥生成地址
  generateAddress() {
    // 1. 计算公钥哈希
    const publicKeyHash = ripemd160(sha256(this.publicKey));
    
    // 2. 添加版本号
    const versionedHash = Buffer.concat([Buffer.from([0x00]), publicKeyHash]);
    
    // 3. 计算校验和
    const checksum = sha256(sha256(versionedHash)).slice(0, 4);
    
    // 4. 组合并Base58编码
    const binaryAddr = Buffer.concat([versionedHash, checksum]);
    return base58Encode(binaryAddr);
  }
  
  // 签名交易
  signTransaction(transaction) {
    const transactionHash = sha256(JSON.stringify(transaction));
    return ecdsaSign(transactionHash, this.privateKey);
  }
}

安全考虑

1. 密钥长度

// 不同算法的安全密钥长度
const securityLevels = {
  "RSA": {
    "80位安全": 1024,
    "112位安全": 2048,
    "128位安全": 3072,
    "256位安全": 15360
  },
  "ECC": {
    "80位安全": 160,
    "112位安全": 224,
    "128位安全": 256,
    "256位安全": 512
  }
};

2. 侧信道攻击防护

// 时间攻击防护
function constantTimeCompare(a, b) {
  if (a.length !== b.length) {
    return false;
  }
  
  let result = 0;
  for (let i = 0; i < a.length; i++) {
    result |= a[i] ^ b[i];
  }
  
  return result === 0;
}

3. 随机数生成

// 安全的随机数生成
function secureRandomBytes(length) {
  return crypto.randomBytes(length);
}

// 不安全的随机数生成(仅作对比)
function insecureRandomBytes(length) {
  const bytes = new Uint8Array(length);
  for (let i = 0; i < length; i++) {
    bytes[i] = Math.floor(Math.random() * 256);
  }
  return bytes;
}

最佳实践

  1. 选择合适的算法:RSA用于密钥交换,ECC用于移动设备
  2. 使用足够长的密钥:RSA至少2048位,ECC至少256位
  3. 保护私钥:使用硬件安全模块(HSM)存储私钥
  4. 定期更新密钥:根据安全策略定期轮换密钥
  5. 验证证书链:确保数字证书的有效性
  6. 使用混合加密:结合对称和非对称加密的优势

非对称加密解决了密钥分发问题,是现代网络安全的基础。理解其原理和应用对于构建安全的系统至关重要。