# Author: Lirui Bi
# Title: One stronger method based upon a Polybius cipher
# Time: 05.12.2021
#--------------------------------------------------------------------
# Create Polybius matrix
Polybius<-matrix(c(NA, "Z", "M", "D", NA, "K", "W", "Q", NA, "G",
                   "V", NA, "A", NA, "R", NA, "E", NA, "T", "O",
                   NA, "J", "I", "S", "B", "P", "Y", NA, "F", NA,
                   "L", NA, NA, "C", NA, "U", "H", "N", NA, "X"),
                 ncol = 10, byrow = T)

# Add row names using rownames()
rownames(Polybius)<-c(0, 1, 2, 3)

# Add column names using colnames()
colnames(Polybius)<-c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

# Display Polybius
Polybius

# Question2
# Create Message vector
Message<-("RAISETHEFLAG")

# Display Message
Message

# Create keyword vector
keyword<-("PEACH")

# Display keyword
keyword

# Create Letter_code1 vector
Letter_code1<-NULL

for (z in 1:nchar(Message)) 
{
  # Extract every letter of Message
  letter<-substring(Message, z, z) 
  
  # Loop to find the position[i,j] of each letter in Polybius
  for (i in 1:nrow(Polybius)) 
  {
    for (j in 1:ncol(Polybius)) 
    {
      # If the element is not NA
      if(!is.na(Polybius[i,j]))
      {
        if(Polybius[i,j] == letter)
        # Update Letter_code1 vector and encrypt the letter
        Letter_code1<-c(Letter_code1, as.numeric(paste(i-1, j-1,
                                            sep="", collapse="")))
      }
    }
  }
}

# Display Letter_code1
Letter_code1   

# Create Letter_code2 vector
Letter_code2<-NULL

for (z in 1:nchar(keyword)) 
{
  # Extract every letter of keyword
  letter<-substring(keyword, z, z) 
  
  # Loop to find the position i,j of each letter in Polybius
  for (i in 1:nrow(Polybius)) 
  {
    for (j in 1:ncol(Polybius)) 
    {
      # If the element is not NA
      if(!is.na(Polybius[i,j]))
      {
        if(Polybius[i,j] == letter)
        # update Letter_code2 vector and encrypt the letter
        Letter_code2<-c(Letter_code2, as.numeric(paste(i-1, j-1,
                                          sep="", collapse="")))
      }
    }
  }
}

# Display Letter_code2
Letter_code2   

# Using keyword to increase letter_code complexity
Adjusted_letter_code<-c(Letter_code2,Letter_code1+Letter_code2)

# Display Adjusted_letter_code
Adjusted_letter_code

# Convert Adjusted_letter_code vector to a long character 
# pre_finaltext vector
pre_finaltext<-paste(Adjusted_letter_code, collapse="")

# Display pre_finaltext
pre_finaltext

# Create finaltext vector
finaltext<-NULL

# Calculate the number of groups of finaltext 
n<-ceiling(nchar(pre_finaltext)/5)

for (a in 1:n) 
{
  # Extract characters from pre_finaltext in groups of 5
  temp<-substring(pre_finaltext, a*5-4, a*5)
  if(nchar(temp)<5) # If the number of chr in temp is less than 5
  {
    b<-5-nchar(temp) # Number of characters to be added to temp
    c<-floor(runif(b, 0, 10)) # Randomly generate b integers from 0-9
    c<-paste(c, collapse="")
    temp<-paste(temp, c, sep = "" ) # Update temp vector
    #print(temp)
    finaltext<-paste(finaltext, temp) # Update finaltext vector
  }
  else
    finaltext<-paste(finaltext, temp) # Update finaltext vector
  
}

# Display finaltext
finaltext

# Question3

# Create Ciphertext vector
Ciphertext<-("48521 82559 53320 83151 44382 13349 40352 42260 48521 84349 48343 23518")

# Display Ciphertext
Ciphertext

# Create pre_adjusted_letter_code vector
pre_adjusted_letter_code<-NULL

# Calculate the number of groups of Ciphertext
n1<-ceiling(nchar(Ciphertext)/6)

for (a in 1:n1) 
{
  # Extract char from Ciphertext in groups of 6(except for space)
  temp<-substring(Ciphertext, a*6-5, a*6-1)
  # Update pre_adjusted_letter_code
  pre_adjusted_letter_code<-paste(pre_adjusted_letter_code, temp, 
                                  sep="", collapse="")
}

# Display pre_adjusted_letter_code
pre_adjusted_letter_code

# Create Adjusted_letter_code vector
Adjusted_letter_code<-NULL

# Calculate the number of digits of Adjusted_letter_code vector
n2<-floor(nchar(pre_adjusted_letter_code)/2)

for (a in 1:n2) 
{ 
  #Extract characters from pre_letter_code in groups of 2 
  #And convert character to numeric 
  Adjusted_letter_code<-as.numeric(c(Adjusted_letter_code, substring
                          (pre_adjusted_letter_code, 2*a-1, 2*a)))
}

# Display Adjusted_letter_code
Adjusted_letter_code

# Create keyword vector
keyword<-("LEMON")

# Create letter_code vector
letter_code<-NULL

for (z in 1:nchar(keyword)) 
{
  #Extract every letter of keyword
  letter<-substring(keyword, z, z) 
  
  #Loop to find the position[i,j] of each letter in Polybius
  for (i in 1:nrow(Polybius)) 
  {
    for (j in 1:ncol(Polybius)) 
    {
      temp<-which(Polybius[i,j] == letter)
      #If the element is not NA
      if(length(temp)!=0 ) 
      {
        # Update letter_code vector and encrypt the letter
        letter_code<-c(letter_code, as.numeric(paste(i-1, j-1,
                                        sep="", collapse="")))
      }
    }
  }
}

# Display letter_code
letter_code

# Subtract the letter code of keyword
pre_letter_code<-c(Adjusted_letter_code-letter_code)

pre_letter_code<-as.character(pre_letter_code)

# Display pre_letter_code
pre_letter_code

#Create plaintext vector
plaintext<-NULL

for (a in 1:length(pre_letter_code)) 
{ 
  # Loop to extract the char in pre_letter_code, and covert the char
  # to numeric
  b<-as.numeric(pre_letter_code[a])
  if(b>0) # b<0 means that b is a randomly added number 
  {
    if(b>=10)
    {
      #Extract i,j from pre_letter_code[a], convert char to numeric
      i<-as.numeric(substring(pre_letter_code[a], 1, 1))
      j<-as.numeric(substring(pre_letter_code[a], 2, 2))
      if (!is.na(Polybius[i+1, j+1]))#Or nchar(Polybius[i+1, j+1])==1)? 
      {
        temp<-Polybius[i+1,j+1]
        # Update plaintext vector
        plaintext<-paste(plaintext, temp, sep="", collapse="") 
      } 
      else
        break #If Polybius[i+1, j+1] is NA, break the loop
    }
    else
    {
      #Extract i,j from pre_letter_code[a], convert char to numeric
      i<-0
      j<-as.numeric(substring(pre_letter_code[a], 1, 1))
      if (!is.na(Polybius[i+1, j+1]))#Or nchar(Polybius[i+1, j+1])==1)? 
        {
          temp<-Polybius[i+1,j+1]
          # Update plaintext vector
          plaintext<-paste(plaintext, temp, sep="", collapse="") 
        } 
      else
        break #If Polybius[i+1, j+1] is NA, break the loop
    }
  }
  else
    break
}

# Display plaintext
plaintext

 
           
           
           
           