2012-07-20 23 views
3

用不同的編碼編碼的兩個不同的字符串可以有相同的字節序列嗎?當使用兩種不同的編碼 (Cp1252和UTF-8僅僅是示例)進行編碼時,下面的例子中的一些「字符串1」和「字符串2」將導致測試通過?用不同的編碼編碼時,兩個不同的字符串可以具有相同的字節序列嗎?

import java.io.UnsupportedEncodingException; 
import java.util.Arrays; 

import org.junit.Assert; 
import org.junit.Test; 

public class EncodingTest { 
    @Test 
    public void test() throws UnsupportedEncodingException { 
     final byte[] sequence1 = "string one".getBytes("Cp1252"); 
     final byte[] sequence2 = "string two".getBytes("UTF-8"); 
     Assert.assertTrue(Arrays.equals(sequence1, sequence2)); 
    } 
} 

在我的代碼中的錯誤散列從JVM的默認編碼字符串生成的字節序列,我需要驗證是否當代碼與不同的字符串和不同的JVM文件編碼運行,將導致哈希衝突(可例如,在Windows和Linux上運行時發生)。

由於編碼是字節序列和字符之間的映射,我認爲可能有一些字符串和編碼通過上述測試。但只是想知道是否有任何衆所周知的例子或一些很好的理由,爲什麼我不應該依賴沒有發生散列衝突。

感謝

PS:這僅僅是通過JDK 1.6支持的編碼,而不是由一些彌補的。

+0

使用「默認編碼」往往是..懷疑。 – 2012-07-20 02:01:33

+1

請注意,這個問題是要求*反*什麼答案是響應;如果兩個相同的**字符串具有不同的編碼可以生成相同的字節序列*,那麼它不是要求具有不同編碼的兩個**不同**字符串能夠生成相同的字節序列*。 (更具體地說,如果存在這種碰撞的「已知情況」)。 – 2012-07-20 02:03:29

+0

爲什麼散列碰撞很重要?哈希碼不需要是唯一的。 – jtahlborn 2012-07-20 03:23:28

回答

2

是的。舉一個簡單的例子,編碼爲ISO-8859-1的字符串「¡」(倒置的感嘆號)和字符串「Ą」(大寫字母A與字母編碼)編碼爲ISO-8859-2都成爲單字節序列A1(十六進制)。當使用將字符映射到單個字節的非常簡單的編碼時,或多或少會發生這種情況;否則它們不會是不同的編碼。當涉及更復雜的編碼方案時,它肯定會發生。

1

下面是一個簡單的例子:大多數代碼頁和UTF-8共享ASCII編碼(0x00 = 0x7F)。如果你的文本是純英文的,那麼很有可能它是ASCII格式 - 不管聲明的編碼是什麼,因爲它會使用大多數普通的非重音字符。

+1

這是如何導致兩個不同的輸入字符串以getBytes()的相同字節結束的? – 2012-07-20 02:01:53

1

如果源字符串是支持多字節字符的編碼,而目標編碼是不支持多字節字符的編碼,那麼由於多字節字符需要映射到單字節字符集。

例如,如果輸入字符串是用中文書寫的,而目標字符集是US-ASCII,則許多中文字符肯定會映射到相同的US-ASCII表示。

1

是的,至少對於不同長度的琴絃是可能的。

字符串"\u2020"(或"†")以UTF-16編碼爲0x20,0x20。這也是ASCII碼中的"\x20\x20"(兩個ASCII空格的字符串)編碼的結果。

當然,The Dagger,經常沒有用語言表達[=^_^=],但是一些標準的[非拉丁字母]字母可以生成類似的字節序列,映射到標準(非對照字符)ASCII編碼..以及更多如果有關控制字符的限制放寬。

這將是更有趣的尋找到兩個類似的「現實主義」的字符串(例如相同的長度和「敏感數據」)可以映射到不同編碼相同的字節序列的情況下..

1

此代碼最終應生成一個示例:

while(true){ 
     Random r = new Random(); 
     byte[] bytes = new byte[4]; 
     r.nextBytes(bytes); 
     try{ 
      String raw = Arrays.toString(bytes); 
      String utf8 = new String(bytes, "UTF-8"); 
      String latin1 = new String(bytes, "ISO-LATIN-1"); 
      System.out.println(raw + " is " + utf8 + " or " + latin1); 
      break; 
     }catch(Exception e){} 
    } 
相關問題