unicode 给世界上所有的语言字符编号,编码方式决定了二进制的序列,hash 函数通过二进制生成散列值,
那么哪天操作系统不采用这种编码方式了,编码出的二进制序列不同,那么散列值也不一样了,那不就解不开压缩报了?
比如中文”我“,使用 utf8 和 GBK 编码出的二进制序列是不一样的,压缩软件是如何判定输入的字符的编码方式的,
是使用操作系统的编码方式吗
不知道描述的对不对,有对编码熟悉的大佬说说吗

压缩和编码是两码事,编码这种东西也只可能出现新的,不可能改老的。

能在短短几行字里聊出那么多认知错误也是不简单

哈哈!

大佬详细说说,就是不懂才问

换新的编码肯定会有新的名字,不可能出出个新的 unicode 完全取代现有的 unicode 然后还叫 unicode ,软件判定或者说计算肯定是基于编码后的二进制内容,不管是什么编码方式不管明文是什么,只要编码后二进制是对的就能解,

你没搞懂的只有一个点。。。unicode 不是一个编码,是一系列编码的统称。。所以 unicode 一般都要先声明自己是哪一套编码。。。

除了上边说的,根据你提到压缩包,以及解压密码,我推测你说的是文件解压缩,文件解压缩和文件内容和编码没太大关系,是在“文件”这个层面上进行解压缩的。

  1. Unicode 字符集: 每个字符对应的码点不会变化(只会添加新的 Code)2. UTF-8/16/32: 是存储方案(编码方案),也不会变化,只会添加对新的 Unicode 字符集版本的支持。3. 压缩软件没有办法知道用的什么格式,要不再元数据携带,要不最终用户告诉它使用的什么编码,要不靠猜测,要不靠诱探。PS: 各个编码方案通过编码表是可以相互转换的,但是很多转换是不可行的,例如 ASCII 的字符集就很小,没法包容 UTF-8 的所有有效字符集。

同样的文字用 Unicode 的确可以有多种表示法,这个在中文里好像很难出现,但是非中文非英文有很多情况所以一般系统的密码都限定了字符集

老哥你的 1 ,2 解答了我对码点和编码的疑惑,但是第三点我很好奇,假设操作系统是 GBK 编码环境,然后软件能拿到操作系统的编码方式,输入到密码框中的数据是 GBK 编码的二进制数据,然后压缩软件把他转化成 utf8 的二进制编码值,然后再散列比对解压缩密码,这种编码的转化过程可能存在吗

你理解错了,操作系统没有编码一说。字符串对操作系统来说是透明的字节序列。操作系统并不关心字节序列到底是什么编码方案,关心编码模式的是应用程序( Application),应用程序自己必须要知道你使用的字符串到底使用的什么编码,否则就无法解析。各个编程语言内置的 string 类型使用的编码都可以是不同的。例如 Python 用的 utf-8, c#/javascript 用的 UTF16 。因此这个属于应用程序需要关心了。例如你是要 C#将一个文件是要 UTF-16 写入文件,在 python 中是要 utf8 去加载这个文件,就会乱码,这个时候 python 加载这个文件必须显示告诉加载方法应该文件是要的是 UTF16 编码,这个时候 python 会将文件是要 utf-16 加载后转码为 utf-8, 从而才能在 python 中正常的处理这个字符串。

另外就是,操作系统本身是由内核+驱动+一堆周边软件构成的。操作系统内核部分的确也有自己的字符串编码模式,但这个和你普通的应用程序没关系,你们也不同共享内存,除非涉及到内核调用和封送。这个时候你就需要关心操作系统内部字符串的格式了。或者你调用一些系统组件,这个时候返回给你的字节序列你必须按照操作系统的编码模式转换为你本地编程语言的字符串使用的编码格式,不知道我这样解释,你理解没有。

总结一下: 这个问题是我在设置压缩包密码时,是否应该用非 ascii 字符引出的,我担心如果未来中文出现新的文字,unicode 码点和字符的映射会发生变化。 一般来讲 ascii 字符 基本不会变化了,英文字母就那几个,中文的可变性太强了,新增文字就意味着新增码点。但是想想 unicode 委员会应该不会范这种低级错误,有点杞人忧天了。但是也不是没有收获,又加深了对编码的理解

