Do anyone know how to translate this code from C# to PHP? private UInt32 seed; private void srand(UInt32 newSeed) { seed = newSeed; } private UInt32 rand() { seed = ((0x41c64e6d * seed + 0x6073)) & 4294967295L; return seed >> 16; } private void encrypt(bool inbag, byte[] pks2) { UInt32 pid = 0; UInt16 checksum = 0; pid = BitConverter.ToUInt32(pks2, 0); checksum = BitConverter.ToUInt16(pks2, 6); int order = (pid >> (13) & 31) % 24; string firstblock = null; string secondblock = null; string thirdblock = null; string fourthblock = null; switch (order) { case 0: firstblock = "A"; secondblock = "B"; thirdblock = "C"; fourthblock = "D"; break; case 1: firstblock = "A"; secondblock = "B"; thirdblock = "D"; fourthblock = "C"; break; case 2: firstblock = "A"; secondblock = "C"; thirdblock = "B"; fourthblock = "D"; break; case 3: firstblock = "A"; secondblock = "C"; thirdblock = "D"; fourthblock = "B"; break; case 4: firstblock = "A"; secondblock = "D"; thirdblock = "B"; fourthblock = "C"; break; case 5: firstblock = "A"; secondblock = "D"; thirdblock = "C"; fourthblock = "B"; break; case 6: firstblock = "B"; secondblock = "A"; thirdblock = "C"; fourthblock = "D"; break; case 7: firstblock = "B"; secondblock = "A"; thirdblock = "D"; fourthblock = "C"; break; case 8: firstblock = "B"; secondblock = "C"; thirdblock = "A"; fourthblock = "D"; break; case 9: firstblock = "B"; secondblock = "C"; thirdblock = "D"; fourthblock = "A"; break; case 10: firstblock = "B"; secondblock = "D"; thirdblock = "A"; fourthblock = "C"; break; case 11: firstblock = "B"; secondblock = "D"; thirdblock = "C"; fourthblock = "A"; break; case 12: firstblock = "C"; secondblock = "A"; thirdblock = "B"; fourthblock = "D"; break; case 13: firstblock = "C"; secondblock = "A"; thirdblock = "D"; fourthblock = "B"; break; case 14: firstblock = "C"; secondblock = "B"; thirdblock = "A"; fourthblock = "D"; break; case 15: firstblock = "C"; secondblock = "B"; thirdblock = "D"; fourthblock = "A"; break; case 16: firstblock = "C"; secondblock = "D"; thirdblock = "A"; fourthblock = "B"; break; case 17: firstblock = "C"; secondblock = "D"; thirdblock = "B"; fourthblock = "A"; break; case 18: firstblock = "D"; secondblock = "A"; thirdblock = "B"; fourthblock = "C"; break; case 19: firstblock = "D"; secondblock = "A"; thirdblock = "C"; fourthblock = "B"; break; case 20: firstblock = "D"; secondblock = "B"; thirdblock = "A"; fourthblock = "C"; break; case 21: firstblock = "D"; secondblock = "B"; thirdblock = "C"; fourthblock = "A"; break; case 22: firstblock = "D"; secondblock = "C"; thirdblock = "A"; fourthblock = "B"; break; case 23: firstblock = "D"; secondblock = "C"; thirdblock = "B"; fourthblock = "A"; break; } int z = 0; int v = 8; //Block A UInt16[] blocka = new UInt16[17]; while (z < 16) { blocka[z] = BitConverter.ToUInt16(pks2, v); z = z + 1; v = v + 2; } z = 0; v = 40; //Block B UInt16[] blockb = new UInt16[17]; while (z < 16) { blockb[z] = BitConverter.ToUInt16(pks2, v); z = z + 1; v = v + 2; } z = 0; //Block C v = 72; UInt16[] blockc = new UInt16[17]; while (z < 16) { blockc[z] = BitConverter.ToUInt16(pks2, v); z = z + 1; v = v + 2; } z = 0; //Block D UInt16[] blockd = new UInt16[17]; v = 104; while (z < 16) { blockd[z] = BitConverter.ToUInt16(pks2, v); z = z + 1; v = v + 2; } z = 0; UInt16[] inbagb = new UInt16[43]; v = 136; z = 0; while (z < 42) { inbagb[z] = BitConverter.ToUInt16(pks2, v); z = z + 1; v = v + 2; } z = 0; srand(checksum); UInt16[] byter = new UInt16[17]; z = 0; v = 8; switch (firstblock) { case "A": while (z < 16) { byter[z] = blocka[z] ^ rand(); z = z + 1; } break; case "B": while (z < 16) { byter[z] = blockb[z] ^ rand(); z = z + 1; } break; case "C": while (z < 16) { byter[z] = blockc[z] ^ rand(); z = z + 1; } break; case "D": while (z < 16) { byter[z] = blockd[z] ^ rand(); z = z + 1; } break; } z = 0; v = 8; while (z < 16) { pks2[v] = byter[z] & 255; pks2[v + 1] = byter[z] >> 8; z = z + 1; v = v + 2; } z = 0; v = 40; switch (secondblock) { case "A": while (z < 16) { byter[z] = blocka[z] ^ rand(); z = z + 1; } break; case "B": while (z < 16) { byter[z] = blockb[z] ^ rand(); z = z + 1; } break; case "C": while (z < 16) { byter[z] = blockc[z] ^ rand(); z = z + 1; } break; case "D": while (z < 16) { byter[z] = blockd[z] ^ rand(); z = z + 1; } break; } z = 0; while (z < 16) { pks2[v] = byter[z] & 255; pks2[v + 1] = byter[z] >> 8; z = z + 1; v = v + 2; } z = 0; v = 72; switch (thirdblock) { case "A": while (z < 16) { byter[z] = blocka[z] ^ rand(); z = z + 1; } break; case "B": while (z < 16) { byter[z] = blockb[z] ^ rand(); z = z + 1; } break; case "C": while (z < 16) { byter[z] = blockc[z] ^ rand(); z = z + 1; } break; case "D": while (z < 16) { byter[z] = blockd[z] ^ rand(); z = z + 1; } break; } z = 0; while (z < 16) { pks2[v] = byter[z] & 255; pks2[v + 1] = byter[z] >> 8; z = z + 1; v = v + 2; } z = 0; v = 104; switch (fourthblock) { case "A": while (z < 16) { byter[z] = blocka[z] ^ rand(); z = z + 1; } break; case "B": while (z < 16) { byter[z] = blockb[z] ^ rand(); z = z + 1; } break; case "C": while (z < 16) { byter[z] = blockc[z] ^ rand(); z = z + 1; } break; case "D": while (z < 16) { byter[z] = blockd[z] ^ rand(); z = z + 1; } break; } z = 0; while (z < 16) { pks2[v] = byter[z] & 255; pks2[v + 1] = byter[z] >> 8; z = z + 1; v = v + 2; } z = 0; //inbag v = 136; if (inbag == true) { srand(pid); z = 0; UInt16[] inbagbytes = new UInt16[43]; while (z < 42) { inbagbytes[z] = (inbagb[z]) ^ (rand()); z = z + 1; } z = 0; v = 136; while (z < 42) { pks2[v] = inbagbytes[z] & 255; pks2[v + 1] = inbagbytes[z] >> 8; z = z + 1; v = v + 2; } } z = 0; return pks2; } Code (markup): Your help will be appreciated!
Not exactly rocket science -- mostly it's just a matter of stripping out all the typecasting, putting $ before all variable names, and making sure since this appears to be using bitwise operations that you strip off any excess data since php has no strict/predictable typecasting rules. Though... damn that's some ugly C code given the "long form" maths, completely pointless 'sRand function... pointless zero assignments on declarations when it's set to a value after... Also the bitConverter class might be a bit tricky to deal with since that's an oddball typecasting function specific to C# that other languages would have no equivalent. Byte-wise operations and PHP aren't exactly buddies with PHP's complete lack of pointers and proper typecasting. I'm also seeing a lot of uninitialized values in there -- so I'm skeptical the original code would even work right, though I'm not as well versed in C# as I probably should be. I'm on the laptop right now, but when I'm back at my workstation I'll see if I can at least get you started on this... though again I'm not convinced the original code actually works given a few... faux-pas in the code like not initializing the values in certain array elements. Rewriting the original to make it a HELL of a lot less code would also probably be a good start.
I tossed together a rewrite, this SHOULD be functionally identical, but don't hold me to that as the original was... well... very poorly written. class encrypt { private static $encryptSeed=0, // lookup table faster and easier than massive switch statement $encryptOrders = [ [0,1,2,3],[0,1,3,2],[0,2,1,3],[0,2,3,1],[0,3,1,2],[0,3,2,1], [1,0,2,3],[1,0,3,2],[1,2,0,3],[1,2,3,0],[1,3,0,2],[1,3,2,0], [2,0,1,3],[2,0,3,1],[2,1,0,3],[2,1,3,0],[2,3,0,1],[2,3,1,0], [3,0,1,2],[3,0,2,1],[3,1,0,2],[3,1,2,0],[3,2,0,1],[3,2,1,0] ], $inData, $result; public static function doIt( $inBag, &$data ) { // make private pointer for subroutine use self::$inData = &$data; // copy first ten bytes as they are unchanged self::$result=subStr($data,0,10); $pid = self::readWord(0); $order = self::$encryptOrders[(($pid >> 13) & 31) % 24]; self::$encryptSeed = self::readWord(6); // checksum for ($t=0; $t<3; $t++) self::encryptBlock( 8 + 32 * $order[$t], 16 ); if ($inBag) { self::$encryptSeed = $pid; self::encryptBlock( 136, 42); $t=178; } else $t=136; // copy any extra data at end unchanged if ($t<strlen($data)) self::$result.=subStr($data,$t); return self::$result; } // method doIt private static function encryptRand() { self::$encryptSeed = ( (0x41c64e6d * self::$encryptSeed + 0x6073) ) & 4294967295; return self::$encryptSeed >> 16; } // method encryptRand private static function readByte( $start ) { return ( (ord(self::$inData[$start]) << 8) + ord(self::$inData[$start+1]) ); } // method readByte private static function readWord( $start ) { return ( (ord(self::$inData[$start]) << 24) + (ord(self::$inData[$start+1]) << 16) + (ord(self::$inData[$start+2]) << 8) + ord(self::$inData[$start+3]) ); } // method readWord private static function encryptBlock( $read, $count ) { $end = $read + ($count * 2); do { $temp = self::readByte($read) ^ self::encryptRand(); self::$result.=chr($temp & 0x00FF); self::$result.=(chr($temp >>8) & 0x00FF); $read += 2; } while ($read < $end); } // method encryptBlock } // class encrypt Code (markup): made it a singleton, so everything is nice and contained in it's own namespace. If you had some sample before and after data, I'd be able to dial in better if I'm even CLOSE to deciphering the original's purpose.
Unfourtunately I cannot upload the file, but here is the file content in hex ENCRYPTED: 87 4B FE 0C 00 00 5F 0F 6A 07 B2 AA 6F 5F 73 18 57 72 B8 6A 6C 68 BB 74 E0 90 3E 5F 6E 5C 97 15 5C 09 39 51 C4 3E 85 0B 88 D3 B2 60 36 3F 11 77 65 BA 1B E1 D7 F7 3C 09 63 C1 B7 5D E1 B7 8E 7C 90 ED DB 93 92 C2 76 76 58 3B 1C 8E 30 D1 8E 2D F0 C7 42 22 3D DA 56 B9 06 2F A7 FA 4A 21 02 33 B1 FA 68 B8 B2 5B 91 2E 32 0C 5C 65 14 79 01 6E 02 3A 43 B8 FC 47 F3 D1 3F 8C 3B D6 0D 74 1E 2E E8 75 56 C0 0E 9B D2 8A BEFORE: 87 4B FE 0C 00 00 5F 0F 3D 00 3A 01 2A 2C 63 F3 14 2C 10 00 FF 06 00 02 55 55 55 55 55 55 00 00 00 00 00 00 00 00 00 00 AA 01 38 00 66 01 BB 00 0A 05 0A 0A 00 00 00 00 FF FF FF 3F 00 00 00 00 00 15 00 00 00 00 00 00 52 00 61 00 6E 00 65 00 FF FF 00 00 A1 48 02 0C FF E0 FF FF FF FF 00 04 00 00 00 00 00 00 00 00 45 00 53 00 47 00 FF FF 00 00 00 00 00 00 FF FF 00 00 00 0B 03 06 00 00 00 00 00 04 1F 00 00 00