关于 cryptography
面向开发者的密码学安全技能,依据 Hack23 ISMS 密码控制政策规范加密算法、密钥管理和传输保护,并提供实现示例。
主要功能
- 01规定批准与禁用的密码算法
- 02给出密钥生成、存储和轮换要求
- 03规范 TLS、证书与随机数使用
- 04涵盖静态与传输中数据加密
- 05提供常见密码学操作示例
适用场景
- 01为应用选择符合政策的加密算法
- 02检查密钥生命周期管理做法
- 03配置 TLS 与证书验证
- 04加密敏感数据及通信
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ hack23/ homepage --skill cryptography安装后在 Claude Code 中输入/cryptography确认已加载。
详细介绍
密码学技能
目的
此技能强制执行 Hack23 ISMS 密码控制策略中定义的密码学要求。它确保所有密码操作均使用获批算法,并遵循密钥管理最佳实践。
规则
获批算法
必须使用的对称加密算法:
- AES-256(高级加密标准,256 位密钥)
- AES-128(最低要求,优先使用 AES-256)
- ChaCha20-Poly1305(用于认证加密)
必须使用的非对称加密算法:
- RSA-2048 或更高(最低为 2048 位密钥,优先使用 3072 或 4096 位)
- 使用 P-256、P-384 或 P-521 曲线的 ECDSA
- Ed25519(基于 Curve25519 的 EdDSA)
必须使用的哈希算法:
- SHA-256(最低要求)
- SHA-384
- SHA-512
- SHA-3 系列
- BLAKE2(用于高性能应用)
必须使用的密码哈希算法:
- bcrypt(成本因子至少为 12)
- scrypt
- Argon2id(优先使用)
- 使用 SHA-256 的 PBKDF2,迭代次数至少为 100,000 次
必须使用的消息认证算法:
- HMAC-SHA256(最低要求)
- HMAC-SHA512
禁止使用(已弃用/已破解):
- DES、3DES
- MD5、SHA-1(校验和等非安全用途除外)
- RC4
- RSA < 2048 位
- 未使用认证加密的 CBC 模式
- ECB 模式(任何情况下都禁止)
TLS/SSL 要求
必须:
- 至少使用 TLS 1.2
- 优先使用 TLS 1.3
- 仅使用强密码套件
- 验证服务端证书
- 高安全性应用应使用证书固定
- 强制启用 HSTS(HTTP 严格传输安全)
- 使用具备完全前向保密(PFS)的密码套件
TLS 1.2 获批密码套件(按优先级排序):
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS 1.3 获批密码套件:
TLS_AES_256_GCM_SHA384
TLS_AES_128_GCM_SHA256
TLS_CHACHA20_POLY1305_SHA256
禁止:
- 使用 SSL 2.0、SSL 3.0、TLS 1.0、TLS 1.1
- 使用出口级密码算法
- 使用 NULL 密码套件
- 使用匿名密码套件
- 在生产环境中接受自签名证书(明确受信任的 CA 除外)
密钥管理
必须:
- 使用密码学安全的随机数生成器(CSPRNG)生成密钥
- 安全存储密钥(使用密钥管理系统;高度敏感的密钥应使用 HSM)
- 绝不将密钥硬编码在源代码中
- 使用环境变量或机密管理系统
- 按计划轮换密钥:
- TLS 证书:每年轮换一次,或在到期前轮换
- 对称密钥:机密数据每年轮换一次,受限数据每季度轮换一次
- API 密钥:每年轮换一次,或在密钥泄露时轮换
- 密码:特权帐户每 90 天更换一次
- 不再需要密钥时安全销毁
- 记录密钥生命周期事件(创建、轮换、销毁)
- 将密钥生成与密钥使用分开
- 不同用途使用不同密钥
- 为业务连续性实施密钥托管(并施以严格控制)
密钥长度要求:
- AES:256 位(最低 128 位)
- RSA:至少 2048 位(优先使用 3072 或 4096 位)
- ECDSA:至少 P-256(优先使用 P-384 或 P-521)
- HMAC:至少 256 位
禁止:
- 以明文存储密钥
- 将密钥提交到版本控制系统
- 通过电子邮件或未加密渠道发送密钥
- 在不同应用或上下文中重复使用密钥
- 使用弱密钥派生函数
- 共享私钥
随机数生成
必须:
- 使用密码学安全的伪随机数生成器(CSPRNG)
- 对于 Node.js:
crypto.randomBytes()、crypto.randomInt() - 对于 Python:
secrets模块、os.urandom() - 对于 Java:
SecureRandom - 对于浏览器:
window.crypto.getRandomValues()
禁止:
- 将
Math.random()用于安全目的 - 使用可预测的种子
- 将非密码学伪随机数生成器用于安全令牌、密钥或 IV
初始化向量(IV)和 Nonce
必须:
- 为每次加密操作生成唯一的 IV/Nonce
- CBC 模式使用经过密码学安全随机生成的 IV
- CTR/GCM 模式使用顺序 Nonce(确保唯一性)
- 将 IV 与密文一同存储(IV 不是秘密)
- 不得使用同一密钥重复使用 IV
不得:
- 在 CBC 模式中使用可预测或顺序生成的 IV
- 在 CTR/GCM 模式中使用同一密钥重复使用 Nonce
- 将 IV 视为秘密(IV 应为随机值,但可以公开)
证书管理
必须:
- 使用受信任的证书颁发机构(CA)颁发的证书
- 验证证书链
- 检查证书吊销状态(CRL/OCSP)
- 使用主题备用名称(SAN)支持多个域名
- 实施证书到期监控和告警
- 在证书到期前续期(至少提前 30 天)
- 使用自动化证书管理(例如,使用自动续期功能的 Let's Encrypt)
- 安全存储私钥(加密并进行访问控制)
- 为不同服务/环境使用独立证书
证书有效期:
- 生产环境:最长 1 年
- 开发/测试环境:最长 90 天
- 内部 CA:最长 2 年
不得:
- 在生产环境中使用自签名证书(内部 CA 除外)
- 在多个证书之间共用私钥
- 在缺乏适当访问控制的情况下使用通配符证书
- 忽略证书警告或错误
静态数据加密
必须:
- 对静态存储的机密级和受限级数据进行加密
- 对笔记本电脑和移动设备使用全盘加密
- 对敏感数据库使用数据库加密(TDE)
- 将敏感文件存储到云服务之前进行加密
- 使用信封加密(使用主密钥加密数据密钥)
- 将加密密钥与加密数据分开存储
不得:
- 存储未加密的机密级或受限级数据
- 使用同一密钥进行加密和身份验证
- 对高敏感度数据使用确定性加密
传输中加密
必须:
- 所有网络通信均使用 TLS 1.2+
- 对包含机密级或受限级数据的电子邮件进行加密(S/MIME 或 PGP)
- 使用 VPN 远程访问内部系统
- 远程管理使用 SSH(而非 Telnet)
- 所有 Web 应用均使用 HTTPS
- 使用安全协议(SFTP、FTPS,而非 FTP)
不得:
- 通过未加密的信道传输受限级数据
- 使用未加密协议(HTTP、FTP、Telnet、未使用 TLS 的 SMTP)
- 禁用证书验证
示例
示例 1:对称加密(Node.js)
const crypto = require('crypto');
// GOOD: AES-256-GCM encryption
function encrypt(plaintext, key) {
// Generate random IV (12 bytes for GCM)
const iv = crypto.randomBytes(12);
// Create cipher
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
// Encrypt
let ciphertext = cipher.update(plaintext, 'utf8', 'hex');
ciphertext += cipher.final('hex');
// Get authentication tag
const authTag = cipher.getAuthTag();
// Return IV + authTag + ciphertext
return {
iv: iv.toString('hex'),
authTag: authTag.toString('hex'),
ciphertext: ciphertext
};
}
function decrypt(encrypted, key) {
// Create decipher
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
key,
Buffer.from(encrypted.iv, 'hex')
);
// Set authentication tag
decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'));
// Decrypt
let plaintext = decipher.update(encrypted.ciphertext, 'hex', 'utf8');
plaintext += decipher.final('utf8');
return plaintext;
}
// Generate secure key (store securely, don't hardcode!)
const key = crypto.randomBytes(32); // 256 bits
// Usage
const encrypted = encrypt('Sensitive data', key);
console.log('Encrypted:', encrypted);
const decrypted = decrypt(encrypted, key);
console.log('Decrypted:', decrypted);
// BAD: Using deprecated algorithm
function encryptBad(plaintext, key) {
// NEVER use DES!
const cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
return cipher.update(plaintext, 'utf8', 'hex') + cipher.final('hex');
}
示例 2:密码哈希(使用 bcrypt 的 Node.js)
const bcrypt = require('bcrypt');
// GOOD: bcrypt with appropriate cost factor
async function hashPassword(password) {
// Cost factor 12 = 2^12 iterations (minimum)
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);
return hash;
}
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// Usage
const password = 'MySecurePassword123!';
const hash = await hashPassword(password);
console.log('Hash:', hash);
const isValid = await verifyPassword(password, hash);
console.log('Valid:', isValid);
// BAD: Using weak hashing
function hashPasswordBad(password) {
// NEVER use MD5 or SHA-1 for passwords!
return crypto.createHash('md5').update(password).digest('hex');
}
// BAD: Insufficient iterations
async function hashPasswordWeak(password) {
// Cost factor 4 is too weak!
return await bcrypt.hash(password, 4);
}
示例 3:安全随机数生成
const crypto = require('crypto');
// GOOD: Cryptographically secure random
function generateToken(length = 32) {
return crypto.randomBytes(length).toString('hex');
}
function generateApiKey() {
return crypto.randomBytes(32).toString('base64');
}
function generateSecurePin(digits = 6) {
const max = Math.pow(10, digits);
return crypto.randomInt(0, max).toString().padStart(digits, '0');
}
// Usage
const sessionToken = generateToken();
const apiKey = generateApiKey();
const pin = generateSecurePin(6);
// BAD: Using Math.random() for security
function generateTokenBad() {
// NEVER use Math.random() for security!
return Math.random().toString(36).substring(2);
}
示例 4:TLS 配置(Node.js HTTPS 服务器)
const https = require('https');
const fs = require('fs');
// GOOD: Secure TLS configuration
const options = {
key: fs.readFileSync('/path/to/private-key.pem'),
cert: fs.readFileSync('/path/to/certificate.pem'),
ca: fs.readFileSync('/path/to/ca-bundle.pem'),
// TLS 1.2 minimum
minVersion: 'TLSv1.2',
// Prefer TLS 1.3
maxVersion: 'TLSv1.3',
// Strong cipher suites only
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_AES_128_GCM_SHA256',
'TLS_CHACHA20_POLY1305_SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-ECDSA-AES256-GCM-SHA384',
'ECDHE-ECDSA-AES128-GCM-SHA256'
].join(':'),
// Prefer server cipher order
honorCipherOrder: true,
// Enable Perfect Forward Secrecy
ecdhCurve: 'prime256v1:secp384r1:secp521r1',
// Require client certificate (if needed)
requestCert: false,
rejectUnauthorized: true
};
const server = https.createServer(options, (req, res) => {
// Set security headers
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.writeHead(200);
res.end('Secure connection');
});
server.listen(443);
// BAD: Weak TLS configuration
const optionsBad = {
key: fs.readFileSync('/path/to/private-key.pem'),
cert: fs.readFileSync('/path/to/certificate.pem'),
// NEVER allow TLS 1.0/1.1
minVersion: 'TLSv1.0', // TOO WEAK!
// Allowing weak ciphers
ciphers: 'ALL', // INSECURE!
// Not rejecting unauthorized
rejectUnauthorized: false // DANGEROUS!
};
示例 5:密钥派生(PBKDF2)
const crypto = require('crypto');
// Derive encryption key from password
function deriveKey(password, salt, keyLength = 32) {
// Use PBKDF2 with SHA-256, 100,000 iterations minimum
return crypto.pbkdf2Sync(
password,
salt,
100000, // iterations (minimum)
keyLength,
'sha256'
);
}
// Usage
const password = 'UserPassword123!';
const salt = crypto.randomBytes(16); // Store salt with encrypted data
const key = deriveKey(password, salt, 32); // 256-bit key
console.log('Derived key:', key.toString('hex'));
// BAD: Weak key derivation
function deriveKeyWeak(password) {
// NEVER use simple hashing for key derivation!
return crypto.createHash('sha256').update(password).digest();
}
示例 6:安全文件加密
const crypto = require('crypto');
const fs = require('fs').promises;
async function encryptFile(inputPath, outputPath, key) {
// Read file
const plaintext = await fs.readFile(inputPath);
// Generate IV
const iv = crypto.randomBytes(12);
// Encrypt
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
const ciphertext = Buffer.concat([
cipher.update(plaintext),
cipher.final()
]);
// Get auth tag
const authTag = cipher.getAuthTag();
// Write IV + authTag + ciphertext
const encrypted = Buffer.concat([iv, authTag, ciphertext]);
await fs.writeFile(outputPath, encrypted);
}
async function decryptFile(inputPath, outputPath, key) {
// Read encrypted file
const encrypted = await fs.readFile(inputPath);
// Extract IV, auth tag, and ciphertext
const iv = encrypted.slice(0, 12);
const authTag = encrypted.slice(12, 28);
const ciphertext = encrypted.slice(28);
// Decrypt
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
const plaintext = Buffer.concat([
decipher.update(ciphertext),
decipher.final()
]);
// Write decrypted file
await fs.writeFile(outputPath, plaintext);
}
// Usage
const key = crypto.randomBytes(32);
await encryptFile('sensitive.pdf', 'sensitive.pdf.enc', key);
await decryptFile('sensitive.pdf.enc', 'sensitive-decrypted.pdf', key);
示例 7:证书验证
const https = require('https');
const tls = require('tls');
// GOOD: Verify certificate
function makeSecureRequest(url) {
return new Promise((resolve, reject) => {
https.get(url, {
// Verify certificate chain
rejectUnauthorized: true,
// Check hostname
checkServerIdentity: (hostname, cert) => {
const err = tls.checkServerIdentity(hostname, cert);
if (err) {
return err;
}
// Additional checks
const now = new Date();
const notBefore = new Date(cert.valid_from);
const notAfter = new Date(cert.valid_to);
if (now < notBefore || now > notAfter) {
return new Error('Certificate not valid for current date');
}
return undefined;
}
}, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(data));
}).on('error', reject);
});
}
// BAD: Skipping certificate verification
function makeInsecureRequest(url) {
return new Promise((resolve, reject) => {
https.get(url, {
// NEVER disable certificate verification!
rejectUnauthorized: false // DANGEROUS!
}, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(data));
}).on('error', reject);
});
}
相关 ISMS 政策
相关文档
- SECURITY_ARCHITECTURE.md - 架构中的加密控制
- secure-development SKILL.md - 安全编码实践
- data-classification SKILL.md - 按分类划分的加密要求
合规性映射
ISO 27001:2022
- A.8.24 使用密码技术
NIST Cybersecurity Framework
- PR.DS-1:保护静态数据
- PR.DS-2:保护传输中的数据
CIS Controls
- 控制项 3:数据保护
- 3.10 加密传输中的敏感数据
- 3.11 加密静态存储的敏感数据
密钥轮换计划
| 密钥类型 | 轮换频率 | 立即轮换的触发条件 |
|---|---|---|
| TLS 证书 | 每年 | 泄露、算法存在弱点 |
| 对称密钥(RESTRICTED) | 每季度 | 泄露、员工离职 |
| 对称密钥(CONFIDENTIAL) | 每年 | 泄露 |
| API 密钥 | 每年 | 泄露、员工离职 |
| SSH 密钥 | 2 年 | 泄露 |
| 根 CA 密钥 | 10 年 | 泄露 |
| 数据库加密密钥 | 2 年 | 泄露 |
执行
违反加密要求的情况:
- 严重(使用禁用算法、硬编码密钥):阻止部署
- 高(配置较弱、缺少加密):要求立即修复
- 中(配置欠佳):在当前迭代内修复
评论
支持 Markdown