Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm looking to decrypt RC4 encrypted data. I've tried openssl but it doesn't support my key length of 64 bits (my version only has rc4 and rc4-40).

Encrypted data: 6dec8a6b6356b36e1f4c1a94c8f6dd5ddfd60108da479d5b4a8794afa468c7e78cd22946d7

Key: 24641684

The plain text should come out to: ThisIstheOriginaltext=theoriginaltext

Using this website http://rc4.online-domain-tools.com/ I am able to successfuly decrypt the data. However I am struggling to decrypt it in linux without the use of a website tool.

How can I decrypt this in linux?

share|improve this question

migrated from security.stackexchange.com Aug 15 '13 at 13:33

This question came from our site for information security professionals.

It appears that the openssl utility that comes with most Linux distributions wasn't compiled with support for rc4-64.

What you can do is grab the latest source code from the OpenSSL website and compile it yourself.

share|improve this answer
    
Which version? openssl-1.0.1e only contains EVPs EVP_rc4() and EVP_rc4_40(), no mention of an explicit 64-bit variant except in the enc man page, which I suspect might be incorrect. – mr.spuratic Aug 15 '13 at 10:37

The OpenSSL enc utility only supports rc4 which is implicitly 128-bit by default (EVP_rc4()), and rc4-40 (EVP_rc4_40()).

The former supports variable key sizes (via EVP_CIPHER_CTX_set_key_length()) but it seems enc does not support non-default key sizes, and never calls that set-length function. I'm not aware of any CLI tool or perl module which supports this.

Instead, you can trivially amend the do_crypt() RC2 80-bit example in the OpenSSL EVP_EncryptInit man page to do RC4-64 (or any other supported size):

// compile with: gcc -lcrypto -o rc4-64 rc4-64.c 
#include <stdio.h>
#include <openssl/ssl.h>

int main(int argc, char * argv[]) {
    FILE *in,*out; 

    // encrypt
    //in=fopen("rc4.in","r");
    //out=fopen("rc4.out","w");
    //do_crypt(in,out,1);
    //fclose(in); 
    //fclose(out);

    // decrypt
    in=fopen("rc4.out","r");
    out=fopen("rc4.txt","w");
    do_crypt(in,out,0);
    fclose(in); 
    fclose(out);
}

int do_crypt(FILE *in, FILE *out, int do_encrypt)
{
    /* Allow enough space in output buffer for additional block */
    unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
    int inlen, outlen;
    EVP_CIPHER_CTX ctx;

    /* Bogus key and IV: we'd normally set these from
       * another source.  */
    //unsigned char key[] = "0123456789";
    //unsigned char iv[] = "12345678";
    unsigned char key[] = "24641684";
    unsigned char iv[] = "\0\0\0\0\0\0\0\0";

    /* Don't set key or IV because we will modify the parameters */
    EVP_CIPHER_CTX_init(&ctx);

    /* set RC4 with 64-bit key */
    EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, do_encrypt);
    EVP_CIPHER_CTX_set_key_length(&ctx, 64/8)

    /* We finished modifying parameters so now we can set key and IV */

    EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
    for(;;) {
        inlen = fread(inbuf, 1, 1024, in);
        if(inlen <= 0) break;
        if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) {
            /* Error */
            EVP_CIPHER_CTX_cleanup(&ctx);
            return 0;
        }
        fwrite(outbuf, 1, outlen, out);
    }
    if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) {
        /* Error */
        EVP_CIPHER_CTX_cleanup(&ctx);
        return 0;
    }
    fwrite(outbuf, 1, outlen, out);
    EVP_CIPHER_CTX_cleanup(&ctx);
    return 1;
}

(Error checking etc omitted for brevity and clarity - this is not production code)

share|improve this answer

RC4? It should be easy. There is a very short c version that supports any key (hex encoded) length. Just compile like this:

$ gcc -o rc4 -O4 rc4.c

this code:

#define S ,t=s[i],s[i]=s[j],s[j]=t /* rc4 hexkey <file */
unsigned char 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;}

Usage is:

$ rc4 hexkey < input > output

Shamelessly copied from this site:

If you need/want the long version, use this.
This one is more robust, just a little bigger as it is a 2k file of c code.

share|improve this answer

You must log in to answer this question.