php 从非拉丁字符和不同编码中获得相同的哈希结果[已关闭]

ogsagwnx  于 2023-06-21  发布在  PHP
关注(0)|答案(1)|浏览(105)

已关闭,此问题需要更focused。目前不接受答复。
**想改善这个问题吗?**更新问题,使其仅通过editing this post关注一个问题。

5天前关闭。
Improve this question
我有2个PHP文件,内容相同,唯一的区别是编辑器设置的文件编码-一个是ANSI,另一个是UTF-8,没有BOM。
当我对只包含拉丁字符的同一个字符串进行散列时,我从两个文件中得到相同的结果,但是如果字符串包含西里尔字符,我从两个文件中得到不同的散列值。
下面是一个拉丁字符的例子:
echo md5('text');
这两个文件都生成字符串1cb251ec0d568de6a929b520c4aed8d1
下面是两个文件都包含西里尔字符的例子:
echo md5('текст');
ANSI文件的结果为91929cf468f2b1210df40a036d4c9d83,UTF文件的结果为64ffe1bae8047554de614e1dc0553602
我使用md5作为最简单的例子,但其他哈希算法如sha 512的行为完全相同。

所以,我的问题是-有没有一种方法可以将字符串转换为无论编码方式如何都始终相同的字符串,然后再进行散列?

我希望base64_encode可能会有所帮助,但它也会产生不同的值。
我想使用一个转换编码的函数可能会起作用,但我更喜欢不依赖于编码的解决方案(如果可能的话)。
我的另一个想法是创建一个音译函数,将西里尔字符转换为拉丁文,但如果有人决定使用其他非拉丁字符,并且将用户限制为拉丁字符,这也是一个不可取的解决方案。
我知道现在我应该在任何地方使用UTF-8,但在10-15年内,它可能会被其他东西取代,我希望散列数据尽可能可移植。我已经遇到过类似的麻烦,试图将数据从早在UTF-8成为主流之前编写的旧代码迁移到UTF-8。

//编辑:

只是为了澄清-我不期望md5('text');md5('текст');将返回相同的哈希!
我期望md5('текст');将以与md5('text');相同的方式在两个不同的文件中以两种不同的编码返回相同的散列。

//编辑2:

建议的将编码转换为UTF-8的解决方案并不是我想要的。我的问题是,在未来的UTF-8可能会被其他东西取代,如果我需要使代码与新的东西兼容,我不会有原始数据,但只有哈希,他们不会与新的东西兼容。
例如,如果我使用哈希来存储密码,而代码使用的是取代UTF-8的新编码,而有人用他们的密码登录,那么在比较过程中会产生不同的哈希。
所以,我的问题更像是,在对字符串进行散列之前,是否可以有一个与编码无关的字符串表示。

不幸的是,我想我在shingo提供的zend.multibyte文档链接中找到了答案。

ISO-8859-1兼容编码(如UTF-8、EUC等)不需要此选项。
如果我的假设是正确的,我的测试设置中的拉丁字符会产生相同的哈希,因为ISO-8859-1(最有可能用于拉丁字符)和UTF-8是兼容的,但ISO-8859-1与西里尔字符不兼容,而是使用了其他与UTF-8不兼容的东西,如CP-1251。
感谢所有试图提供帮助的人,如果版主认为这个问题毫无意义,请删除它。

olmpazwi

olmpazwi1#

程序几乎不可能检测到编码,引用mb_detect_encoding的描述:
自动检测预期的字符编码永远不可能完全可靠;在没有一些附加信息的情况下,它类似于在没有密钥的情况下对加密的字符串进行解码。
没有神奇的和简单的解决方案。要解决这个问题,您需要告诉PHP脚本的编码方式。
1.在 * php.ini * 中打开zend.multibyte

zend.multibyte = On

1.仍然在 * php.ini * 中给予选项zend.script_encoding一个默认值

zend.script_encoding = UTF-8

1.检查所有的PHP脚本,如果它不是用UTF-8编码的,你需要通过添加一个声明结构来指定编码

<?php declare(encoding='ISO-8859-5'); #Cyrillic
echo md5('текст'), PHP_EOL;

现在,当脚本运行时,其中的文字字符串将转换为默认编码。
这只解决了脚本中的字符串。如果字符串来自代码外部,您仍然需要手动处理编码问题。

相关问题