Добрый день!

Возникла необходимость деплоить и настраивать UltraVnc сервер на удаленных машинах. Для этого необходимо было написать шифратор паролей для UltraVnc.

Пароли хранятся в файле ultravnc.ini

[ultravnc]
passwd=<Зашифрованный пароль>
passwd2=<Зашифрованный пароль>

passwd - пароль с полным доступом
passwd2 - пароль с доступом только для чтения

Пароль должен быть не больше 8-ми символов. Недостающие символы заполняются null символами ('�') Шифруется пароль алгоритмом DES, с добавлением 2-x символов в конец.

Была найдена реализация на Perl которая в последствии была переписана на C#. Возникли проблемы с совместимостью DES шифрования Perl и С#, но они были благополучно решены.

Реализация шифрования и дешифровки UltraVnc паролей на C#:

public static string EncryptPassword(string plainPassword)
{
 DES des = CreateDES();
 ICryptoTransform cryptoTransfrom = des.CreateEncryptor();

 plainPassword = plainPassword + "��������";
 plainPassword = plainPassword.Length > 8 ? plainPassword.Substring(0, 8) : plainPassword;
 byte[] data = Encoding.ASCII.GetBytes(plainPassword);
 byte[] encryptedBytes = cryptoTransfrom.TransformFinalBlock(data, 0, data.Length);

 return ByteArrayToHex(encryptedBytes) + "00";
}

public static string DecryptPassword(string encryptedPassword)
{
 DES des = CreateDES();
 ICryptoTransform cryptoTransfrom = des.CreateDecryptor();
 byte[] data = HexToByteArray(encryptedPassword.Substring(0, encryptedPassword.Length - 2));
 byte[] decryptedBytes = cryptoTransfrom.TransformFinalBlock(data, 0, data.Length);

 return Encoding.ASCII.GetString(decryptedBytes);
 }

private static DES CreateDES()
{
 byte[] key = { 0xE8, 0x4A, 0xD6, 0x60, 0xC4, 0x72, 0x1A, 0xE0 };
 DES des = DES.Create();
 des.Key = key;
 des.IV = key;
 des.Mode = CipherMode.ECB;
 des.Padding = PaddingMode.Zeros;
 return des;
} 
public static string ByteArrayToHex(byte[] bytes)
{
 char[] c = new char[bytes.Length * 2];
 byte b;
 for (int i = 0; i < bytes.Length; i++)
 {
  b = (byte)(bytes[i] >> 4);
  c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
  b = (byte)(bytes[i] & 0xF);
  c[(i * 2) + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
 }
 return new string(c);
}

public static byte[] HexToByteArray(string hex)
{
 if (hex.Length % 2 == 1)
 {
  throw new Exception("The binary key cannot have an odd number of digits");
 }
 byte[] arr = new byte[hex.Length >> 1];
 for (int i = 0; i < (hex.Length >> 1); ++i)
 {
  arr[i] = (byte)(((hex[i << 1] - (hex[i << 1] < 58 ? 48 : 55)) << 4) + (hex[(i << 1) + 1] - (hex[(i << 1) + 1] < 58 ? 48 : 55)));
 }
 return arr;
}

Перевод: en