views:

52

answers:

0

I have recently stumbled upon the CipherSaber project, and thought it would be fun to implement the CS1 algorithm, an RC4 with IV. On encryption it generates a random 10 byte IV, it appens it to the password and then crypts. On generation the IV is read from the beginning of the file (first 10 bytes) and then appended to the password and finally decrypted. I can't manage to get it working. (link)

Here's the code: CRYPTO.H

typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned char* uchar_p;

#define Array_Size(a) (sizeof(a)/sizeof(a[0]))

class RC4
{
private:
    uint iA, iB;
    uchar cPermutations[256];
    //uchar_p cKey;
    std::string sKey;
    void SwapElements (uint iA, uint iB, uchar_p cArray);
    void Initialize ();
    void GenerateIV (bool bForceIV, std::string sIV);
public:
    RC4(std::string sKeyL, bool bIV, std::string sIV, bool bForceIV, std::string sForcedIV);
    uchar Stream ();
    void Dispose ();
    void LoadIV(std::string sIV);
};

void RC4::LoadIV(std::string sIV)
{
    sKey += sIV;
}

void RC4::SwapElements(uint iA, uint iB, uchar_p cArray)
{
    uchar cTemp = cArray[iA];
    cArray[iA] = cArray[iB];
    cArray[iB] = cTemp;
}

void RC4::Initialize()
{
    uint iKeylength = sKey.length();
    for (iA = 0; iA < 256; ++iA)
    {
        cPermutations[iA] = iA;
    }
    for (iA = iB = 0; iA < 256; ++iA)
    {
        iB = (iB + cPermutations[iA] + sKey[iA % iKeylength]) & 255;
        SwapElements(iA, iB, cPermutations);
    }
    iA = iB = 0;
}

uchar RC4::Stream ()
{
    iA = (iA + 1) & 255;
    iB = (iB + cPermutations[iA]) & 255;
    SwapElements(iA, iB, cPermutations);
    return cPermutations[(cPermutations[iA] + cPermutations[iB]) & 255];
}

void RC4::Dispose ()
{
    for (iA = 0; iA < 256; ++iA)
    {
        cPermutations[iA] = 0;
    }
    iA = iB = 0;
}

RC4::RC4(std::string sKeyL, bool bIV, std::string sIV, bool bForcedIV, std::string sForcedIV)
{
    sKey = sKeyL;
    if (bIV)
    {
        LoadIV(sIV);
    }
    if (bForcedIV)
    {
        GenerateIV(true, sForcedIV);
    }
    if (!bIV && !bForcedIV)
    {
        GenerateIV(false, NULL);
    }
    Initialize();
}

void RC4::GenerateIV (bool bForceIV, /*DEBUG ONLY*/std::string sIV)
{
    if (!bForceIV)
    {
        srand(time(NULL));
        uchar cIV;
        for (int iFoo = 0; iFoo < 10; ++iFoo)
        {
            cIV = (uchar)(rand() % 256 + 1);
            sKey += cIV;
        }
    }
    else
    {
        sKey += sIV;
    }
}

And here's how I am using it.

    ifstream blablab("file.cs1", ifstream::in);
    string iv = "";
    string text = "";
    string line;
    string encrypted;
    while (getline(blablab, line))
    {
        text += line;
    }
    iv = text.substr(0, 10);
    RC4 dec("asdfg", true, iv, false, "");
    cout << iv.length() << endl;
    cout << iv << endl;
    cout << text << endl;
    encrypted = text.substr(10);
    for (int a = 0; a < encrypted.length(); a++)
    {
        cout << (char)(encrypted[a] ^ dec.Stream());
    }
    cout << endl;

The file I am trying to decrypt is the cstest1.cs1 which I generated by turning each hex value into an int and then into a char and wrote them all in a file.

FOLLOW-UP: I looked closer at the file I was trying to decrypt and I had generated it the wrong way, so I recreated it and made sure it was in accordance with the hex-file contents posted on the site. I have also modified the code, and it seems to be better now, but 2 questions still remain.

1: When decrypting, I load the IV and then decrypt the file without the IV or with the IV, because 10 extra or 10 minus permutations on RC4 make a difference.

2: Why is it still not working ? Here's the code:

    ifstream isFile("file.cs1", ios::in | ios::binary);
    vector<uchar> vc;
    uchar dummy;
    while (isFile.good())
    {
        dummy = (uchar)isFile.get();
        vc.push_back(dummy);
    }
    string IV = "";
    for (int i = 0; i < 11; i++)
    {
        IV += vc[i];
    }
    RC4 eng("asdfg", true, IV, false, "");
    for (int i = 10; i < vc.size(); i++)
    {
        cout << (uchar)(vc[i] ^ eng.Stream()) << " ";
    }

BTW, I did not alter the header file, only thing I added is the outputting of some variables here and there for debug purposes. (which partially helped me).