另外存在一个叫做码表或者 Encoding 的东西,它可以将不同 Encoding 编码的字节序列做相互转换,例如将一个 byte[] /utf-8 转换为 byte[] utf-16, 字符串内部都使用 byte[]序列表示。获取到一个字节序列后,如果你不知道它究竟是什么编码方案,甚至不知道它不是字符序列,就只能靠探测了。例如 VSCode 默认就会一个探测功能,可以猜测一个文件使用了什么 Encodeing 模式,但是这个探测并不是总是靠谱。

谢谢老哥了,我理解你的意思,我就是好奇字符的编码对应用程序的影响,应用程序是如何应对多语言多编码环境的

压缩软件会在内部使用一个固定的 encoding 模式获取到的密码的 byte[]表示,这个表示在 Encoding 指定值不变的情况下是不会有什么变化的。另外就是 zip 这种压缩编码存在缺陷,的确会又解析错误。例如你在 GB2312 chcp 下压缩一个文件夹,然后在 UTF8 chcp 的另外一个计算机上解码,文件夹就会乱码。因为 zip 这个格式规范并没有存储压缩时候的文件名的字符串编码格式,导致它总是按照操作系统当前的编码来处理字节序列,这回导致文件名这种东西,使用 gb2312 byte 字节存储,却使用 UTF-8 解码,这个时候你就会看到解码后的文件名称错误。这个纯粹是因为 zip 这种文件格式存在缺陷。这种情况你就只能显示的告诉解压软件不要使用操作系统默认编码来解压文件,而是使用你手动指定的编码格式。软件应该避免依赖操作系统的默认编码格式。否则你的软件很可能无法正常在各个不同国家的系统上运行。

但这种粗暴的解决方案有时候也存在问题。因为某些系统,甚至不携带非 ASCII 的码表,也无法显示非 ASCII 编码的字符,这就是另外一个话题了,这些都是历史遗留问题。

赛博求剑?

你说的这个场景我遇到过,之前有 hook 过 app ,遇到 java 的字节流数据,打印出来是一个整数数组,这个时候需要知道它的编码方式才能将他转成可阅读的文本,字节流数据你不知道编码方式,你就不知道是三个字节表示一个字符还是 2 个字节表示一个字符

压缩包只是分发文件的一种方式,而文件就是二进制数据的容器,别人收到压缩包后,解开得到一系列文件,这个文件如何解读是什么完全靠预先定义。比如你收到一个压缩包,作者说编码是 utf-8 ,你解压后就按照 utf-8 编码打开它。或者你发现 gbk 打开乱码了,就尝试用 utf-8 打开也就说压缩是针对二进制数据的操作,编码是对二进制数据的理解方式

谢谢各位老哥的解答,涨姿势了

