2012-07-19 53 views
2

我正在將一個簡單的C++函數移植到Javascript中,但似乎我遇到了JavaScript處理按位運算符的問題。與C++相比,Javascript中的按位XOR

在C++:

AnsiString MyClass::Obfuscate(AnsiString source) 
{ 
    int sourcelength=source.Length(); 
    for(int i=1;i<=sourcelength;i++) 
    { 
     source[i] = source[i]^0xFFF; 
    } 
    return source; 
} 

模糊處理( 「測試」)得到臨時intvalues

-117, -102, -116, -117 

模糊處理( 「測試」)得到stringValue的

‹šŒ‹ 

在Javascript中:

function obfuscate(str) 
{ 
    var obfuscated= ""; 
    for (i=0; i<str.length;i++) { 

     var a = str.charCodeAt(i);     
     var b = a^0xFFF; 
     obfuscated= obfuscated+String.fromCharCode(b); 
    } 
    return obfuscated; 
}  

模糊處理( 「測試」)得到臨時intvalues

3979 , 3994 , 3980 , 3979 

模糊處理( 「測試」)得到stringValue的

ྋྚྌྋ 

現在,我認識到,有一噸的線程,其中的他們指出Javascript將所有數字視爲浮動數據,而按位操作則將臨時數據轉換爲32位整數。

這真的不會是一個問題,除了我在Javascript中進行混淆和在C++中進行反轉,並且不同的結果並不匹配。

我如何將Javascript結果轉換爲C++結果?有一些簡單的轉變嗎?

+1

這可能不是問題,但你墮入* [隱全局的恐怖(http://blog.niftysnippets.org/2008/03/horror-of- implicit-globals.html)*:你需要聲明你的''''變量。 – 2012-07-19 14:42:02

+0

我沒有注意到。謝謝。 – petrobrush 2012-07-20 12:21:46

回答

4

Working demo

從結果異或1160xFFF給人-117來看,我們要仿效在JavaScript 2的補數8位整數:

function obfuscate(str) 
{ 
    var bytes = []; 
    for (var i=0; i<str.length;i++) { 
     bytes.push((((str.charCodeAt(i)^0xFFF) & 0xFF)^0x80) -0x80); 
    } 
    return bytes; 
} 

好這些字節解釋在Windows CP 1252,如果它們是負數,可能只是從256中減去。

var ascii = [ 
    0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F 
    ,0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F 
    ,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F 
    ,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F 
    ,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F 
    ,0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F 
    ,0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F 
    ,0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F 
]; 

var cp1252 = ascii.concat([ 
    0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD 
    ,0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,0x02DC,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178 
    ,0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF 
    ,0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF 
    ,0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF 
    ,0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF 
    ,0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF 
    ,0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF 
]); 

function toStringCp1252(bytes){ 
    var byte, codePoint, codePoints = []; 
    for(var i = 0; i < bytes.length; ++i) { 
     byte = bytes[i]; 
     if(byte < 0) { 
      byte = 256 + byte; 
     } 
     codePoint = cp1252[byte]; 
     codePoints.push(codePoint); 

    } 

    return String.fromCharCode.apply(String, codePoints); 
} 

結果

toStringCp1252(obfuscate("test")) 
//"‹šŒ‹" 
+0

雖然這是一個正確和可用的答案,但我不知道如何擴展這個,用於幾個XOR操作。見[這jfiddle。](http://jsfiddle.net/5HSQ3/6/) – petrobrush 2012-07-20 12:14:17

+1

@petrobrush這是否給予預期的結果? http://jsfiddle.net/5HSQ3/8/,它導致了未定義的CP1252字符,我的Cp1252函數用'0xFFFD'( )unicode替換字符替代。我需要查看原始結果才能知道如何處理常規CP1252字符。請參閱http://en.wikipedia.org/wiki/CP-1252灰色框 – Esailija 2012-07-20 12:18:30

+0

@petrobrush這裏是相同的jsfiddle,記錄多個異或操作的中間字節結果http://jsfiddle.net/5HSQ3/9/ – Esailija 2012-07-20 12:19:25

0

首先,將您的AnsiString轉換爲wchar_t*。只有這樣,混淆其單個字符:

AnsiString MyClass::Obfuscate(AnsiString source) 
{ 
    /// allocate string 
    int num_wchars = source.WideCharBufSize(); 
    wchar_t* UnicodeString = new wchar_t[num_wchars]; 
    source.WideChar(UnicodeString, source.WideCharBufSize()); 

    /// obfuscate individual characters 
    int sourcelength=source.Length(); 
    for(int i = 0 ; i < num_wchars ; i++) 
    { 
     UnicodeString[i] = UnicodeString[i]^0xFFF; 
    } 

    /// create obfuscated AnsiString 
    AnsiString result = AnsiString(UnicodeString); 

    /// delete tmp string 
    delete [] UnicodeString; 

    return result; 
} 

對不起,我不是C++ Builder的專家,但我的觀點很簡單:在JavaScript中你有WCS2符號(或UTF-16),所以你必須轉換AnsiString首先是寬字符。

嘗試使用的WideString代替AnsiString

+0

我懷疑這是否行得通,因爲unicode字符串將包含12位字符,並將其填充到8位值的數組中...... – 2012-07-19 14:52:04

1

我假定AnsiString是在某種形式的char秒的陣列。這就是問題所在。在,char通常只能保持8位。因此,當您與0xfff異或,並將結果存儲在char中時,它與0xff異或。

並非如此。使用Unicode的JavaScript。這證明通過觀察整數值:

-117 == 0x8b3979 == 0xf8b

我會建議用異或作爲0xff這兩種語言。或者您可以將您的代碼切換爲使用Unicode。

+0

它看起來像一箇舊的C++ Builder類庫,帶有一些自定義的AnsiString/WideString類。這絕對是char的大小,我只是不確定有多少位,我沒有訪問C++ Builder的權限。 – 2012-07-19 14:57:20

1

我在猜測AnsiString包含8位字符(因爲ANSI字符集是8位)。當您將XOR的結果分配回字符串時,它將被截斷爲8位,因此結果值在[-128 ... 127]範圍內。因爲沒有指定char是有符號還是無符號,或者是8位還是更大,所以在某些平臺上,它可以是[0..255],而在其他平臺上,範圍可以更寬。

Javascript字符串包含unicode字符,它可以保存更寬範圍的值,結果不會被截斷爲8位。 XOR的結果將有至少12位的範圍,[0 ... 4095],因此您在那裏看到的數字很大。

假設原始字符串只包含8位字符,則將操作更改爲a^0xff應該在兩種語言中給出相同的結果。

0

我根本不知道AnsiString,但我的猜測是這與它的字符寬度有關。具體來說,我懷疑它們的寬度小於32位,當然在按位操作中,這是你操作的寬度,特別是在處理2的補碼時。

在JavaScript中,您的"t""test"是字符代碼116,它是b00000000000000000000000001110100。 0xFFF(4095)是b00000000000000000000111111111111,你得到的結果(3979)是b00000000000000000000111110001011。我們可以很容易地看到你得到正確的結果爲XOR:

116 = 00000000000000000000000001110100 
4095 = 00000000000000000000111111111111 
3979 = 00000000000000000000111110001011

所以我想你要在你的C一些截斷或類似++代碼,不只是因爲-117是b10001011八位2的補碼......這正是我們所看到的3979以上的最後八位。