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
Источник — «http://wiki.mydc.ru/Lock2Key»
Личные инструменты
Пространства имён
Варианты
Действия
Навигация
RusHub
Инструменты
Портал