Lock2Key
Материал из MyDC's Wiki
Описание
Реализация в различных языках функции Lock2Key для нахождения ключа по параметру команды $Lock. Для построения ключа используется код, который находится в команде $Lock непосредственно между $Lock и Pk
$Lock {код} Pk={пк}|
Язык С/C++
char *lock2key(char *lock) { int len = strlen(lock); char *key = (char *)calloc(1, len + 1); int i; for(i = 1; i < len; ++i) key[i] = lock[i] ^ lock[i-1]; key[0] = lock[0] ^ lock[len-1] ^ lock[len-2] ^ 5; for(i = 0; i < len; ++i) key[i] = ((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F); char *newkey = (char *)calloc(1, len + 100); char *newkey_p = newkey; for(i = 0; i < len; ++i) { switch(key[i]) { case 0: case 5: case 36: case 96: case 124: case 126: sprintf(newkey_p, "/%%DCN%03d%%/", key[i]); newkey_p += 10; break; default: *newkey_p = key[i]; ++newkey_p; } } *newkey_p = '\0'; return newkey; }
Язык C++
/// DCN экранирование void DCN_Escape(const char *sBuf, int iLen, string &sDest) { sDest.clear(); unsigned char c; char buf[11]; while(iLen-- > 0) { c = *(sBuf++); switch(c) { case 0: case 5: case 36: case 96: case 124: case 126: sprintf(buf, "/%%DCN%03d%%/", c); sDest += buf; break; default: sDest += c; break; } } } /// DCN разэкранирование void DCN_UnEscape(const string &sSrc, char *sDest, int &iLen) { string sStart = "/%DCN", sEnd = "%/"; unsigned char c; size_t iPos = sSrc.find(sStart), iPos2 = 0; iLen = 0; while((iPos != sSrc.npos) && (iLen < sSrc.size())) { if(iPos > iPos2) { memcpy(sDest + iLen, sSrc.c_str() + iPos2, iPos - iPos2); iLen += iPos - iPos2; } iPos2 = sSrc.find(sEnd, iPos); if((iPos2 != sSrc.npos) && (iPos2 - iPos <= sStart.size() + 3)) { c = atoi(sSrc.substr(iPos + sStart.size(), 3).c_str()); sDest[iLen++] = c; iPos2 += sEnd.size(); } iPos = sSrc.find(sStart, iPos + 1); } if (iPos2 < sSrc.size()) { memcpy(sDest + iLen, sSrc.c_str() + iPos2, sSrc.size() - iPos2 + 1); iLen += sSrc.size() - iPos2; } } /// Функция кодирования void lock2key(const string &sLock, string &sKey) { int iCount = 0, iLen = sLock.size(); char *key = 0, *lock = new char[iLen + 1]; DCN_UnEscape(sLock, lock, iLen); key = new char[iLen + 1]; key[0] = lock[0] ^ lock[iLen - 1] ^ lock[iLen - 2] ^ 5; while(++iCount < iLen) key[iCount] = lock[iCount] ^ lock[iCount - 1]; key[iLen] = 0; iCount = -1; while(++iCount < iLen) key[iCount] = ((key[iCount] << 4)) | ((key[iCount] >> 4)); DCN_Escape(key, iLen, sKey); delete [] key; delete [] lock; }
Язык C#
private static string lock2key(string Lock) { int i, len = Lock.Length; byte[] key = new byte[len]; for(i = 1; i < len; ++i) key[i] = (byte)(Lock[i] ^ Lock[i - 1]); key[0] = (byte)(Lock[0] ^ Lock[len - 1] ^ Lock[len - 2] ^ 5); for(i = 0; i < len; ++i) key[i] = (byte)(((key[i] << 4) & 0xF0) | ((key[i] >> 4) & 0x0F)); string Buf = "", Key = Encoding.Default.GetString(key); for(i = 0; i < len; ++i) switch((int)Key[i]) { case 0: case 5: case 36: case 96: case 124: case 126: Buf += String.Format("/%DCN{0:000}%/", (int)Key[i]); break; default: Buf += Key[i]; break; } return Buf; }
Язык Lua (5.1)
function lock2key(lock) local function bitwise(x, y, bw) local c, p = 0, 1 local function bODD(x) return x ~= math.floor(x / 2) * 2 end while x > 0 or y > 0 do if bw == "xor" then if (bODD(x) and not bODD(y)) or (bODD(y) and not bODD(x)) then c = c + p end elseif bw == "and" then if bODD(x) and bODD(y) then c = c + p end elseif bw == "or" then if bODD(x) or bODD(y) then c = c + p end end x = math.floor(x / 2) y = math.floor(y / 2) p = p * 2 end return c end local key = {} table.insert(key, bitwise(bitwise(bitwise(string.byte(lock, 1), string.byte(lock, -1), "xor"), string.byte(lock, -2), "xor"), 5, "xor")) for i=2, string.len(lock),1 do table.insert(key, bitwise(string.byte(lock, i), string.byte(lock, i - 1), "xor")) end local function nibbleswap(bits) return bitwise(bitwise(bits * (2 ^ 4), 240, "and"), bitwise(math.floor(bits / (2 ^ 4)), 15, "and"), "or") end local g = {["5"] = 1, ["0"] = 1, ["36"] = 1, ["96"] = 1, ["124"] = 1, ["126"] = 1} for i=1, #key do local b = nibbleswap(rawget(key, i)) rawset(key, i, (g[tostring(b)] and string.format("/%%DCN%03d%%/", b) or string.char(b))) end return table.concat(key) end
Язык PHP
function lock2key($_LOCK) { $lockLength = strlen($_LOCK); $LockToKey = ''; for ($j = 0; $j < strlen($_LOCK); $j++) { if($j == 0) { $h = ord($_LOCK{0}) ^ ord( $_LOCK{ $lockLength - 1} ) ^ ord( $_LOCK{ $lockLength - 2} ) ^ 5; } else { $h = ord($_LOCK{$j}) ^ ord($_LOCK{$j-1}); } $h = $h % 256; $a = (($h<<4) & 240) | (($h>>4) & 15); if($a == '126' or $a == '124' or $a == '96' or $a == '36' or $a == '5' or $a == '0') { $LockToKey .= "/%DCN"; if ($a < 100) $LockToKey .= "0"; if ($a < 10) $LockToKey .= "0"; $LockToKey .= $a; $LockToKey .= "%/"; } else { $LockToKey .= chr($a); } } return $LockToKey; }
Язык Perl
sub lock2key($) { my @lock = split(//, shift); my $i; my @key = (); # convert to ordinal map {$_=ord} @lock; # calc key[0] with some xor-ing magic push(@key,$lock[0]^5); # calc rest of key with some other xor-ing magic for ($i=1;$i<@lock;$i++) { push(@key, ($lock[$i]^$lock[$i-1])); } # nibble swapping for ($i=0;$i<@key;$i++) { $key[$i] = ((($key[$i] << 4) & 240) | (($key[$i] >> 4) & 15)) & 0xff; } $key[0] = $key[0] ^ $key[ @key - 1 ]; # escape some foreach (@key) { $_ = ( $_ == 0 || $_ == 5 || $_ == 36 || $_ == 96 || $_ == 124 || $_ == 126 ) ? sprintf('/%%DCN%03i%%/', $_) : chr; } # done return join('', @key); }
Язык Delphi / Pascal
function lock2key(StrLock : string) : string; // The follow function converts "1" (byte) to "001" (string), "10" to "010" and so on function ByteToThreeCharStr (Value : byte) : string; begin if value < 10 then result := '00'+inttostr(value) else if value < 100 then result := '0'+inttostr(value) else result := inttostr(value); end; var i : byte; Temp : string; TempChar : byte; begin result := ''; if length (StrLock) < 3 then begin result := 'BROKENCLIENT'; setlength (result,length(strlock)); exit; end; // First char temp := chr (ord (StrLock[1]) xor ord (StrLock[length(StrLock)]) xor ord (StrLock[length(strLock)-1]) xor 5); for i := 2 to length (StrLock) do temp := temp + chr (ord(StrLock[i]) xor ord (StrLock[i-1])); for i := 1 to length (temp) do begin TempChar := ord (temp[i]); // I now used assembler. In the visual basic code the same was done with ugly math asm // <- Nibble swap! We swap the last four // bits with the first four: 00101111 -> 11110010 ror TempChar, 4 end; // Some chars need to be replaced with a string like "/%DCN005%/" If (TempChar = 0) or (TempChar = 5) or (TempChar = 36) or (TempChar = 96) or (TempChar = 124) or (TempChar = 126) then result := result + '/%DCN' + ByteToThreeCharStr(TempChar) + '%/' else result := result + chr (TempChar); end; end;
Язык Java
class Utils { private static final String CHARENCODING = "windows-1252"; public static String lockToKey(String lockstr) throws UnsupportedEncodingException { byte[] lock = lockstr.split(" ", 3)[1].getBytes(CHARENCODING); byte[] key = new byte[lock.length]; for (int i = 1; i < lock.length; i++) { key[i] = (byte) ((lock[i] ^ lock[i - 1]) & 0xFF); } key[0] = (byte) ((((lock[0] ^ lock[lock.length - 1]) ^ lock[lock.length - 2]) ^ 5) & 0xFF); for (int i = 0; i < key.length; i++) { key[i] = (byte) ((((key[i] << 4) & 0xF0) | ((key[i] >> 4) & 0x0F)) & 0xFF); } return dcnEncode(new String(key, CHARENCODING)); } private static String dcnEncode(String lock) { for (int i: new int[]{0,5,36,96,124,126}) { String paddedDecimal = String.format("%03d", i); String paddedHex = String.format("%02x", i); lock = lockstring.replaceAll("\\x"+paddedHex, "/%DCN"+paddedDecimal+"%/"); } return "$Key " + lock + "|"; } }
Язык Visual Basic
Public Function Lock2Key(StrLock As String) As String Dim TLock2Key As String, TChar As Integer If Len(StrLock) < 3 Then Lock2Key = Left$("BROKENCLIENT", Len(StrLock)) Exit Function End If TLock2Key = Chr$(Asc(Left$(StrLock, 1)) Xor Asc(Right$(StrLock, 1)) Xor Asc(Mid$(StrLock, Len(StrLock) - 1, 1)) Xor 5) For i = 2 To Len(StrLock) TLock2Key = TLock2Key & Chr$(Asc(Mid$(StrLock, i, 1)) Xor Asc(Mid$(StrLock, i - 1, 1))) Next i For i = 1 To Len(TLock2Key) TChar = Asc(Mid$(TLock2Key, i, 1)) TChar = TChar * 16 + TChar \ 16 'Swap bits 11110000 -> 00001111 TChar = TChar Mod 256 If TChar = 0 Or TChar = 5 Or TChar = 36 Or TChar = 96 Or TChar = 124 Or TChar = 126 Then Lock2Key = Lock2Key & "/%DCN" & Right$("000" & TChar, 3) & "%/" Else Lock2Key = Lock2Key & Chr$(TChar) End If Next i End Function Case "$LOCK" 'You've recived $LOCK, convert it to $KEY Dim sLock2 As String sLock2 = Split(Mid(sData2, 7), " Pk=")(0) sLock2 = Lock2Key(sLock2)
Язык Python
lock = self.sock.recv(1024) lock = re.findall('\$Lock[\s](.*?)[\s]', lock)[0] key = {} for i in xrange(1, len(lock)): key[i] = ord(lock[i]) ^ ord(lock[i-1]) key[0] = ord(lock[0]) ^ ord(lock[len(lock)-1]) ^ ord(lock[len(lock)-2]) ^ 5 for i in xrange(0, len(lock)): key[i] = ((key[i]<<4) & 240) | ((key[i]>>4) & 15) out = "" for i in xrange(0, len(lock)): out += unichr(key[i]) out = out.replace(u'\0', u'/%DCN000%/').replace(u'\5', u'/%DCN005%/').replace(u'\44', u'/%DCN036%/') out = out.replace(u'\140', u'/%DCN096%/').replace(u'\174', u'/%DCN124%/').replace(u'\176', u'/%DCN126%/')
Язык Python 2.5.2 (Ubuntu 8.10)
# "lock" must be the exact lock character sequence, not the whole command. # i.e. if the command is $Lock blah pk=bleh|, lock should be "blah" def lock_to_key(lock): "Decrypts lock to key." key = {} for i in xrange(1, len(lock)): key[i] = ord(lock[i]) ^ ord(lock[i-1]) key[0] = ord(lock[0]) ^ ord(lock[len(lock)-1]) ^ ord(lock[len(lock)-2]) ^ 5 for i in xrange(0, len(lock)): key[i] = ((key[i]<<4) & 240) | ((key[i]>>4) & 15) out = "" for i in xrange(0, len(key)): if key[i] in (0, 5, 36, 96, 124, 126): out += "/%%DCN%03d%%/" % (key[i],) else: out += chr(key[i]) return out
Язык Ruby
def lock2key(_LOCK) lockLength = _LOCK.size lockToKey = '' spec_chars = [126, 124, 96, 36, 5, 0] lockLength.times{ |j| if j == 0 h = _LOCK[0] ^ _LOCK[ lockLength - 1] ^ _LOCK[ lockLength - 2 ] ^ 5 else h = _LOCK[j] ^ _LOCK[j-1] end h = h % 256 # h = h & 0xFF a = ((h<<4) & 240) | ((h>>4) & 15) if spec_chars.include?(a) lockToKey << sprintf("/%%DCN%03d%%/", a) else lockToKey << a.chr end } lockToKey end