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

Supabase Postgres存储短加密文本遇报错,求解决方案

解决PostgreSQL存储加密文本时的空字符问题(同时保持最短存储长度)

问题背景

用crypto-js的AES加密文本后,为缩短存储长度将Base64结果通过atob转成二进制字符串,存储到Supabase的PostgreSQL时触发错误:

ERROR: unsupported Unicode escape sequence Detail: � cannot be converted to text.

原因是PostgreSQL不支持空终止字符�,直接处理二进制字符串会踩坑。之前尝试的trim()(会破坏有效数据)、替换空字符(无法准确还原)均不可行,需要找替代方案。

可行解决方案

方案1:改用Base64URL编码(接近原长度,无兼容问题)

Base64URL是Base64的变体,将+替换为-、/替换为_,去掉末尾的=,比标准Base64略短,且所有字符都是PostgreSQL支持的ASCII字符,彻底规避空字符问题。

修改加密解密函数:

import AES from 'crypto-js/aes';
import encBase64url from 'crypto-js/enc-base64url';
import encUtf8 from 'crypto-js/enc-utf8';

export function encryptText(text, key) {
  // 直接输出Base64URL编码结果,无需转二进制
  return AES.encrypt(text, key).toString(encBase64url);
}

export function decryptText(encodedText, key) {
  // 用Base64URL格式解析后解密
  return AES.decrypt(encodedText, key, { format: encBase64url }).toString(encUtf8);
}

方案2:存储为PostgreSQL的bytea类型(存储效率最高)

PostgreSQL的bytea类型专门用于存储二进制数据,完全避免字符编码问题,且存储的是原始二进制字节,长度是最短的(比Base64短约33%)。

修改函数,将加密结果转为Uint8Array后存入bytea字段:

import AES from 'crypto-js/aes';
import encUtf8 from 'crypto-js/enc-utf8';
import WordArray from 'crypto-js/lib-typedarrays';

export function encryptText(text, key) {
  // 将加密后的WordArray转为Uint8Array
  const encryptedWordArray = AES.encrypt(text, key);
  return WordArray.toUint8Array(encryptedWordArray);
}

export function decryptText(binaryData, key) {
  // 将Uint8Array转回WordArray再解密
  const wordArray = WordArray.create(binaryData);
  return AES.decrypt(wordArray, key).toString(encUtf8);
}

在Supabase中,直接将这个Uint8Array传入insert/update操作即可,Supabase会自动处理bytea类型的存储。

方案3:十六进制编码(兼容性极强,长度略长)

如果不想修改字段类型,十六进制编码是稳妥选择,所有字符都是0-9和a-f,PostgreSQL完全支持,缺点是长度比Base64长约一倍,但胜在实现简单。

修改函数:

import AES from 'crypto-js/aes';
import encHex from 'crypto-js/enc-hex';
import encUtf8 from 'crypto-js/enc-utf8';

export function encryptText(text, key) {
  return AES.encrypt(text, key).toString(encHex);
}

export function decryptText(hexText, key) {
  return AES.decrypt(hexText, key, { format: encHex }).toString(encUtf8);
}

方案对比

方案存储长度兼容性操作复杂度
Base64URL较短(比原二进制字符串长约33%)全兼容低
bytea类型存储最短(原始二进制)需使用bytea字段中
十六进制编码最长(比原二进制长100%)全兼容低

内容的提问来源于stack exchange,提问作者chit's programming blog

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:23:08