Описание:
Реализация в различных языках функции lock2key для нахождения ключа по параметру команды $Lock.
Язык С/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;
}
{
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;
}
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;
}
{
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
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, $port) {
$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;
}
$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);
}
{
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;
// 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:
private static final String CHARENCODING = "windows-1252";
public static String generateKey(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);
}
String modifiedLock = new String(key,CHARENCODING);
return dcnEncode(modifiedLock);
}
private static String dcnEncode(String lockstring) {
for (int i: new int[]{0,5,36,96,124,126}) {
String paddedDecimal = String.format("%03d", i);
String paddedHex = String.format("%02x", i);
lockstring = lockstring.replaceAll("\\x"+paddedHex, "/%DCN"+paddedDecimal+"%/");
}
return "$Key "+lockstring+"|";
}
public static String generateKey(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);
}
String modifiedLock = new String(key,CHARENCODING);
return dcnEncode(modifiedLock);
}
private static String dcnEncode(String lockstring) {
for (int i: new int[]{0,5,36,96,124,126}) {
String paddedDecimal = String.format("%03d", i);
String paddedHex = String.format("%02x", i);
lockstring = lockstring.replaceAll("\\x"+paddedHex, "/%DCN"+paddedDecimal+"%/");
}
return "$Key "+lockstring+"|";
}
Язык 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%/')
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
# 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
Оригинал (by Setuper): http://mydc.ru/index.html?showtopic=915&view=findpost&p=19477