S Lazy-H
  • Home
  • About
  • Posts
  • Contact
  • Slide Rules
  • A Biker’s Tale

Casual Cryptography Using R, Updated

ciphers
R Programming
Author

Sam Hutchins

Published

February 5, 2024

I do believe it is time for an update to Casual Cryptography Using R posted last year. I have made some minor changes and will attempt to describe them.

I actually store different elements required by the program in different files. For example, the password file noted in the first post is one, another is the initial lookup table also described in the first post. To prevent confusion, all existing variables are deleted at the start and end of each program segment using rm(list=ls()).

We then check for existing password files and the lookup table, and load if necessary. Then we present a menu of options, primarily Encode and Decode using this snippet of code.

Code
sel <- menu(c("Encode","Decode"))
if(sel==1) {
  # do encoding process
} else {
  # do decoding process
}

Under those two options lie the entire program. Understand that this entire process, except the actual curve25519 encryption, is just another level of encryption on top of the final step.

Alluded to in the first post, the data frame could look like this, or any different combination of alphanumeric characters.

Code
   x1  x2
1   A  21
2   B  12
3   C   4
4   D  10
5   E  15
6   F   2
7   G  20
8   H   9
9   I  11
10  J  23
11  K  14
12  L  25
13  M   6
14  N  19
15  O   1
16  P  22
17  Q   8
18  R  26
19  S  18
20  T   3
21  U  16
22  V   5
23  W  24
24  X  13
25  Y   7
26  Z  17
27     38
28  .  34
29  ,  45
30  -  56
31  :  67
32  ;  78
33  /  89
34  @  99
35  #  98
36  %  87
37  *  76
38  &  65
39  !  54
40  ?  44
41  '  55
42 \\  57
43  |  63
44  ~  73
45  $  83
46  ^  93
47  (  94
48  )  95
49  _  96
50  +  97
51  =  79
52  <  80
53  >  81
54  [  82
55  ]  84
56  {  85
57  }  86
58  0 120
59  1 121
60  2 122
61  3 123
62  4 124
63  5 125
64  6 126
65  7 127
66  8 128
67  9 129

For your own use, you would want to arrange the table in your own order. Notice this table includes punctuation and numbers, and the second column is scrambled. Use any numbers, but ensure you avoid duplicating the numbers for the second column. In this program, both the password and lookup table files are loaded and decrypted as needed. The creation of both are accomplished using separate programs. If you generate a new private key, you must also generate a new lookup table as they are intertwined. I leave this part as an exercise for the reader. However, this program is separate from that process, so you may wish to do something different.

To load those two files, I use something similar to this.

Code
# see if we need a password
if(!exists("pass")) {
    writeLines("Retrieving password.")
    pass %<% "password.file"
    pass <- substr(pass,6,str_length(pass))
}
if(!exists("lookupTable")) {
    writeLines("Retrieving lookup table.")
    bet1 <- safer::retrieve_object(conn="lookupTable.file",key=pass)
}

Notice in the above, the password key is needed to decrypt the lookup table. To ask for a default file or new file for saving or loading the encrypted message, I use this function.

Code
newOld <- function() {
    fileSel <- menu(c("Default filename","New filename"))
    if(fileSel==1) {
        fileName <- 'default.bin'
    } else {
        fileName <- readline(prompt="Enter new filename: ")
    }
    return(fileName)
}

The next part of the program describes the encryption process, which would be placed within the first code snippet at the top of this post where the “# do encoding process” comment is.

Code
phrase <- readline(prompt="Enter text to encode: \n")
    writeLines(paste("Phrase:", phrase))
    phrase1 <- str_to_upper(phrase) # change input to all upper case
    B <- strsplit(phrase1, NULL, perl = TRUE)[[1]]
    n <- length(B) # length of string
    z <- data.frame(x1=1:n,x2=0) # for storing encrypted message
    i <- 1
    while(i<=n) { # lookup table loop using left column (1)
        if(B[i]==" ") {
            z[i,] <- 38 } # space, could be a pre-known variable...
        else {
            z[i,] <- bet1[bet1$x1 %in% B[i],] # select matching number in lookup table 'bet1'
        }
        i <- i+1
    }
    z <- z[,2] # select only second column
    
    # Encryption steps. Could ask for another filename
    fileName <- newOld()
    if(file.exists(fileName)) { # check if file exists
        file.remove(fileName) # if so, remove output file
    }
    safer::save_object(z,conn=fileName,key=pass) # encrypt and save
    rm(list=ls()) # remove variables from memory

Then the opposite function, decrypt a possible existing message file, would be placed within the “# do decoding process” comment location as described before.

Code
# Decryption steps. Could ask for filename
    fileName <- newOld()
    dec <- safer::retrieve_object(conn=fileName,key=pass)
    o <- length(dec) # length of data.frame rows
    msg <- data.frame(x1=1:o,x2=0) # for storing decrypted message
    i <- 1
    while(i<=o) { # lookup table loop using right column (2)
        msg[i,] <- bet1[bet1$x2 %in% dec[i],]
        i <- i+1
    }
    a <- gsub(", ","",toString(msg[,1])) # lookup table results
    #b <- gsub("\\\\", "\\\\", a, fixed=T) # remove double backslash
    # use writeLines instead of print to NOT show double backslashes
    writeLines(paste("Message:", a, "\n")) # show final decoded message
    rm(list=ls()) # remove variables from memory

That’s the basic program. It allows for encrypting or decrypting a default file or another file if the filename is supplied. This could be a message file received remotely, or from the same computer. Remember, for effective communication, both the initiator and recipient would need the same password file and lookup table as described in the first Casual Cryptography Using R post.

© S Lazy-H 2019 -