2016-11-13 38 views
-2

我有代碼:爲ASCII爲什麼哈希結果不同,當應用UTF8功能

push my(@list), $x; 
utf8::upgrade($tmp = $x); push @list, $tmp; 
utf8::downgrade($tmp = $x); push @list, $tmp; 
push @list, Encode::encode_utf8($x); 
push @list, Encode::decode_utf8($x); 

print Digest::SHA::hmac_sha256_hex($_), "\n" for @list 


d9fa76e37bfe94cfcb0011cf070316775e52845021ee92d9bebe8ef289f87e16 
d9fa76e37bfe94cfcb0011cf070316775e52845021ee92d9bebe8ef289f87e16 
d9fa76e37bfe94cfcb0011cf070316775e52845021ee92d9bebe8ef289f87e16 
d9fa76e37bfe94cfcb0011cf070316775e52845021ee92d9bebe8ef289f87e16 
d9fa76e37bfe94cfcb0011cf070316775e52845021ee92d9bebe8ef289f87e16 

爲什麼當$ x是фыва第四哈希值是不同的,PROGRAMM的崩潰:

09165674df9a2eada20acb972bbf71d4cb5637b152d84568fd2e8fcbe9d61188 
09165674df9a2eada20acb972bbf71d4cb5637b152d84568fd2e8fcbe9d61188 
09165674df9a2eada20acb972bbf71d4cb5637b152d84568fd2e8fcbe9d61188 
36cdc4291ac91e26f76a208feb90e8a5a35729d54660bbb63acdb82746f7ec6a 
Wide character in subroutine entry at ./t3.pl line 7. 

請給我一些關於utf8魔法的燈光。謝謝。

UPD

在應用程序,我應該通過檢查體徵檢查數據完整性。有時數據以UTF8格式顯示。在我們不處理這種情況之前。

Digest::SHA::hmac_sha256_hex(Encode::encode_utf8($data)) 

與此同時我檢查,如果我申請這個或那個功能,輸入的數據會是什麼:在這裏,我想檢查後簽收不會改變。

是啊,我不明白UTF8,所以我想問

+3

您誤解了'map'和UTF-8編碼。 'map'是通過對原始列表的每個元素應用相同的規則將一個列表轉換爲另一個列表的工具。它不應該用於其副作用,如打印列表中的每個元素,特別是在丟棄返回的列表時。因此'map {print Digest :: SHA :: hmac_sha256_hex($ _),「\ n」} @ list'可能應該是'print digest :: SHA :: hmac_sha256_hex($ _),「\ n」 。 – Borodin

+1

請注意,如果參數不能用ASCII表示,'utf8 :: downgrade()'將失敗。所以西里爾字符會失敗。另外'Digest :: SHA :: hmac_sha256_hex()'需要參數作爲字節,所以對於寬字符將會失敗。 –

+0

@HåkonHægland奇怪的是,'utf8 :: downgrade()'不會因西里爾字符失敗,正如你所看到的。 –

回答

3

最重要的原因是你沒有理解什麼utf8::downgrade一樣。看看utf8 utility functions

如果你有

use strict; 
use warnings 'all'; 

在你的代碼的頂部的地方,你會看到消息

在子程序入口寬字符

爲線

utf8::downgrade($tmp = $x) 

文檔告訴我們utf8::downgrade

將轉換就地從UTF-8字符串的內部表示,以在本地編碼的等效八位位組序列(Latin-1的或EBCDIC)

您的字符串以ф開頭,即Unicode U+0444CYRILLIC SMALL LETTER EF。在Latin-1或EBCDIC中沒有相應的代碼,因此您的代碼會生成一個您不處理的錯誤Encode模塊,它將在最流行的字符編碼之間進行轉換

+0

perl如何知道字符串應該是字符而不是八位字節? –

+1

@EugenKonkov:有一個內部標誌,表明字符串中的每個字節應該被視爲單個字符還是UTF-8編碼的多字節字符的一部分(擴展名)。你應該讓perl在內部做正確的事情,並確保所有的輸入和輸出都被正確解碼和編碼。極少數情況下,您需要使用多字節編碼的單個字節。 – Borodin

+0

啊。它知道是因爲'utf8 :: downgrade',但它報告了我的代碼行,因爲XS。我應該嘗試不從我的區域設置的utf8符號 –

相關問題