核心要点固化 SBOM 模式与版本;统一采用 JSON 并限定 schema 版本。组件必须包含名称、版本、哈希与来源;禁止缺失或弱算法。SBOM 与构建产物互相引用对齐,支持离线验证与归档。对 SBOM 文件执行签名与密钥轮换;校验时间窗口与 `kid`。参数与规则允许 schema:SPDX `2.3`、CycloneDX `1.5`。允许算法:`SHA-256`;外部引用仅限 `https` 白名单域。时间窗口:`created` 与 `expires` 间隔不超过 `7d`;校验 `leeway` ≤ `60s`。实现示例type Component = { name: string; version: string; hashes: { alg: 'SHA-256'; value: string }[]; purl?: string; supplier?: string; licenses?: string[] } function validHash(h: { alg: 'SHA-256'; value: string }): boolean { return /^[A-Fa-f0-9]{64}$/.test(h.value) } function validComponent(c: Component): boolean { if (!c.name || !c.version) return false if (!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.test(c.version)) return false if (!c.hashes || c.hashes.length === 0) return false for (const h of c.hashes) if (!validHash(h)) return false return true } type Sbom = { format: 'SPDX' | 'CycloneDX'; version: '2.3' | '1.5'; components: Component[]; created: number; expires: number } function within(created: number, expires: number, now: number, leewaySec: number): boolean { if (expires <= created) return false return now + leewaySec * 1000 >= created && now - leewaySec * 1000 <= expires } function validateSbom(s: Sbom): { ok: boolean; errors: string[] } { const errors: string[] = [] if (s.format === 'SPDX' && s.version !== '2.3') errors.push('spdx-version') if (s.format === 'CycloneDX' && s.version !== '1.5') errors.push('cxdx-version') if (!within(s.created, s.expires, Date.now(), 60)) errors.push('time-window') for (const c of s.components) if (!validComponent(c)) errors.push(`component:${c.name}`) return { ok: errors.length === 0, errors } } async function signSbom(s: Sbom, jwk: JsonWebKey, kid: string): Promise<{ kid: string; alg: string; sig: string }> { const data = Buffer.from(JSON.stringify(s)) const key = await crypto.subtle.importKey('jwk', jwk, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign']) const sig = await crypto.subtle.sign({ name: 'RSASSA-PKCS1-v1_5' }, key, data) return { kid, alg: 'RS256', sig: Buffer.from(sig).toString('base64') } } async function verifySbom(s: Sbom, signed: { kid: string; alg: string; sig: string }, jwk: JsonWebKey): Promise<boolean> { if (signed.alg !== 'RS256') return false const data = Buffer.from(JSON.stringify(s)) const key = await crypto.subtle.importKey('jwk', jwk, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['verify']) return crypto.subtle.verify({ name: 'RSASSA-PKCS1-v1_5' }, key, Buffer.from(signed.sig, 'base64'), data) } 审计与归档构建产出存档包含:SBOM、签名、密钥 `kid`、时间戳与组件哈希列表。任意产物均可通过 SBOM 反向定位来源、版本与校验状态,实现快速回溯。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
1.821442s