C#实现Serv-U 6 保存的ODBC密码解密
时间:2010-09-15 来源:xhuad
最近应用asp.net在做一个windows服务器的管理软件。ftp用到的是serv-u 6,软件能够智能读取FTP数据库的保存位置(如:ini,注册表,odbc数据库)与相关的配置信息。其中,保存到odbc数据库中的密码是经过加密的。
经过简单分析,发现ODBC密码的加密模式是:
1.加密的结果是以16进制的方式保存的字符串;
2.使用一个固定的密钥(32位)对密码原文进行加密;
3.使用相同的密钥(32位)对密文进行解密;
4.加密字符串32位一个循环,即把加密的字符串分解成32位长度的字符串与加密密钥进行与或处理;
5.需要加密的字符串分解成32位为一个数组后,跟密钥的数组是一一对应的。假设:密钥数组为keyArry,需要加密或者解密的字符串数组为strArry, 那么 strArry[i % 32 ] (其中i % 32 == 1) 对应的就是 key[1]
具体用C#实现如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace DD.Virtualhost.Ftp.ServU
{
public class FtpUtils
{
/// <summary>
/// OBDC加密密码代码
/// </summary>
/// <param name="pass">ASCII码字符</param>
/// <returns></returns>
public static string ODBCPassEncode(string pass)
{
pass = StringToHex(pass);
return ODBCPassDecode(pass);
}
/// <summary>
/// OBDC解密密码代码
/// </summary>
/// <param name="hexStr">16进制字符串</param>
/// <returns></returns>
public static string ODBCPassDecode(string hexStr)
{
if (hexStr.Length % 2 != 0) return "";
string deStr = "";
string tmpStr, notStr, binStr;
//int[] notArry = null;
for (int i = 0; i < hexStr.Length / 2; i++)
{
tmpStr = hexStr.Substring(i * 2, 2);
binStr = HexToBin(tmpStr);
notStr = BinStrNotByPos(binStr, GetIntArray(i % 32));
deStr += BinToHex(notStr);
}
return deStr;
}
#region 私有方法
/// <summary>
/// 字符串转换为16进制
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private static string StringToHex(string input)
{
return StringToHex(input, "");
}
/// <summary>
/// 字符串转换为16进制
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private static string StringToHex(string input, string splitStr)
{
string hexStr = "";
char[] values = input.ToCharArray();
foreach (char letter in values)
{
int value = Convert.ToInt32(letter);
string hexOutput = String.Format("{0:X}", value);
if (hexOutput.Length == 1) hexOutput = "0" + hexOutput;
//Console.Write("{1} ", letter, hexOutput);
hexStr += hexOutput + splitStr;
}
return hexStr;
}
/// <summary>
/// 得到取反的位数的Int数组
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private static int[] GetIntArray(int num)
{
string notStr = "00100100,01000000,00100011,00110100,00110011,01101011,00111011,00100011,00110000,01101100,00101100,00111010,00111110,01101110,01101011,01101100,01110011,01101010,00100100,00100011,00111001,00110000,00110010,01101101,01101100,01101011,01101110,00101011,00101101,01011111,01101100,00000000";
string tmpStr = notStr.Split(',')[num];
ArrayList a = new ArrayList();
for (int i = 0; i < tmpStr.Length; i++)
{
if (tmpStr.Substring(i, 1) == "1") a.Add(i + 1);
}
return (int[])a.ToArray(typeof(int)); ;
}
/// <summary>
/// 二进制转换为16进制
/// </summary>
/// <param name="binStr"></param>
/// <returns></returns>
private static string BinToHex(string binStr)
{
string hexStr = "";
int tmp;
string tmpStr = "";
for (int i = 0; i < binStr.Length / 4; i++)
{
tmp = Convert.ToInt32(binStr.Substring(i * 4, 4), 2);
tmpStr = Convert.ToString(tmp, 16);
hexStr += tmpStr;
}
return hexStr;
}
/// <summary>
/// 16进制字符串转换为字符串
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private static string HexToString(string hexValues)
{
if (hexValues.IndexOf(' ') < 0)
{
string tmpStr = hexValues;
hexValues = tmpStr.Substring(0, 2);
for (int i = 1; i < tmpStr.Length / 2; i++)
{
hexValues += " " + tmpStr.Substring(i * 2, 2);
}
}
string[] hexValuesSplit = hexValues.Split(' ');
string str = "";
foreach (String hex in hexValuesSplit)
{
// Convert the number expressed in base-16 to an integer.
int value = Convert.ToInt32(hex, 16);
// Get the character corresponding to the integral value.
string stringValue = Char.ConvertFromUtf32(value);
str += stringValue;
}
return str;
}
/// <summary>
/// 16进制转换为二进制字符串
/// </summary>
/// <param name="hexStr"></param>
/// <returns></returns>
private static string HexToBin(string hexStr)
{
string binStr = "";
int tmp;
string tmpStr = "";
for (int i = 0; i < hexStr.Length; i++)
{
tmp = Convert.ToInt32(hexStr.Substring(i, 1), 16);
tmpStr = Convert.ToString(tmp, 2);
tmpStr = tmpStr.Length < 4 ? "0000".Substring(0, 4 - tmpStr.Length) + tmpStr : tmpStr;
binStr += tmpStr;
//hexStr.Substring(i, 1);
}
return binStr;
}
/// <summary>
/// 对于不同位置的数据取反
/// </summary>
/// <param name="binStr"></param>
/// <param name="poss"></param>
/// <returns></returns>
private static string BinStrNotByPos(string binStr, int[] poss)
{
string tmpStr;
foreach (int pos in poss)
{
tmpStr = binStr.Substring(pos - 1, 1);
tmpStr = tmpStr == "1" ? "0" : "1";
binStr = binStr.Substring(0, pos - 1) + tmpStr + binStr.Substring(pos);
}
return binStr;
}
#endregion
}
}