You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS实现Bitnami Sealed Secrets解密遇RSA-OAEP填充错误求助

解决Sealed Secret解密时的Invalid RSAES-OAEP padding错误

以下是导致错误的关键问题及修正方案:

问题分析

  1. 数据拆分错误:截取AES加密数据时错误地减去了1字节,导致后续RSA解密的输入数据错位或不完整
  2. Label参数类型不兼容:node-forge的RSA-OAEP解密不接受Node.js原生Buffer作为label参数,需要转换为forge兼容格式
  3. AES会话密钥处理错误:RSA解密得到的会话密钥是原始二进制字节,不需要额外转十六进制
  4. AES-GCM数据拆分遗漏标签:Bitnami的AES-256-GCM加密结果包含IV、密文和认证标签,未处理标签会导致解密失败

修正后的代码

import * as fs from 'fs';
import * as forge from 'node-forge';

// 加载私钥
const privateKeyPEM = fs.readFileSync('priv.key', 'utf8');
const privateKey = forge.pki.privateKeyFromPem(privateKeyPEM);

// Sealed Secret原始数据
const sealedSecretData = Buffer.from(
  'AgAdMSMYznQfAavqvsmqVnjnZYnaPHyrLoxsj6Qg5uoH0yWgkgea9ipMgl2CAXaatUxsz4Qx3ULM6GyRmOvTP47ETt0h3rALxK47lXdoDq3z9937/2rln2uMaGhCyyTQ0m7G3F0Rj3J5NRFnuuVhYZit/v6vrXHKqAHTuG0AxIA/nuN0o3nFN7+MmBs3RTXPII+6CYYmho3ldZwimyQKrBkbbZpRjFnmvv2ErGFQg9lz63QxzTqE5EPvrz0DIwGFUxJKKZ2fOucVcXavEkZJUflKFnK58d/ur90GPQp/N5Ivmqj+1Lf7L5ezqAP5WpmK0M2q69D6RG+OUoOgpYLNQJybL4nxqgv4lFu0eXHxBwqjmNUOqkFDAd5APS1CDaFNjcw5dJ009jqeUN+4AxM2WtfzjjQz6rf5M5UmGMDCc26mjx3fOvi8AAIvEJ6B/hJcRwnC0zqsK0apJ00VykRyHsOTK8G6/eFy8wFnvx4neBCNKgQAMMq0F8A5ekWVZg7sxdeUucc2KXHc53c/p+tOcf0eMBCwefM7ijcoc85x+0wr+wigJ71BakjCGZfQDlnnfOGf9ayp4EhpiPfUdNQ8k1A3G45dE8wJdrUtvn4Qoootevhb9acWM3rKjFstDj3FB8epCct85Fnu5y8QGqWPfUTiprSNWAc+1zejXtZULSWal2cf66kniG+hjjAeEU8l2unncQj+0mf/',
  'base64'
);

// 正确拆分Sealed Secret数据
const aesKeySize = sealedSecretData.readUIntBE(0, 2);
const rsaEncryptedData = sealedSecretData.slice(2, 2 + aesKeySize);
// 移除错误的length-1截断,取完整剩余数据作为AES加密结果
const aesEncryptedData = sealedSecretData.slice(2 + aesKeySize);

// 转换Label为forge兼容的Buffer格式
const label = forge.util.createBuffer('kube-systemsealed-secrets-keyfc5ht', 'utf8');

// 解密RSA加密数据获取AES会话密钥
const rsaEncryptedBytes = forge.util.createBuffer(rsaEncryptedData.toString('binary'));
const aesSessionKey = privateKey.decrypt(rsaEncryptedBytes.getBytes(), 'RSA-OAEP', {
  md: forge.md.sha256.create(),
  label,
});

// 拆分AES-GCM的IV、密文和认证标签(GCM标准标签长度为16字节)
const iv = aesEncryptedData.slice(0, 16);
const ciphertext = aesEncryptedData.slice(16, -16);
const tag = aesEncryptedData.slice(-16);

// 解密AES-GCM数据
const aesDecipher = forge.cipher.createDecipher('AES-GCM', aesSessionKey);
aesDecipher.start({
  iv: forge.util.createBuffer(iv.toString('binary')),
  tag: forge.util.createBuffer(tag.toString('binary')), // 传入认证标签用于完整性验证
});
aesDecipher.update(forge.util.createBuffer(ciphertext.toString('binary')));
const decryptSuccess = aesDecipher.finish();

if (decryptSuccess) {
  const decryptedSecretData = aesDecipher.output.toString('utf8');
  console.log('解密成功:', decryptedSecretData);
} else {
  console.error('AES-GCM解密失败,可能是数据篡改或密钥不匹配');
}

关键改动说明

  • 数据拆分修正:删除sealedSecretData.length - 1的错误截断,确保AES加密数据完整
  • Label格式修正:用forge的Buffer包装label字符串,符合RSA-OAEP解密的参数要求
  • 会话密钥处理:直接使用RSA解密后的原始字节作为AES密钥,移除多余的hexToBytes转换
  • AES-GCM标签处理:明确拆分并传入认证标签,保证GCM解密的完整性验证通过

内容的提问来源于stack exchange,提问作者Saad Belkhou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:10:30