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;
}最佳实践
- 选择合适的算法:RSA用于密钥交换,ECC用于移动设备
- 使用足够长的密钥:RSA至少2048位,ECC至少256位
- 保护私钥:使用硬件安全模块(HSM)存储私钥
- 定期更新密钥:根据安全策略定期轮换密钥
- 验证证书链:确保数字证书的有效性
- 使用混合加密:结合对称和非对称加密的优势
非对称加密解决了密钥分发问题,是现代网络安全的基础。理解其原理和应用对于构建安全的系统至关重要。