TLDR:压缩文件的规范应该写明密码的编码方式,不然确实可能会有问题。 题主的提问其实完全没有任何问题,题主是在问非 ASCII 的密码本身的编码方式会不会影响解压缩,而不是被压缩的文件的编码方式会不会影响解压缩。我刚刚用 7-zip 试了一下,7z 格式使用中文密码,在中文 Windows 上压缩,可以正常在 Linux 上解压缩。而 zip 格式不允许非 ASCII 字符作为密码。题主这个问题的答案其实很简单,压缩文件的格式规范里面规定密码的编码方式就行了,比如规定非 ASCII 密码按 UTF-8 来处理就行。我猜测 7z 格式应该就是规定了一种密码的编码方式(简单搜索了一下没搜到,没去读代码验证)。除了密码,其实文件名也有这个问题,我之前研究过。对于 7z 压缩包,压缩和解压缩的时候按照标准会统一按 UTF-16-LE 来处理(参见 py7zr.readthedocs.io/en/latest/archive_format.html#filename ),所以不会有问题。而 zip 格式根本没规定编码,这样不同默认编码的环境创建出来的压缩包就会不兼容,所以 zip 格式经常有文件名乱码问题。对于 rar 格式,文件名是 UTF-8 编码(参见 www.rarlab.com/technote.htm )。而对于被压缩的文件,文件本身就是一串字节,压缩的过程跟编码方式无关,所以不会有任何问题。如果压缩文件的规范里面没有写明密码的编码方式,并且压缩软件的实际实现也忽略了这一点,使用系统的默认编码来把密码文本框里的字符串编码为字节串然后再进行哈希,那确实会导致相同的密码在不同环境下无法正确解压的问题。

程序员区出现这帖子,是耻辱。

#23 怎么耻辱了,我觉得这类问题不论对错都可以探讨探讨,千年虫事件不就是当时程序员觉得不可能吗。

我读了好几遍才大致猜到 OP 的意思,你也可以看下上面的兄弟有多少是没有发现 OP 在讨论“压缩密码使用非 ASCII 的编码问题”,而不是“压缩包内文本文件的编码”或者“压缩包内文件名的编码”的

unicode 也不是编码的统称,它只定义了字符的码点

这种东西肯定会向后兼容的

推荐 20 楼和 25 楼密码就不应该有 ASCII 之外的其他格式

借楼,请教一下,rar 是不是有不同的压缩模式,在密码一样的情况下,用 windows 压缩,会不会 mac 的 unarchived 软件解压不开

可以这样类比:现在我们都用十进制。我记下一个数 114514 。数百年后,人类升级,新人类使用十六进制。那么,我记下的数会被当作十六进制解读,理解为十进制的 1131796 ,从而增大为 9.88 多倍吗?这是个兼容性问题,升级时肯定是要解决的嘛。

#23 千年虫事件的原因,是 1960 年代的程序规则——6 位数表示日期,随着时间的演变到了 2000 年不再适合了。程序员社区,能出现你这种连千年虫事件的浅显原因都不知道的人,那也是耻辱。你这种回复还能收到感谢,那更是耻辱。

我看了一下回复,发现很多人没有理解我的意思,我重新整理一下描述。标题应该改为:”使用非 ascii 字符设置压缩包密码,在未来会不会解不开压缩包,提示解压缩密码不正确“ 这个问题本质上是一个编码问题,要理解为什么是编码问题,需要知道解压缩时,压缩软件是如何比对用户输入的密码的,如此就引出了用户设置的压缩包密码是以”什么形式“存储在压缩包中的,既然存储了,那么就能读取,对于 7-zip 这类开源软件,是可以找到它的压缩逻辑的,那么就可以知道密码在二进制文本的哪个位置。 那么问题来了,你都能读取了,我设置密码意义在哪,这里就引出了”信息摘要算法“,也可以说是”hash 算法”,将文本“映射”为一串不可逆推出原始文本的一串字符,这样就保证了密码的安全性,别人无法从压缩包中提取出你设置的压缩密码。 为什么说这是一个编码问题,这是由于 hash 算法在做 hash 运算的时候,会将你设置的密码文本转化成二进制,然后再做 hash ,文本字符转二进制,这里就引出了编码问题。 ascii 字符集在我看来基本就那样了,不太可能会变动,但是 unicode 字符集就不太一样了,就拿中文来讲,未来可能就会多一个字,多一个字就意味着 unicode 需要将他纳入,新的码点就会产生,我之前担心的是新的码点的产生会不会更改以前码点的值,比如 U+4444 变成 U+4441,加入使用 utf8 编码,对应的二进制值就会发生变化,从而影响 hash 值,导致无法解开压缩包,提示压缩密码错误,这个纯属我胡思乱想。 还有一种顾虑是操作系统编码环境的改变对解开压缩包的影响,比如中国用户 windows 操作系统很多的默认编码是 gbk (我的是,使用 [Console]::OutputEncoding 查看),对于一个中文字符,utf8 使用三个字节,而 gbk 使用两个字节,这就导致同一个中文字符,二进制结果是不一样的,那么 hash值也会不一样,这就意味着操作系统编码环境改变,如果压缩软件不统一对字符的编码,就会导致在不同的系统中解不开压缩包。 这个老哥牛皮,他是真能从官方文档中找到答案

#31 难道不是一个意思?当时的程序员没有想到 2000 年这种跨世纪的情况,有的程序甚至连闰年 29 日都没识别,这就是程序员为了省存储或者考虑不周的失误,咋还被你说成演变了。

我就是来看看有多少人没明白题主的意思..."压缩密码","解不开压缩包",这些关键字看不懂吗?硬是扯到压缩文件编码方式也是厉害.至于答案嘛:不影响.

明白 lz 的意思,我以前用中文当 qq 密码,后来版本更新登陆不上去了,然后找回密码依旧不改,用 alt+小键盘的方式输入中文字,然后后来换了个平台,被坑了,因为只记得编码不记得具体是什么字了,再后来就再也不用这种奇怪的密码。肯定是有影响的,假设文明清零重新开始,那么要复原非 ascii 的难度肯定更大。所以对于不太重要的文件且密码奇葩,估计是真没办法输入密码了