0

I am trying to create a R function that will take a seed,and key length to generate a RC4 keystream.

The following is what I have so far:

  library(numbers)
    library(seqinr)
    library(compositions)

    rc4_genkey <- function(seed,keylength){
      keystream <- vector(mode="integer", length=keylength)

# initialized S vector
      s <- vector(mode="integer", length=255)
      for(i in 1:255){
      s[i + 1] = i+1
      }

# initialize k vector with seed
      key <- utf8ToInt(seed)
      n <- length(key)
      k <- vector(mode="integer", length=256)
      for (i in 1:255){
      k[i + 1] = key[mod(i+1, n)+1]
      }

# Rc4 algorithm randomize 2 with 256 iterations
      for (i in 1:255){
      j <- (mod(j + s[i+1] + k[i+1], 256))
      swap(s[i + 1], s[j])
      }

# generate keystream of keystream length   
    for(i in 0:length(keystream)){
      i <- mod((i + 1),256)
      j <-  mod((j + s[i]), 256)
      swap(s[i+1],s[j+1])
      t <- mod((s[i] + s[j]),256)
      k[i] <-  s[t]
      keystream[i] <- k[i]
    }
    }

Now every time I run the function, it keeps telling me 
"s[i + 1] <- s[j + 1] : replacement has length zero"

Hoping to get a little help to fix up this to run a proper rc4 encrpytion

Zaid Islam
  • 29
  • 3
  • 1
    Please state all non-base `library` calls and fix code issues as `object 'j' not found` so that someone may replicate your problem. – jay.sf Mar 06 '20 at 08:55
  • 1
    I'm not a programmer in `r` but if I were, I would hope to find well indented & spaced out code. You're trying to do too much in one function, split it up! – Maarten Bodewes Mar 06 '20 at 08:56
  • 1
    Note that RC4 is mainly of historical interest by now. It is an easy cipher to implement, which makes it a good introduction to stream ciphers, I guess. But please don't use it in a modern protocol / use case. It has bias, a tricky key setup and doesn't allow a separate IV... – Maarten Bodewes Mar 06 '20 at 09:40
  • @MaartenBodewes I agree, though unfortunately it is still necessary to have an rc4 implementation for certain tasks such as reading old encrypted pdf files. I think the newer ones use AES – Allan Cameron Mar 06 '20 at 09:43

1 Answers1

2

I think you have made quite a few errors here: rc4 is a symmetric cypher, so your rc4 function should take a message and key (not key length), and return a stream of bytes.

I'm guessing you have tried to translate this function from a lower-level, zero-indexed language into R. Your creation of the state vector s, for example (which in rc4 should start off as 0 to 255) should just be s <- 0:255, not written with a loop.

I have previously written a C++ implementation of rc4, so I have translated it to R here for you.

This function will return a raw vector if there are non-Ascii elements in the result, and a character string otherwise, so most of the time your encrypted message will be in raw format and an unencrypted message will be a character string. It would be easy enough to modify it to accept and return only raw vectors though.

rc4 <- function(message, key)
{
  if(is.raw(message)) message <- as.integer(message)
  if(is.character(message)) message <- utf8ToInt(message)  
  key            <- utf8ToInt(key)
  key_length     <- length(key)
  message_length <- length(message)
  s              <- 0:255
  a <- b <- x <- y <- 0 

  if(key_length == 0) stop("No key given")
  if(message_length == 0) return("")

  for (i in seq_along(s))
  {
    b <- (key[a + 1] + s[i] + b) %% 256
    tmp <- s[i]
    s[i] <- s[b + 1]
    s[b + 1] <- tmp
    a <- (a + 1) %% key_length;
  }

  for (k in seq(message_length))
  {
    x1 <- x <- (x + 1) %% 256
    y1 <- y <- (s[x + 1] + y) %% 256
    tmp <- s[x1]
    s[x1] <- s[y1]
    tmp <- s[y1]
    message[k] = bitwXor(message[k], s[(s[x1 + 1] + s[y1 + 1]) %% 256]);
  }
  if(any(message < 9 | message > 127)) return(as.raw(message))
  return(intToUtf8(message))
}

So lets see if it works:

encrypted_message <- rc4("hello", "world")
encrypted_message
#> [1] b7 31 74 99 98

It should be reversible with the same key:

rc4(encrypted_message, "world")
#> [1] "hello"
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87