当前位置: 首页 > article >正文

【Python】利用 Emoji 隐藏数据

背景介绍

Emoji 突变「U盘」?表情符号被曝能“走私”数据,程序员亲测:真的可以!-CSDN博客

Unicode使用代码点(Code Point)序列表示文本,每个代码点对应一个特定字符。通常表示为U+XXXXXXXX格式的十六进制数。对于拉丁字母等简单字符,代码点与显示字符一一对应。但在复杂书写系统中,单个显示字符可能由多个代码点组合而成。

Unicode定义了256个特殊代码点作为变体选择器(Variation Selectors,VS),范围从VS-1(U+FE00)到VS-256(U+E01EF)。它们不直接显示,而是修改前一个字符的样式。例如,g(U+0067)后跟VS-2(U+FE01)仍显示为g,但复制时会包含隐藏的选择器。

由于256个选择器正好对应一个字节(0-255),这提供了一种在Unicode文本中隐藏任意字节数据的方法。

编码实现

字节转变体选择器

def byte_to_variation_selector(byte: int) -> str:
    if byte < 16:
        return chr(0xFE00 + byte)
    else:
        return chr(0xE0100 + (byte - 16))

该函数将字节值映射到对应的变体选择器字符。前16个字节(0-15)对应U+FE00U+FE0F,后续字节(16-255)对应U+E0100U+E01EF

数据编码

def encode(base: str, data: bytes) -> str:
    encoded = [base]
    for byte in data:
        encoded.append(byte_to_variation_selector(byte))
    return ''.join(encoded)

将基础字符(如😊)与所有字节转换后的变体选择器拼接,生成最终字符串。例如:

data = b'hello'  # 字节值 [0x68, 0x65, 0x6c, 0x6c, 0x6f]
encoded = encode('😊', data)
print(encoded)  # 输出:😊󠅘󠅕󠅜󠅜󠅟
print(repr(encoded))  # 输出:'😊\U000e0158\U000e0155\U000e015c\U000e015c\U000e015f'

解码实现

变体选择器转字节

def variation_selector_to_byte(c: str) -> int | None:
    cp = ord(c)
    if 0xFE00 <= cp <= 0xFE0F:
        return cp - 0xFE00
    elif 0xE0100 <= cp <= 0xE01EF:
        return (cp - 0xE0100) + 16
    else:
        return None

通过判断字符的Unicode码点,反向解析出原始字节值。

数据解码

def decode(encoded: str) -> bytes:
    result = []
    for c in encoded:
        byte = variation_selector_to_byte(c)
        if byte is not None:
            result.append(byte)
        elif result:  # 遇到非变体选择符且已开始解码,终止
            break
    return bytes(result)

遍历字符串,跳过基础字符后的非变体选择符,遇到首个变体选择符开始解析,直至再次遇到无效字符停止。

decoded = decode(encoded)
print(decoded.decode('utf-8'))  # 输出:hello

面向对象封装

class UnicodeDataHider:
    def __init__(self, base: str):
        """
        初始化时设置基础字符,后续将基于该字符进行编码。
        :param base: 基础字符,例如 '😊'
        """
        self.base = base

    @staticmethod
    def char_to_variation_selector(char: str) -> str:
        """
        将字符转换为对应的Unicode变体选择器字符。
        :param char: 需要转换的字符
        :return: 对应的Unicode变体选择器字符
        """
        byte = ord(char)  # 获取字符的Unicode码点(字节值)
        if byte < 16:
            return chr(0xFE00 + byte)
        else:
            return chr(0xE0100 + (byte - 16))

    def encode(self, data: str) -> str:
        """
        将字符串编码为隐藏在基础字符后的Unicode变体选择器字符串。
        :param data: 需要编码的数据(普通字符串)
        :return: 编码后的字符串
        """
        encoded = [self.base]
        for char in data:
            encoded.append(self.char_to_variation_selector(char))
        return ''.join(encoded)

    @staticmethod
    def variation_selector_to_char(c: str) -> str | None:
        """
        将Unicode变体选择器字符反向转换为原始字符。
        :param c: 变体选择器字符
        :return: 对应的原始字符,或None(无效字符)
        """
        cp = ord(c)
        if 0xFE00 <= cp <= 0xFE0F:
            return chr(cp - 0xFE00)
        elif 0xE0100 <= cp <= 0xE01EF:
            return chr((cp - 0xE0100) + 16)
        else:
            return None

    def decode(self, encoded: str) -> str:
        """
        解码隐藏在Unicode变体选择器中的字符串数据。
        :param encoded: 编码后的字符串
        :return: 解码后的原始字符串
        """
        result = []
        for c in encoded:
            char = self.variation_selector_to_char(c)
            if char is not None:
                result.append(char)
            elif result:  # 遇到非变体选择符且已开始解码,终止
                break
        return ''.join(result)


# 使用示例
if __name__ == '__main__':
    base_char = '😊'
    data = 'hello'  # 普通字符串

    # 创建UnicodeDataHider实例
    hider = UnicodeDataHider(base_char)

    # 编码数据
    encoded = hider.encode(data)
    print(f'Encoded: {repr(encoded)}')

    # 解码数据
    decoded = hider.decode(encoded)
    print(f'Decoded: {decoded}')

应用场景与注意事项

  • 隐蔽传输:可在看似正常的文本中隐藏元数据或水印。
  • 兼容性:需确保处理程序保留变体选择器,部分环境可能丢弃不可识别字符。
  • 显示差异:某些渲染器可能忽略变体选择器,导致隐藏数据丢失。

通过巧妙利用Unicode特性,我们实现了数据的隐蔽存储与传输。


http://www.kler.cn/a/551114.html

相关文章:

  • Qt CMake 参考网址
  • 【Zookeeper如何实现分布式锁?】
  • 机器学习实战(4):逻辑回归——分类问题的基础
  • Docker 存储管理:卷、绑定挂载、临时存储
  • 50道题快速复习MySQL之准备篇
  • node的内置对象,vue的内置对象
  • 高通推出骁龙游戏超级分辨率™:充分释放移动游戏性能,带来更持久的续航
  • windows在wsl ubuntu环境中启用cuda加速AI推理和训练
  • 【DeepSeek 行业赋能】从金融到医疗:探索 DeepSeek 在垂直领域的无限潜力
  • UART(一)——UART基础
  • 云贝餐饮连锁V3独立版全开源+vue源码
  • 领克汽车工厂探秘品牌体验方案拆解
  • 蓝桥杯备赛1-2合法日期
  • 一文掌握Docker基础
  • Cloud: aws:network: limit 含有pps这种限制
  • 渲染相机设置 pyrender cameralib
  • AWS上Amazon Redshift用Zoominfo API验证公司基本信息数据正确性检查设计方案
  • 从二维到三维3D工业相机如何改变机器视觉检测
  • vue3项目实践心得-寻找未被使用的最小编号
  • Maven指南-从入门到精通