Next.js+TypeScript项目调用crypto.publicEncrypt报Cannot read properties of null错误
问题原因
- 执行环境不匹配:你使用的
crypto是Node.js内置模块,仅能在Node.js运行环境(如Next.js的API路由、getServerSideProps等服务端场景)下运行。若该加密方法在客户端(浏览器侧)调用,浏览器没有对应的原生实现,仅安装@types/node仅能解决类型校验问题,无法提供运行时代码,会导致公钥解析步骤返回null,触发该报错。 - 公钥格式错误:若传入的
public_key不符合标准PEM格式,比如缺失-----BEGIN PUBLIC KEY-----/-----END PUBLIC KEY-----头尾标识、换行符丢失、内容被截断,都会导致公钥解析失败返回null,触发该错误。
解决方案
方案1:将加密逻辑迁移到服务端(推荐)
将加密逻辑移到Next.js的服务端执行场景中,比如:
- 接口请求前先调用你自己写的Next.js API路由,在API路由中执行加密后再返回结果
- 在
getServerSideProps中完成敏感数据加密后再传递给客户端
服务端原生支持crypto模块,无需额外配置,你的现有加密代码无需修改即可正常运行。
方案2:客户端加密改用浏览器原生API
若必须在客户端执行加密,放弃使用Node.js的crypto模块,改用浏览器原生支持的Web Crypto API实现,示例代码如下:
export const encryptSensitiveData = async ({ sensitive_data, public_key, }: { sensitive_data: string; public_key: string; }) => { // 转换公钥格式,去掉PEM头尾和换行 const pubKeyContent = public_key .replace(/-----BEGIN PUBLIC KEY-----/, '') .replace(/-----END PUBLIC KEY-----/, '') .replace(/\n/g, ''); const keyBuffer = Uint8Array.from(atob(pubKeyContent), c => c.charCodeAt(0)); // 导入公钥 const publicKey = await crypto.subtle.importKey( 'spki', keyBuffer, { name: 'RSA-OAEP', hash: 'SHA-256' }, // 对应RSA_PKCS1_OAEP_PADDING,若要使用PKCS1填充可调整参数 false, ['encrypt'] ); // 加密数据 const dataBuffer = new TextEncoder().encode(sensitive_data); const encryptedBuffer = await crypto.subtle.encrypt( { name: 'RSA-OAEP' }, publicKey, dataBuffer ); // 转base64返回 return btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer))); };
额外校验点
先确认你传入的公钥是完整的标准PEM格式,示例如下:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr...(公钥主体内容) ... -----END PUBLIC KEY-----
注意头尾标识不可缺失,公钥主体的换行符不要随意删除。
内容的提问来源于stack exchange,提问作者Ishrat
相关产品推荐
相关产品推荐

