Skip to content

Instantly share code, notes, and snippets.

@fubar-coder
Last active October 11, 2015 18:05
Show Gist options
  • Save fubar-coder/e099af6213da3125ea93 to your computer and use it in GitHub Desktop.
Save fubar-coder/e099af6213da3125ea93 to your computer and use it in GitHub Desktop.
This source code encrypts/decrypts lexware passwords for Lexware database access
public static class LexwarePasswordEncryption
{
public static string Encrypt(string password, string key)
{
return PerformCrypt(password, true, key);
}
public static string Decrypt(string encryptedPassword, string key)
{
return PerformCrypt(encryptedPassword, false, key);
}
private static string PerformCrypt(string pwd, bool encrypt, string currentKey)
{
if (string.IsNullOrEmpty(currentKey))
return pwd;
if (currentKey == "DUMMY")
return new string(pwd.Reverse().ToArray());
if (currentKey == "LEXWARE")
currentKey = "1a1z";
if (encrypt)
return DoEncryption(pwd, currentKey);
return DoDecryption(pwd, currentKey);
}
private static string DoEncryption(string pwd, string key)
{
var buffer = new byte[0xC0];
InitBufferWithKey(buffer, key);
if (string.IsNullOrEmpty(pwd))
return null;
return DoEncryption(buffer, pwd);
}
private static string DoEncryption(byte[] buffer, string pwd)
{
if (string.IsNullOrEmpty(pwd) || pwd.Length > 0x100)
return null;
int encryptedLength = 0x200;
var encrypted = new byte[encryptedLength];
var pwdBuffer = Encoding.Default.GetBytes(pwd);
DoEncryption(buffer, pwdBuffer, encrypted, out encryptedLength);
return BytesToHex(encrypted.ToSlice(0, encryptedLength));
}
private static void DoEncryption(byte[] buffer, byte[] pwdBuffer, byte[] encrypted, out int encryptedLengthRef)
{
var keyChars = buffer.ToSlice(0xAC, 8);
var keyIndexes = buffer.ToSlice(0xB4, 8);
var encryptedData = buffer.ToSlice(0x00, 8);
var dataToEncrypt = buffer.ToSlice(0x08, 8);
var cryptProcessingBuffer = buffer.ToSlice(0x18, 0x90);
MemSet(encryptedData, 1, 8);
var blockLength = Math.Min(8, pwdBuffer.Length);
MemCopy(dataToEncrypt, pwdBuffer, blockLength);
var processedPasswordLength = blockLength;
var resultLength = 0;
var isLastBlock = false;
while (!isLastBlock)
{
if (blockLength < 8)
{
var blockFillLength = (byte)(8 - blockLength);
MemSet(dataToEncrypt.ToSlice(blockLength, blockFillLength), 0, blockFillLength);
dataToEncrypt[7] = blockFillLength;
isLastBlock = true;
}
for (var index1 = 0; index1 != 8; ++index1)
{
dataToEncrypt[index1] = (byte)(encryptedData[index1] ^ dataToEncrypt[index1]);
}
BuildCryptKey(
cryptProcessingBuffer,
keyChars,
keyIndexes,
true);
ProcessSymmetricCrypt(
cryptProcessingBuffer,
buffer.ToSlice(0x00, 0x08 * 8),
buffer.ToSlice(0x08, 0x08 * 8),
8,
true);
MemCopy(encrypted.ToSlice(resultLength, 8), buffer, 8);
resultLength += 8;
if (pwdBuffer.Length >= processedPasswordLength + 8)
{
MemCopy(dataToEncrypt, pwdBuffer.ToSlice(processedPasswordLength, 8), 8);
blockLength = 8;
}
else
{
if (pwdBuffer.Length > resultLength)
{
var remainingLength = pwdBuffer.Length - processedPasswordLength;
MemCopy(dataToEncrypt, pwdBuffer.ToSlice(processedPasswordLength, remainingLength), remainingLength);
blockLength = remainingLength;
}
else
{
blockLength = 0;
}
}
processedPasswordLength += blockLength;
}
encryptedLengthRef = resultLength;
}
private static string DoDecryption(string pwd, string key)
{
var buffer = new byte[0xC0];
InitBufferWithKey(buffer, key);
if (string.IsNullOrEmpty(pwd))
return null;
return DoDecryption(buffer, pwd);
}
private static string DoDecryption(byte[] buffer, string pwd)
{
if (string.IsNullOrEmpty(pwd) || pwd.Length > 0x200)
return null;
var pwdBuffer = HexToBytes(pwd);
if (pwdBuffer == null)
return null;
return DoDecryption(buffer, pwdBuffer);
}
private static string DoDecryption(byte[] buffer, byte[] pwdBuffer)
{
var dest = new byte[256];
int destLength;
DoDecryption(buffer, pwdBuffer, dest, out destLength);
var text = Encoding.Default.GetString(dest, 0, destLength);
return text;
}
private static void DoDecryption(byte[] buffer, byte[] pwdBuffer, byte[] dest, out int destLengthRef)
{
var blockCount = pwdBuffer.Length / 8;
var decryptedData = buffer.ToSlice(0, 8);
MemSet(decryptedData, 1, 8);
var cryptProcessingBuffer = buffer.ToSlice(0x18, 0x90);
var dataToDecrypt = buffer.ToSlice(0x08, 8);
var dataToDecryptCopy = buffer.ToSlice(0x10, 8);
var keyChars = buffer.ToSlice(0xAC, 8);
var keyIndexes = buffer.ToSlice(0xB4, 8);
var blockLength = Math.Min(pwdBuffer.Length, 8);
MemCopy(dataToDecrypt, pwdBuffer, blockLength);
var processedBlockLength = blockLength;
var decryptedLength = 0;
while (blockCount-- != 0)
{
MemCopy(dataToDecryptCopy, dataToDecrypt, 8);
BuildCryptKey(
cryptProcessingBuffer,
keyChars,
keyIndexes,
false);
ProcessSymmetricCrypt(
cryptProcessingBuffer,
buffer.ToSlice(0x08, 0x08 * 8),
buffer.ToSlice(0x08, 0x08 * 8),
8,
false);
for (var index1 = 0; index1 != 8; ++index1)
dataToDecrypt[index1] = (byte)(decryptedData[index1] ^ dataToDecrypt[index1]);
if (blockCount == 0)
{
var var19 = buffer[0x0F];
if (var19 <= 8)
{
blockLength -= var19;
}
else
{
buffer[0x0f] = 0x27;
}
}
if (blockLength > 8)
{
dest[0] = 0;
destLengthRef = 0;
return;
}
MemCopy(dest.ToSlice(decryptedLength, 8), dataToDecrypt, blockLength);
decryptedLength += blockLength;
MemCopy(decryptedData, dataToDecryptCopy, 8);
if (pwdBuffer.Length >= processedBlockLength + 8)
{
MemCopy(dataToDecrypt, pwdBuffer.ToSlice(processedBlockLength, 8), 8);
blockLength = 8;
}
else
{
if (pwdBuffer.Length > processedBlockLength)
{
var copyLength = pwdBuffer.Length - processedBlockLength;
MemCopy(dataToDecrypt, pwdBuffer.ToSlice(processedBlockLength, copyLength), copyLength);
// blockLength = originalBlockLength - destLength;
}
blockLength = 0;
}
processedBlockLength += blockLength;
}
destLengthRef = decryptedLength;
}
private static void BuildCryptKey(Slice<byte> cryptProcessingBuffer, Slice<byte> keyChars, Slice<byte> inputIndexes, bool encrypt)
{
CopyReverse4X2(cryptProcessingBuffer.ToSlice(0x80, 0x08), inputIndexes);
CopyReverse4X2(cryptProcessingBuffer.ToSlice(0x88, 0x08), inputIndexes);
BuildCryptKey(cryptProcessingBuffer, keyChars, encrypt);
}
private static void ProcessSymmetricCrypt(Slice<byte> cryptProcessingBuffer, Slice<byte> target, Slice<byte> blocks, byte length, bool encrypt)
{
if ((length % 8) != 0)
throw new ArgumentOutOfRangeException(nameof(length), "Length must be a multiple of 8");
var temp = new byte[8];
var blockCount = length / 8;
for (var index = 0; index != blockCount; ++index)
{
CopyReverse4X2(temp.ToSlice(), blocks.ToSlice(index * 8, 0x08));
uint itemLo, itemHi;
//var isDecryption = BitConverter.ToInt32(cryptProcessingBuffer.ToArray(0x90, 4), 0) == 0;
var isDecryption = !encrypt;
if (isDecryption)
{
itemLo = BitConverter.ToUInt32(temp, 0);
itemHi = BitConverter.ToUInt32(temp, 4);
}
else
{
itemLo = BitConverter.ToUInt32(temp, 0);
var tempLo = BitConverter.ToUInt32(cryptProcessingBuffer.ToArray(0x80, 4), 0);
itemLo ^= tempLo;
itemHi = BitConverter.ToUInt32(temp, 4);
var tempHi = BitConverter.ToUInt32(cryptProcessingBuffer.ToArray(0x84, 4), 0);
itemHi ^= tempHi;
}
PerformCrypt(cryptProcessingBuffer, ref itemLo, ref itemHi);
if (isDecryption)
{
var tempLo = BitConverter.ToUInt32(cryptProcessingBuffer.ToArray(0x80, 4), 0);
var tempHi = BitConverter.ToUInt32(cryptProcessingBuffer.ToArray(0x84, 4), 0);
itemLo ^= tempLo;
itemHi ^= tempHi;
cryptProcessingBuffer.ToSlice(0x80, 8).CopyFrom(temp);
}
else
{
cryptProcessingBuffer.ToSlice(0x80, 4).CopyFrom(BitConverter.GetBytes(itemLo));
cryptProcessingBuffer.ToSlice(0x84, 4).CopyFrom(BitConverter.GetBytes(itemHi));
}
WriteToBigEndian32(target.ToSlice(index * 8, 8), itemLo, itemHi);
}
}
private static void WriteToBigEndian32(IList<byte> target, uint itemLo, uint itemHi)
{
var unk2Index = 0;
target[unk2Index++] = (byte)((itemLo >> 0x18) & 0xFF);
target[unk2Index++] = (byte)((itemLo >> 0x10) & 0xFF);
target[unk2Index++] = (byte)((itemLo >> 0x08) & 0xFF);
target[unk2Index++] = (byte)((itemLo >> 0x00) & 0xFF);
target[unk2Index++] = (byte)((itemHi >> 0x18) & 0xFF);
target[unk2Index++] = (byte)((itemHi >> 0x10) & 0xFF);
target[unk2Index++] = (byte)((itemHi >> 0x08) & 0xFF);
target[unk2Index] = (byte)((itemHi >> 0x00) & 0xFF);
}
private static void PerformCrypt(IReadOnlyList<byte> source, ref uint itemLo, ref uint itemHi)
{
var temp1 = itemLo;
var temp2 = itemHi;
var temp3 = ((temp1 >> 0x04) ^ temp2) & 0x0F0F0F0F;
temp2 ^= temp3;
temp1 ^= (temp3 << 0x04);
temp3 = ((temp1 >> 0x10) ^ temp2) & 0x0000FFFF;
temp2 ^= temp3;
temp1 ^= (temp3 << 0x10);
temp3 = ((temp2 >> 0x02) ^ temp1) & 0x33333333;
temp1 ^= temp3;
temp2 ^= (temp3 << 0x02);
temp3 = ((temp2 >> 0x08) ^ temp1) & 0x00FF00FF;
temp1 ^= temp3;
temp2 ^= (temp3 << 0x08);
temp2 = (temp2 << 0x01) | (temp2 >> 0x1F);
temp3 = (temp1 ^ temp2) & 0xAAAAAAAA;
temp1 ^= temp3;
temp2 ^= temp3;
temp1 = (temp1 << 0x01) | (temp1 >> 0x1F);
var sourceOffset = 0;
var sourceArray = source.ToArray();
for (int i = 0; i != 8; ++i)
{
temp3 = ((temp2 >> 0x04) | (temp2 << 0x1C)) ^ BitConverter.ToUInt32(sourceArray, sourceOffset);
temp1 ^= _magicValues6[temp3 & 0x3F];
temp1 ^= _magicValues7[(temp3 >> 8) & 0x3F];
temp1 ^= _magicValues8[(temp3 >> 0x10) & 0x3F];
temp1 ^= _magicValues9[(temp3 >> 0x18) & 0x3F];
temp3 = temp2 ^ BitConverter.ToUInt32(sourceArray, sourceOffset + 4);
temp1 ^= _magicValues10[temp3 & 0x3F];
temp1 ^= _magicValues11[(temp3 >> 8) & 0x3F];
temp1 ^= _magicValues12[(temp3 >> 0x10) & 0x3F];
temp1 ^= _magicValues13[(temp3 >> 0x18) & 0x3F];
temp3 = ((temp1 >> 0x04) | (temp1 << 0x1C)) ^ BitConverter.ToUInt32(sourceArray, sourceOffset + 8);
temp2 ^= _magicValues6[temp3 & 0x3F];
temp2 ^= _magicValues7[(temp3 >> 8) & 0x3F];
temp2 ^= _magicValues8[(temp3 >> 0x10) & 0x3F];
temp2 ^= _magicValues9[(temp3 >> 0x18) & 0x3F];
temp3 = temp1 ^ BitConverter.ToUInt32(sourceArray, sourceOffset + 12);
temp2 ^= _magicValues10[temp3 & 0x3F];
temp2 ^= _magicValues11[(temp3 >> 8) & 0x3F];
temp2 ^= _magicValues12[(temp3 >> 0x10) & 0x3F];
temp2 ^= _magicValues13[(temp3 >> 0x18) & 0x3F];
sourceOffset += 16;
}
temp2 = (temp2 << 0x1F) | (temp2 >> 0x01);
temp3 = (temp1 ^ temp2) & 0xAAAAAAAA;
temp1 ^= temp3;
temp2 ^= temp3;
temp1 = (temp1 << 0x1F) | (temp1 >> 0x01);
temp3 = ((temp1 >> 0x08) ^ temp2) & 0x00FF00FF;
temp2 ^= temp3;
temp1 ^= (temp3 << 0x08);
temp3 = ((temp1 >> 0x02) ^ temp2) & 0x33333333;
temp2 ^= temp3;
temp1 ^= (temp3 << 0x02);
temp3 = ((temp2 >> 0x10) ^ temp1) & 0x0000FFFF;
temp1 ^= temp3;
temp2 ^= (temp3 << 0x10);
temp3 = ((temp2 >> 0x04) ^ temp1) & 0x0F0F0F0F;
temp1 ^= temp3;
temp2 ^= (temp3 << 0x04);
itemLo = temp2;
itemHi = temp1;
}
private static void BuildCryptKey(IList<byte> cryptProcessingBuffer, IReadOnlyList<byte> keyChars, bool encrypt)
{
var firstHalf = new byte[0x1C];
var secondHalf = new byte[0x1C];
var keyInputBits = new byte[0x38];
var tempResult = new uint[0x40];
for (int i = 0; i != 0x38; ++i)
{
var temp = _magicValues1[i];
var offset1 = temp & 0x7;
var ch = (int)keyChars[temp >> 3];
var bits = (int)_byteBits[offset1];
keyInputBits[i] = (ch & bits) != 0 ? (byte)1 : (byte)0;
}
for (int outerIndex = 0; outerIndex != 16; ++outerIndex)
{
var offset1 = outerIndex * 2;
var offset2 = offset1 + 1;
tempResult[offset2] = 0;
tempResult[offset1] = 0;
for (var innerIndex = 0; innerIndex < 0x1C; ++innerIndex)
{
var temp = _magicValues2[outerIndex] + innerIndex;
if (temp < 0x1C)
{
firstHalf[innerIndex] = keyInputBits[temp];
}
else
{
firstHalf[innerIndex] = keyInputBits[temp - 0x1C];
}
}
for (var innerIndex = 0x1C; innerIndex < 0x38; ++innerIndex)
{
var temp = _magicValues2[outerIndex] + innerIndex;
if (temp < 0x38)
{
secondHalf[innerIndex - 0x1C] = keyInputBits[temp];
}
else
{
secondHalf[innerIndex - 0x1C] = keyInputBits[temp - 0x1C];
}
}
for (var innerIndex = 0x00; innerIndex < 0x18; ++innerIndex)
{
if (firstHalf[_magicValues3[innerIndex]] != 0)
{
tempResult[offset1] |= _magicValues4[innerIndex];
}
if (secondHalf[_magicValues5[innerIndex] - 0x1C] != 0)
{
tempResult[offset2] |= _magicValues4[innerIndex];
}
}
}
JuggleData(cryptProcessingBuffer, tempResult, encrypt);
}
private static void JuggleData(IList<byte> destination, uint[] source, bool encrypt)
{
var currentSourceIndex = 0;
var startDestIndex = encrypt ? 0 : 0x78;
var currentDestIndex = startDestIndex;
var destIndexChange = encrypt ? 0 : -16;
for (var index1 = 0; index1 != 16; ++index1)
{
var sourceIndexAtLoopStart = currentSourceIndex;
currentSourceIndex += 1;
uint temp = 0;
temp |= (source[sourceIndexAtLoopStart] & 0x00FC0000) << 6; // 0x3F000000
temp |= (source[sourceIndexAtLoopStart] & 0x00000FC0) << 10; // 0x003F0000
temp |= (source[currentSourceIndex] & 0x00FC0000) >> 10; // 0x00003F00
temp |= (source[currentSourceIndex] & 0x00000FC0) >> 6; // 0x0000003F
var data = BitConverter.GetBytes(temp);
for (int i = 0; i != data.Length; ++i)
destination[currentDestIndex + i] = data[i];
currentDestIndex += 4;
temp = 0;
temp |= (source[sourceIndexAtLoopStart] & 0x0003F000) << 12; // 0x3F000000
temp |= (source[sourceIndexAtLoopStart] & 0x0000003F) << 16; // 0x003F0000
temp |= (source[currentSourceIndex] & 0x0003F000) >> 4; // 0x00003F00
temp |= (source[currentSourceIndex] & 0x0000003F) >> 0; // 0x0000003F
data = BitConverter.GetBytes(temp);
for (int i = 0; i != data.Length; ++i)
destination[currentDestIndex + i] = data[i];
currentDestIndex += 4 + destIndexChange;
currentSourceIndex += 1;
}
}
private static void InitBufferWithKey(byte[] buffer, string key)
{
if (string.IsNullOrEmpty(key))
return;
var keyBuffer = new byte[16];
for (int index = 0; index != 16; ++index)
{
var ch = key[index % key.Length];
keyBuffer[index] = (byte)ch;
}
FillBufferWithKey(buffer, keyBuffer);
}
private static void FillBufferWithKey(byte[] buffer, byte[] keyBuffer)
{
for (var index = 0; index != 8; ++index)
{
var v = keyBuffer[index];
buffer[index + 0xAC] = v;
buffer[index + 0xB4] = (byte)index;
}
}
private static void CopyReverse4X2(IList<byte> destination, IReadOnlyList<byte> source)
{
for (var index = 0; index != 4; ++index)
destination[3 - index] = source[index];
for (var index = 0; index != 4; ++index)
destination[7 - index] = source[index + 4];
}
private static readonly byte[] _magicValues1 = new byte[]
{
0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x8, 0x0,
0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x9, 0x1,
0x3A, 0x32, 0x2A, 0x22, 0x1A, 0x12, 0x0A, 0x2,
0x3B, 0x33, 0x2B, 0x23, 0x3E, 0x36, 0x2E, 0x26,
0x1E, 0x16, 0x0E, 0x6, 0x3D, 0x35, 0x2D, 0x25,
0x1D, 0x15, 0x0D, 0x5, 0x3C, 0x34, 0x2C, 0x24,
0x1C, 0x14, 0x0C, 0x4, 0x1B, 0x13, 0x0B, 0x3,
};
private static readonly byte[] _magicValues2 = new byte[]
{
0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1C,
};
private static readonly byte[] _magicValues3 = new byte[]
{
0x0D, 0x10, 0x0A, 0x17, 0x00, 0x04, 0x02, 0x1B,
0x0E, 0x05, 0x14, 0x09, 0x16, 0x12, 0x0B, 0x03,
0x19, 0x07, 0x0F, 0x06, 0x1A, 0x13, 0x0C, 0x01,
};
private static readonly uint[] _magicValues4 = new uint[]
{
0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000,
0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100,
0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001,
};
private static readonly byte[] _magicValues5 = new byte[]
{
0x28, 0x33, 0x1E, 0x24, 0x2E, 0x36, 0x1D, 0x27,
0x32, 0x2C, 0x20, 0x2F, 0x2B, 0x30, 0x26, 0x37,
0x21, 0x34, 0x2D, 0x29, 0x31, 0x23, 0x1C, 0x1F,
};
private static readonly uint[] _magicValues6 = new uint[]
{
0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800,
0x4200802, 0x200000, 0, 0x4000002, 2, 0x4000000, 0x4200002, 0x802,
0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002,
0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 2, 0x4000000, 0x200800,
0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 2,
0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800,
0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 2, 0x4200802,
0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002,
};
private static readonly uint[] _magicValues7 = new uint[]
{
0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000,
0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000,
0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100,
0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100,
0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100,
0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000,
0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000,
0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100,
};
private static readonly uint[] _magicValues8 = new uint[]
{
0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200,
0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208,
0x8000000, 8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208,
0x8000208, 0x20200, 0x20000, 0x8000208, 8, 0x8020208, 0x200, 0x8000000,
0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0,
0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008,
0x8000208, 0x20000, 0x8000000, 0x8020208, 8, 0x20208, 0x20200, 0x8000008,
0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 8, 0x8020008, 0x20200,
};
private static readonly uint[] _magicValues9 = new uint[]
{
0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 4, 0x10000,
0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 4,
0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404,
0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000,
0x10000, 0x1010404, 4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400,
0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 4, 0x1000404, 0x10404,
0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400,
0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004,
};
private static readonly uint[] _magicValues10 = new uint[]
{
0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000,
0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40,
0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000,
0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000,
0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040,
0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040,
0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0,
0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000,
};
private static readonly uint[] _magicValues11 = new uint[]
{
0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000,
0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010,
0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010,
0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000,
0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010,
0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000,
0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010,
0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010,
};
private static readonly uint[] _magicValues12 = new uint[]
{
0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001,
0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001,
1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080,
0x800081, 1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81,
0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000,
0x2080, 0x800080, 0x800081, 1, 0x802001, 0x2081, 0x2081, 0x80,
0x802081, 0x81, 1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081,
0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080,
};
private static readonly uint[] _magicValues13 = new uint[]
{
0x80108020, 0x80008000, 0x8000, 0x108020, 0x100000, 0x20, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x100000, 0x20, 0x80100020,
0x108000, 0x100020, 0x80008020, 0, 0x80000000, 0x8000, 0x108020, 0x80100000,
0x100020, 0x80000020, 0, 0x108000, 0x8020, 0x80108000, 0x80100000, 0x8020,
0, 0x108020, 0x80100020, 0x100000, 0x80008020, 0x80100000, 0x80108000, 0x8000,
0x80100000, 0x80008000, 0x20, 0x80108020, 0x108020, 0x20, 0x8000, 0x80000000,
0x8020, 0x80108000, 0x100000, 0x80000020, 0x100020, 0x80008020, 0x80000020, 0x100020,
0x108000, 0, 0x80008000, 0x8020, 0x80000000, 0x80100020, 0x80108020, 0x108000,
};
private static readonly byte[] _byteBits = new byte[]
{
0x80,
0x40,
0x20,
0x10,
0x08,
0x04,
0x02,
0x01,
};
private static string BytesToHex(IReadOnlyCollection<byte> input)
{
return string.Join(string.Empty, input.Select(x => x.ToString("x2")));
}
private static byte[] HexToBytes(string s)
{
if (string.IsNullOrEmpty(s))
return null;
var source = Enumerable
.Range(0, s.Length / 2)
.Select(x => s.Substring(x * 2, 2))
.Select(x => Convert.ToByte(x, 16))
.ToArray();
return source;
}
private static void MemCopy(IList<byte> dest, IReadOnlyList<byte> source, int length)
{
for (int i = 0; i != length; ++i)
dest[i] = source[i];
}
private static void MemSet(IList<byte> dest, byte value, int length)
{
for (int i = 0; i != length; ++i)
dest[i] = value;
}
}
public static class SliceExtensions
{
public static Slice<T> ToSlice<T>(this T[] array)
{
return new Slice<T>(array);
}
public static Slice<T> ToSlice<T>(this T[] array, int offset, int length)
{
return new Slice<T>(array, offset, length);
}
public static Slice<T> ToSlice<T>(this Slice<T> slice)
{
return slice;
}
public static Slice<T> ToSlice<T>(this Slice<T> slice, int offset, int length)
{
return new Slice<T>(slice, offset, length);
}
}
public class Slice<T> : IList<T>, IReadOnlyList<T>
{
private readonly T[] _array;
private readonly int _offset;
public Slice(Slice<T> slice)
: this(slice, 0, slice.Count)
{
}
public Slice(Slice<T> slice, int offset, int length)
{
if (offset + length > slice.Count)
throw new InvalidOperationException();
_offset = slice._offset + offset;
Count = length;
_array = slice._array;
}
public Slice(T[] array)
: this(array, 0, array.Length)
{
}
public Slice(T[] array, int offset, int length)
{
if (offset + length > array.Length)
throw new InvalidOperationException();
_array = array;
_offset = offset;
Count = length;
}
public int IndexOf(T item)
{
var comparer = Comparer<T>.Default;
var index = 0;
foreach (var thisItem in this)
{
if (comparer.Compare(thisItem, item) == 0)
return index;
index += 1;
}
return -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
public T this[int index]
{
get
{
if (index >= Count)
throw new IndexOutOfRangeException();
return _array[_offset + index];
}
set
{
if (index >= Count)
throw new IndexOutOfRangeException();
_array[_offset + index] = value;
}
}
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(T item)
{
return IndexOf(item) != -1;
}
public void CopyTo(T[] array, int arrayIndex)
{
foreach (var thisItem in this)
array[arrayIndex++] = thisItem;
}
public void CopyFrom(IEnumerable<T> source)
{
var targetOffset = 0;
foreach (var item in source)
this[targetOffset++] = item;
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
public int Count { get; }
public bool IsReadOnly => false;
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)new ArraySegment<T>(_array, _offset, Count)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public T[] ToArray(int startIndex)
{
if (startIndex >= Count)
throw new InvalidOperationException();
return ToArray(startIndex, Count - startIndex);
}
public T[] ToArray(int startIndex, int length)
{
if (startIndex + length > Count)
throw new InvalidOperationException();
var temp = new T[length];
Array.Copy(_array, _offset + startIndex, temp, 0, length);
return temp;
}
}
@fubar-coder
Copy link
Author

Der Key ist - soweit ich weiß - immer "LEXWARE".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment