将特定数据字符串转换为可逆向还原的固定长度字母数字串
解决方案:可逆固定长度字母数字编码实现
核心思路
要实现可还原的固定长度字母数字串,不能依赖单向哈希算法,需采用「序列化 + 对称加密 + 编码分段」的组合方案,既保证可逆性,又能输出符合要求的固定长度格式。
具体实现步骤
1. 序列化原始数据
先把ID、issuer Id、时间戳、随机字符串这些结构化数据序列化为二进制格式,优先选择体积紧凑的序列化方式(比如Protobuf、MsgPack),为后续固定长度处理减少冗余。
- 伪代码示例:
import msgpack raw_data = {"id": 12345, "issuer_id": "iss_789", "timestamp": 1699999999, "random_str": "xyzabc123"} serialized_bytes = msgpack.packb(raw_data)
2. 对称加密固定字节长度
如果原始序列化后的字节长度不固定,使用分组对称加密算法(如AES-256-CBC),它会输出固定块大小的加密结果(AES块大小为16字节),不足部分用PKCS7填充,确保加密后字节长度固定(或按块倍数扩展后固定)。
- 伪代码示例:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding import os key = os.urandom(32) # AES-256密钥,服务器端需安全存储 iv = os.urandom(16) # 初始化向量,需和加密结果一同传输 # 填充明文至块大小倍数 padder = padding.PKCS7(128).padder() padded_data = padder.update(serialized_bytes) + padder.finalize() # 执行AES加密 cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) encryptor = cipher.encryptor() encrypted_bytes = encryptor.update(padded_data) + encryptor.finalize()
3. 编码为纯字母数字串
将加密后的二进制数据转成Base32编码,它仅使用大写字母和数字,和示例格式匹配,还能避免大小写混淆问题,后续可去掉填充符=(还原时补回即可)。
- 伪代码示例:
import base64 encoded_str = base64.b32encode(encrypted_bytes + iv).decode('utf-8').replace('=', '')
4. 分段处理为目标格式
把编码后的字符串按每4个字符分段,用连字符分隔,得到示例中的格式:
- 伪代码示例:
chunked_str = '-'.join([encoded_str[i:i+4] for i in range(0, len(encoded_str), 4)]) # 输出示例:U89B-AKFZ-GIM8-HYU3-ZCYH-V5PE-Y3G9-G1B0
服务器端还原流程
- 去掉字符串中的连字符,还原为完整编码串
- 按Base32规则补回填充符
=,确保字符串长度为8的倍数 - Base32解码为二进制数据,拆分出初始化向量IV和加密字节
- 使用服务器端存储的密钥和IV执行AES解密,去掉PKCS7填充
- 反序列化二进制数据,还原出原始的ID、issuer Id、时间戳和随机字符串
关键注意事项
- 对称密钥必须严格保密存储在服务器端,禁止泄露
- 提前约定原始数据的最大长度,确保加密后的字节长度固定,进而保证最终编码串长度一致
- Base32编码的长度有固定换算规则(每5字节二进制转8字节Base32),结合加密块大小可精准控制输出长度
内容的提问来源于stack exchange,提问作者Dineshkumar pachamuthu
相关产品推荐
相关产品推荐

