一、数据与主密钥import crypto from 'crypto'
function genDataKey(): Buffer { return crypto.randomBytes(32) }
function genIv(): Buffer { return crypto.randomBytes(12) }
type Envelope = { cmkId: string; iv: string; aad: string; tag: string; ciphertext: string; wrappedKey: string }
二、加密与包裹function encryptEnvelope(plain: Buffer, cmkId: string, cmk: Buffer, aad: Buffer): Envelope {
const dk = genDataKey()
const iv = genIv()
const cipher = crypto.createCipheriv('aes-256-gcm', dk, iv)
cipher.setAAD(aad)
const ct = Buffer.concat([cipher.update(plain), cipher.final()])
const tag = cipher.getAuthTag()
const wrapped = crypto.createCipheriv('aes-256-gcm', cmk, iv).update(dk)
return { cmkId, iv: iv.toString('base64'), aad: aad.toString('base64'), tag: tag.toString('base64'), ciphertext: ct.toString('base64'), wrappedKey: wrapped.toString('base64') }
}
三、解密与验证function decryptEnvelope(env: Envelope, cmk: Buffer): Buffer | null {
const iv = Buffer.from(env.iv, 'base64')
const aad = Buffer.from(env.aad, 'base64')
const tag = Buffer.from(env.tag, 'base64')
const wrapped = Buffer.from(env.wrappedKey, 'base64')
const unwrap = crypto.createDecipheriv('aes-256-gcm', cmk, iv)
const dk = Buffer.concat([unwrap.update(wrapped), unwrap.final()])
const dec = crypto.createDecipheriv('aes-256-gcm', dk, iv)
dec.setAAD(aad)
dec.setAuthTag(tag)
const ct = Buffer.from(env.ciphertext, 'base64')
try { return Buffer.concat([dec.update(ct), dec.final()]) } catch { return null }
}
四、轮换示例type Meta = { cmkId: string }
function rotateEnvelope(env: Envelope, meta: Meta, oldCmk: Buffer, newCmkId: string, newCmk: Buffer): Envelope | null {
const plain = decryptEnvelope(env, oldCmk)
if (!plain) return null
const aad = Buffer.from(env.aad, 'base64')
return encryptEnvelope(plain, newCmkId, newCmk, aad)
}
五、验收清单数据密钥长度32字节(AES-256)与IV长度12字节(GCM);AAD参与认证;标签校验通过。包裹与解包均基于CMK;轮换后更新`cmkId`与`wrappedKey`,解密成功校验。元数据包含`cmkId/iv/aad/tag`等字段;异常返回`null`并记录审计。

发表评论 取消回复