//RC4.h #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifndef RC4h #define RC4h /* This class implements an algorithm called Arcfour that is believed to be fully interoperable with the RC4 algorithm. RC4 is trademark of RSA Data Security, Inc. The Encrypt and Decrypt methods are only to demonstrate usage and are NOT the correct encryption. For the full Encryption use my CryptStream class which extends this class using the Rand several times. Use the Tester class as a usage example. It must be strongly recommended that no two plaintexts are encrypted with the same key. Otherwise the plaintext can usually be broken, and often even quite easily. If the two encrypted messages are XORed together, the result is the XOR of the original plaintexts. Given the encrypted messages are text strings, credit card numbers, or other byte streams with some known properties, the plaintexts can be estimated with great accuracy. See [DAWSON AND NIELSEN] for more details. The same thing in obfuscated c: #define S ,t=s[i],s[i]=s[j],s[j]=t BYTE k[256],s[256],i,j,t; main(c,v,e)char**v;{ ++v; while(++i) s[i]=i; for(c=0; *(*v)++; k[c++]=e) sscanf((*v)++-1,"%2x",&e); while(j+=s[i]+k[i%c]S,++i); for(j=0; c=~getchar(); putchar(~c^s[t+=s[i]]))j+=s[++i]S; } */ class CRC4 { BYTE* KeyBytes; BYTE* CypherBytes; public: CRC4() { KeyBytes=(BYTE*)LocalAlloc(LMEM_FIXED,512); // LocalAlloc allocates process-private memory. CypherBytes=KeyBytes+256; } virtual ~CRC4() { // Don't leave Key traces in memory memset(KeyBytes,0,512); LocalFree(KeyBytes); KeyBytes=CypherBytes=0; } void Crypt(const CString& Key, CString& Data) { int i; for(i=0; i<256; ++i) { KeyBytes[i]=Key[i % Key.GetLength()]; CypherBytes[i]=i; } int Jump=0; for(i=0; i<256; ++i) { Jump=(Jump+CypherBytes[i]+KeyBytes[i]) & 0xFF; BYTE Tmp=CypherBytes[i]; // Swap: CypherBytes[i]=CypherBytes[Jump]; CypherBytes[Jump]=Tmp; } { BYTE i=0; Jump=0; BYTE* it=(BYTE*)Data.GetBuffer(0); for(int X=Data.GetLength(); X ; --X) { i=(i+1) & 0xFF; BYTE Tmp=CypherBytes[i]; Jump=(Jump+CypherBytes[i]) & 0xFF; BYTE T=(CypherBytes[i]+CypherBytes[Jump]) & 0xFF; CypherBytes[i]=CypherBytes[Jump]; // Swap: CypherBytes[Jump]=Tmp; *it++ ^= CypherBytes[T]; // Character Encryption } } } }; #ifdef Assert static struct CRC4Tester : CRC4, Tester { CRC4Tester() { // Test Vectors: const BYTE Test1[]={0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,0}; const BYTE Test2[]={0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,0x12,0x34,0x56,0x78,0}; CString Data(Test1); Crypt(Test1,Data); CString Text(Data); Assert(Data2ASCIIhex(Text)=="75B7878099E0C596"); Crypt(Test1,Data); Assert(Data==Test1); Data=Test2; Crypt(Test1,Data); Text=Data; Assert(Data2ASCIIhex(Text)=="66A0949F8AF7D6891F7F832BA833C00C892EBE30143CE28740011ECF"); Crypt(Test1,Data); Assert(Data==Test2); } CString Data2ASCIIhex(const CString& S) { // A helper function for Data to ASCII Hex if(S.IsEmpty()) return ""; CString Text; int Len=S.GetLength()*2; const char* src=S; char* dst=Text.GetBufferSetLength(Len); for(int i=S.GetLength(); i--;) { BYTE lo=*src++; BYTE hi=lo>>4; lo&=0x0F; *dst++=hi+(hi>9 ? 'A'-10 : '0'); *dst++=lo+(lo>9 ? 'A'-10 : '0'); } Text.ReleaseBuffer(Len); return Text; } } RC4Tester; #endif //def Assert #endif // RC4h