> From: owner-openssl-us...@openssl.org On Behalf Of Alexander Voropay
> Sent: Friday, 10 August, 2012 08:24

> How to produce a "canonical" RC4 test vectors as seen on Wikipedia
> 
> http://en.wikipedia.org/wiki/Rc4#Test_vectors
[or RFC6229, referenced therein] 

> Is it possible to produce this result with openssl ? I've tried
<snip>
> $ echo -n Key | od -t x1
> 0000000 4b 65 79
> 0000003
> $ echo -n Plaintext | openssl enc -rc4 -nosalt -nopad -K 4b6579 -iv 00
>  | od -t x1
> 0000000 25 28 47 e2 d8 44 d2 f1 0e
> 0000011
> 
That's the right format (-K in hex). Note that -nosalt 
has no effect when using -K and -nopad has no effect 
with a stream cipher/mode, so those are just clutter.

But, commandline enc does only nominal-length keys (16 bytes 
= 128 bits for rc4). set_hex(hkey,key,sizeof key) doesn't even 
remember the length of the argument. The output you get is 
actually for the key 4b657900 00000000 00000000 00000000, 
and is correct for that.

For many ciphers this makes sense, the key size is fixed by 
the cipher anyway. For variable-key ciphers like rc4 it might 
be a good enhancement to allow -K to control the key length.

You can get your expected result calling EVP with set_key_length, 
or calling the low-level RC4 primitives directly, per attached.
/* OpenSSL RC4 interop (ref AVoropay) DThompson 2012.08.10 */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rc4.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/ssl.h>

typedef unsigned char Uchar;
Uchar key [16], dat [16], iv [1]; /* iv exists but not really used */

void error (const char * what)
{ puts(what); ERR_print_errors_fp(stdout); exit(9); }
int gethex (const char * hex, Uchar * byt, int siz)
{ int i, t; for( i = 0; *hex && i < siz; hex += 2, i++ )
    if( sscanf (hex, "%02hhx%n", byt+i, &t)!=1 || t!=2 ) return -1;
  return *hex? -1 /* overlong */: i; /* valid bytes parsed */
}
void puthex (const Uchar * byt, int siz)
{ while( siz-- ) printf ("%02x ", *byt++); putchar ('\n'); }
int usage (void)
{ puts ("usage: keyhex tascii|hexdata [v=varlen|f=dftlen]"); exit(1); }

int main (int argc, char**argv)
{
  RC4_KEY rc4; int keylen, mode = 0, t1, t2;
  const EVP_CIPHER *ciph; EVP_CIPHER_CTX ctx;
  if( argc < 3 || (keylen = gethex (argv[1], key, 64)) < 0 ) usage();
  if( *argv[2] == 't' ) strncpy (dat, argv[2]+1, sizeof dat);
  else if( gethex (argv[2], dat, 64) < 0 ) usage();
  if( argc > 3 ) mode = *argv[3]; /* omit=raw, 'v'=varlen, other=dftlen */

  if( mode==0 ){
    RC4_set_key (&rc4, keylen, key);
    RC4 (&rc4, sizeof dat, dat, dat);
  }else{
    SSL_load_error_strings();
    OpenSSL_add_ssl_algorithms();
    if( (ciph = EVP_get_cipherbyname("rc4"))==NULL ) error("getbyname");
    if(!EVP_EncryptInit (&ctx, ciph,NULL,NULL)) error("Init1");
    if( mode=='v' )
      if(!EVP_CIPHER_CTX_set_key_length (&ctx, keylen)) error("setklen");
    if(!EVP_EncryptInit (&ctx, NULL,key,iv)) error("Init2");
    if(!EVP_EncryptUpdate (&ctx, dat,&t1, dat,sizeof dat)) error("Upd");
    if(!EVP_EncryptFinal (&ctx, dat+t1,&t2)) error("Final");
    printf ("EVP_(Encrypt) did %d+%d\n", t1,t2);
  }
  puthex (dat, sizeof dat);
  return 0;
}

Reply via email to