永珍幻境網管專家普及版密碼演算法 (3千字)

看雪資料發表於2002-06-09

本文可以隨意轉載,但請保留本文的完整性

題目:永珍幻境網管專家普及版密碼演算法

作者:zmworm
演算法描述語言:VC
適應讀者:程式設計人員
永珍幻境網管專家普及版密碼演算法
永珍幻境網管專家普及版密碼破解器v0.1釋出到現在已經近一年了,許多人問我永珍幻境的密碼演算法是什麼,但我一直沒有公佈.隨著永珍幻境R12的發行(其演算法已經改變),面對許多國產軟體的密碼保護力度還不夠強的現狀.我決定將永珍幻境的密碼演算法公開.
這次公佈的解密演算法.加密演算法時此演算法的逆,所以沒有寫.
希望本文能對大家編寫軟體有所幫助,對國產軟體有所幫助.
希望和大家共同探討有關演算法的問題我的郵箱zmworm@sohu.com
注1:本文只是討論演算法,而不是針對某個軟體進行解密.所以對seed1,seed2,seed3進行了處理
注2:本文不討論R12的密碼演算法,事實上R12的演算法不比此演算法強,而且令人氣憤的是,R12演算法的金鑰竟是GODPIG!!!
原理說明:
永珍加密時,得到的密文不同(密文在登錄檔“HKEY_LOCAL_MACHINE\Software\永珍幻境\專家系列網管軟體\”)。
玄機何在?其實很簡單,在每次加密時“永珍”都要隨機的選取一個16位初始向量IV和兩個16位引數m1、
m2,並將它們加密後放在密文之前供解密時使用,然後再利用這三個引數對明文進行加密。
解密時,需先對這三個值解密,再對密文解密。
無論IV、m1、m2還是明文M都有了同一演算法(IV、m1、m2加密過程中的初使向量和兩個引數都是固定的)。
這種演算法屬於較為複雜的CBC模式.
解密函式解密
void uncode(char * szString,CString& sVal)
//szString 為密文;sVal為返回的明文;函式uncode的作用是解密
{
UINT seed1=0x1111,seed2=0x2222,seed3=0x3333;//關鍵!知道這幾個值不同加解密的結果也不同
UINT IV=0,m1=0,m2=0;
//還原出引數IV
int i;
char key1[3]="";
UINT edx=seed1;//金鑰1
for(i=0;i<=2;i++)
{
char inte[3]="";
inte[0]=szString[3*i];
inte[1]=szString[3*i+1];
inte[2]=szString[3*i+2];//取三位
key1[i]=CharToInt(inte);//將此三位數串轉成數
int mk=(edx&0x0000ff00)>>8;//取金鑰1的3 4位準備做異或
UINT temp=key1[i];
temp&=0x000000ff;
edx=(temp+edx)*seed2+seed3;//改變金鑰1的值
key1[i]^=mk;//還原引數1的第i位
};
IV=(key1[0]-'0')*100+(key1[1]-'0')*10+(key1[2]-'0');
//還原出引數m1
char key2[5]="";
edx=0xseed1;
for(i=0;i<=4;i++)
{
char inte[3]="";
inte[0]=szString[3*(i+3)];
inte[1]=szString[3*(i+3)+1];
inte[2]=szString[3*(i+3)+2];
key2[i]=CharToInt(inte);
int mk=(edx&0x0000ff00)>>8;
UINT temp=key2[i];
temp&=0x000000ff;
edx=(temp+edx)*seed2+seed3;
key2[i]^=mk;
};
m1=(key2[0]-'0')*10000+(key2[1]-'0')*1000+(key2[2]-'0')*100+(key2[3]-'0')*10+(key2[4]-'0');
//還原出引數k2
char key3[5]="";
edx=seed1;
for(i=0;i<=4;i++)
{
char inte[3]="";
inte[0]=szString[3*(i+8)];
inte[1]=szString[3*(i+8)+1];
inte[2]=szString[3*(i+8)+2];
key3[i]=CharToInt(inte);
int mk=(edx&0x0000ff00)>>8;
UINT temp=key3[i];
temp&=0x000000ff;
edx=(temp+edx)*seed2+seed3;
key3[i]^=mk;
};
m2=(key3[0]-'0')*10000+(key3[1]-'0')*1000+(key3[2]-'0')*100+(key3[3]-'0')*10+(key3[4]-'0');
//利用引數k1,k2,k3將密文還原成明文密碼
i=0;
char Password[255]="";
edx=IV;
while(szString[(i+13)*3]!='\0')
{
char inte[3]="";
inte[0]=szString[3*(i+13)];
inte[1]=szString[3*(i+13)+1];
inte[2]=szString[3*(i+13)+2];
Password[i]=CharToInt(inte);
int mk=(edx&0x0000ff00)>>8;
UINT temp=Password[i];
temp&=0x000000ff;
edx=(temp+edx)*m1+m2;
Password[i]^=mk;
i++;
};
//返回密碼
sVal=Password;
}
char CharToInt(char * ch)
{
int i;
i=(ch[0]-'0')*100+(ch[1]-'0')*10+ch[2]-'0';
i=i%256;
return i;
}

相關文章