logo

레일펜스 암호 - 암호화 및 복호화

일반 텍스트 메시지와 숫자 키가 주어지면 Rail Fence 알고리즘을 사용하여 주어진 텍스트를 암호화/해독합니다. 
레일펜스 암호(지그재그 암호라고도 함)는 전치 암호의 한 형태입니다. 인코딩되는 방식에서 이름이 파생됩니다. 
예:  

    Encryption     
Input : 'GeeksforGeeks '
Key = 3
Output : GsGsekfrek eoe
Decryption
Input : GsGsekfrek eoe
Key = 3
Output : 'GeeksforGeeks '

Encryption
Input : 'defend the east wall'
Key = 3
Output : dnhaweedtees alf tl
Decryption
Input : dnhaweedtees alf tl
Key = 3
Output : defend the east wall

Encryption
Input : 'attack at once'
Key = 2
Output : atc toctaka ne
Decryption
Input : 'atc toctaka ne'
Key = 2
Output : attack at once

암호화

전치암호에서는 알파벳의 순서를 재배열하여 암호문을 얻는다. 



  • 레일 펜스 암호에서 일반 텍스트는 가상 펜스의 연속 레일에 아래쪽 대각선으로 기록됩니다.
  • 하단 레일에 도달하면 상단 레일에 도달한 후 방향이 다시 바뀌어 대각선으로 위쪽으로 이동합니다. 따라서 메시지의 알파벳은 지그재그 방식으로 작성됩니다.
  • 각 알파벳이 작성된 후 개별 행이 결합되어 암호문을 얻습니다.


예를 들어 메시지가 'GeeksforGeeks'이고 레일 수가 3인 경우 암호는 다음과 같이 준비됩니다. 
 

레일펜스 알고리즘' src='//techcodeview.com/img/dsa/69/rail-fence-cipher-encryption-and-decryption.webp' title=.'.암호화는 행 방식으로 수행됩니다(예: GSGSEKFREKEOE).


 

암호 해독

앞서 살펴본 것처럼 레일 펜스 암호의 열 수는 일반 텍스트 메시지의 길이와 동일하게 유지됩니다. 그리고 키는 레일 수에 해당합니다.
 

  • 따라서 레일 매트릭스는 이에 따라 구성될 수 있습니다. 행렬을 얻은 후에는 텍스트를 배치해야 하는 지점을 알아낼 수 있습니다(대각선 위아래로 번갈아 이동하는 동일한 방법을 사용).
  • 그런 다음 암호문 행을 순서대로 채웁니다. 그것을 채운 후 지그재그 방식으로 행렬을 탐색하여 원본 텍스트를 얻습니다.


구현: 
암호문 = 'GsGsekfrek eoe' 및 키 = 3이라고 가정합니다. 
 

  • 행렬의 열 수 = len(cipher-text) = 13
  • 행 수 = 키 = 3


따라서 원래 행렬은 3*13이 되며 이제 텍스트가 있는 장소를 '*'로 표시합니다. 
 

* _ _ _ * _ _ _ * _ _ _ *  
_ * _ * _ * _ * _ * _ *
_ _ * _ _ _ * _ _ _ * _


다음은 위의 알고리즘을 사용하여 메시지를 암호화/복호화하는 프로그램입니다. 
 

C++
// C++ program to illustrate Rail Fence Cipher // Encryption and Decryption #include    using namespace std; // function to encrypt a message string encryptRailFence(string text int key) {  // create the matrix to cipher plain text  // key = rows  length(text) = columns  char rail[key][(text.length())];  // filling the rail matrix to distinguish filled  // spaces from blank ones  for (int i=0; i < key; i++)  for (int j = 0; j < text.length(); j++)  rail[i][j] = 'n';  // to find the direction  bool dir_down = false;  int row = 0 col = 0;  for (int i=0; i < text.length(); i++)  {  // check the direction of flow  // reverse the direction if we've just  // filled the top or bottom rail  if (row == 0 || row == key-1)  dir_down = !dir_down;  // fill the corresponding alphabet  rail[row][col++] = text[i];  // find the next row using direction flag  dir_down?row++ : row--;  }  //now we can construct the cipher using the rail matrix  string result;  for (int i=0; i < key; i++)  for (int j=0; j < text.length(); j++)  if (rail[i][j]!='n')  result.push_back(rail[i][j]);  return result; } // This function receives cipher-text and key // and returns the original text after decryption string decryptRailFence(string cipher int key) {  // create the matrix to cipher plain text  // key = rows  length(text) = columns  char rail[key][cipher.length()];  // filling the rail matrix to distinguish filled  // spaces from blank ones  for (int i=0; i < key; i++)  for (int j=0; j < cipher.length(); j++)  rail[i][j] = 'n';  // to find the direction  bool dir_down;  int row = 0 col = 0;  // mark the places with '*'  for (int i=0; i < cipher.length(); i++)  {  // check the direction of flow  if (row == 0)  dir_down = true;  if (row == key-1)  dir_down = false;  // place the marker  rail[row][col++] = '*';  // find the next row using direction flag  dir_down?row++ : row--;  }  // now we can construct the fill the rail matrix  int index = 0;  for (int i=0; i<key; i++)  for (int j=0; j<cipher.length(); j++)  if (rail[i][j] == '*' && index<cipher.length())  rail[i][j] = cipher[index++];  // now read the matrix in zig-zag manner to construct  // the resultant text  string result;  row = 0 col = 0;  for (int i=0; i< cipher.length(); i++)  {  // check the direction of flow  if (row == 0)  dir_down = true;  if (row == key-1)  dir_down = false;  // place the marker  if (rail[row][col] != '*')  result.push_back(rail[row][col++]);  // find the next row using direction flag  dir_down?row++: row--;  }  return result; } //driver program to check the above functions int main() {  cout << encryptRailFence('attack at once' 2) << endl;  cout << encryptRailFence('GeeksforGeeks ' 3) << endl;  cout << encryptRailFence('defend the east wall' 3) << endl;  //Now decryption of the same cipher-text  cout << decryptRailFence('GsGsekfrek eoe'3) << endl;  cout << decryptRailFence('atc toctaka ne'2) << endl;  cout << decryptRailFence('dnhaweedtees alf tl'3) << endl;  return 0; } 
Java
// Java program to illustrate Rail Fence Cipher // Encryption and Decryption import java.util.Arrays; class RailFence {  // function to encrypt a message  public static String encryptRailFence(String text  int key)  {  // create the matrix to cipher plain text  // key = rows  length(text) = columns  char[][] rail = new char[key][text.length()];  // filling the rail matrix to distinguish filled  // spaces from blank ones  for (int i = 0; i < key; i++)  Arrays.fill(rail[i] 'n');  boolean dirDown = false;  int row = 0 col = 0;  for (int i = 0; i < text.length(); i++) {  // check the direction of flow  // reverse the direction if we've just  // filled the top or bottom rail  if (row == 0 || row == key - 1)  dirDown = !dirDown;  // fill the corresponding alphabet  rail[row][col++] = text.charAt(i);  // find the next row using direction flag  if (dirDown)  row++;  else  row--;  }  // now we can construct the cipher using the rail  // matrix  StringBuilder result = new StringBuilder();  for (int i = 0; i < key; i++)  for (int j = 0; j < text.length(); j++)  if (rail[i][j] != 'n')  result.append(rail[i][j]);  return result.toString();  }  // This function receives cipher-text and key  // and returns the original text after decryption  public static String decryptRailFence(String cipher  int key)  {  // create the matrix to cipher plain text  // key = rows  length(text) = columns  char[][] rail = new char[key][cipher.length()];  // filling the rail matrix to distinguish filled  // spaces from blank ones  for (int i = 0; i < key; i++)  Arrays.fill(rail[i] 'n');  // to find the direction  boolean dirDown = true;  int row = 0 col = 0;  // mark the places with '*'  for (int i = 0; i < cipher.length(); i++) {  // check the direction of flow  if (row == 0)  dirDown = true;  if (row == key - 1)  dirDown = false;  // place the marker  rail[row][col++] = '*';  // find the next row using direction flag  if (dirDown)  row++;  else  row--;  }  // now we can construct the fill the rail matrix  int index = 0;  for (int i = 0; i < key; i++)  for (int j = 0; j < cipher.length(); j++)  if (rail[i][j] == '*'  && index < cipher.length())  rail[i][j] = cipher.charAt(index++);  StringBuilder result = new StringBuilder();  row = 0;  col = 0;  for (int i = 0; i < cipher.length(); i++) {  // check the direction of flow  if (row == 0)  dirDown = true;  if (row == key - 1)  dirDown = false;  // place the marker  if (rail[row][col] != '*')  result.append(rail[row][col++]);  // find the next row using direction flag  if (dirDown)  row++;  else  row--;  }  return result.toString();  }  // driver program to check the above functions  public static void main(String[] args)  {  // Encryption  System.out.println('Encrypted Message: ');  System.out.println(  encryptRailFence('attack at once' 2));  System.out.println(  encryptRailFence('GeeksforGeeks ' 3));  System.out.println(  encryptRailFence('defend the east wall' 3));  // Now decryption of the same cipher-text  System.out.println('nDecrypted Message: ');  System.out.println(  decryptRailFence('atc toctaka ne' 2));  System.out.println(  decryptRailFence('GsGsekfrek eoe' 3));  System.out.println(  decryptRailFence('dnhaweedtees alf tl' 3));  } } // This code is contributed by Jay 
Python3
# Python3 program to illustrate # Rail Fence Cipher Encryption # and Decryption # function to encrypt a message def encryptRailFence(text key): # create the matrix to cipher # plain text key = rows  # length(text) = columns # filling the rail matrix # to distinguish filled # spaces from blank ones rail = [['n' for i in range(len(text))] for j in range(key)] # to find the direction dir_down = False row col = 0 0 for i in range(len(text)): # check the direction of flow # reverse the direction if we've just # filled the top or bottom rail if (row == 0) or (row == key - 1): dir_down = not dir_down # fill the corresponding alphabet rail[row][col] = text[i] col += 1 # find the next row using # direction flag if dir_down: row += 1 else: row -= 1 # now we can construct the cipher # using the rail matrix result = [] for i in range(key): for j in range(len(text)): if rail[i][j] != 'n': result.append(rail[i][j]) return('' . join(result)) # This function receives cipher-text # and key and returns the original # text after decryption def decryptRailFence(cipher key): # create the matrix to cipher # plain text key = rows  # length(text) = columns # filling the rail matrix to # distinguish filled spaces # from blank ones rail = [['n' for i in range(len(cipher))] for j in range(key)] # to find the direction dir_down = None row col = 0 0 # mark the places with '*' for i in range(len(cipher)): if row == 0: dir_down = True if row == key - 1: dir_down = False # place the marker rail[row][col] = '*' col += 1 # find the next row # using direction flag if dir_down: row += 1 else: row -= 1 # now we can construct the # fill the rail matrix index = 0 for i in range(key): for j in range(len(cipher)): if ((rail[i][j] == '*') and (index < len(cipher))): rail[i][j] = cipher[index] index += 1 # now read the matrix in # zig-zag manner to construct # the resultant text result = [] row col = 0 0 for i in range(len(cipher)): # check the direction of flow if row == 0: dir_down = True if row == key-1: dir_down = False # place the marker if (rail[row][col] != '*'): result.append(rail[row][col]) col += 1 # find the next row using # direction flag if dir_down: row += 1 else: row -= 1 return(''.join(result)) # Driver code if __name__ == '__main__': print(encryptRailFence('attack at once' 2)) print(encryptRailFence('GeeksforGeeks ' 3)) print(encryptRailFence('defend the east wall' 3)) # Now decryption of the # same cipher-text print(decryptRailFence('GsGsekfrek eoe' 3)) print(decryptRailFence('atc toctaka ne' 2)) print(decryptRailFence('dnhaweedtees alf tl' 3)) # This code is contributed # by Pratik Somwanshi 
C#
using System; class GFG_RailFence {  // function to encrypt a message  public static string EncryptRailFence(string text int key) {  // create the matrix to cipher plain text  // key = rows length(text) = columns  char[] rail = new char[key text.Length];  // filling the rail matrix to distinguish filled  // spaces from blank ones  for (int i = 0; i < key; i++)  for (int j = 0; j < text.Length; j++)  rail[i j] = 'n';  bool dirDown = false;  int row = 0 col = 0;  for (int i = 0; i < text.Length; i++) {  // check the direction of flow  // reverse the direction if we've just  // filled the top or bottom rail  if (row == 0 || row == key - 1)  dirDown = !dirDown;  // fill the corresponding alphabet  rail[row col++] = text[i];  // find the next row using direction flag  if (dirDown)  row++;  else  row--;  }  // now we can construct the cipher using the rail  // matrix  string result = '';  for (int i = 0; i < key; i++)  for (int j = 0; j < text.Length; j++)  if (rail[i j] != 'n')  result += rail[i j];  return result;  }  // This function receives cipher-text and key  // and returns the original text after decryption  public static string DecryptRailFence(string cipher int key) {  // create the matrix to cipher plain text  // key = rows length(text) = columns  // create the matrix to cipher plain text  // key = rows  length(text) = columns  char[] rail = new char[key cipher.Length];  // filling the rail matrix to distinguish filled  // spaces from blank ones  for (int i = 0; i < key; i++)  for (int j = 0; j < cipher.Length; j++)  rail[i j] = 'n';  // to find the direction  bool dirDown = true;  int row = 0 col = 0;  // mark the places with '*'  for (int i = 0; i < cipher.Length; i++) {  // check the direction of flow  if (row == 0)  dirDown = true;  if (row == key - 1)  dirDown = false;  // place the marker  rail[row col++] = '*';  // find the next row using direction flag  if (dirDown)  row++;  else  row--;  }  // now we can construct the fill the rail matrix  int index = 0;  for (int i = 0; i < key; i++)  for (int j = 0; j < cipher.Length; j++)  if (rail[i j] == '*' && index < cipher.Length)  rail[i j] = cipher[index++];  // create the result string  string result = '';  row = 0;  col = 0;  // iterate through the rail matrix  for (int i = 0; i < cipher.Length; i++) {  // check the direction of flow  if (row == 0)  dirDown = true;  if (row == key - 1)  dirDown = false;  // place the marker  if (rail[row col] != '*')  result += rail[row col++];  // find the next row using direction flag  if (dirDown)  row++;  else  row--;  }  return result;  }  // driver program to check the above functions  public static void Main() {  // Encryption  Console.WriteLine('Encrypted Message: ');  Console.WriteLine(EncryptRailFence('attack at once' 2));  Console.WriteLine(  EncryptRailFence('GeeksforGeeks ' 3));  Console.WriteLine(  EncryptRailFence('defend the east wall' 3));  // Now decryption of the same cipher-text  Console.WriteLine('nDecrypted Message: ');  Console.WriteLine(  DecryptRailFence('atc toctaka ne' 2));  Console.WriteLine(  DecryptRailFence('GsGsekfrek eoe' 3));  Console.WriteLine(  DecryptRailFence('dnhaweedtees alf tl' 3));  } } 
JavaScript
// function to encrypt a message function encryptRailFence(text key) {  // create the matrix to cipher plain text  // key = rows  text.length = columns  let rail = new Array(key).fill().map(() => new Array(text.length).fill('n'));  // filling the rail matrix to distinguish filled  // spaces from blank ones  let dir_down = false;  let row = 0 col = 0;  for (let i = 0; i < text.length; i++) {  // check the direction of flow  // reverse the direction if we've just  // filled the top or bottom rail  if (row == 0 || row == key - 1) dir_down = !dir_down;  // fill the corresponding alphabet  rail[row][col++] = text[i];  // find the next row using direction flag  dir_down ? row++ : row--;  }  // now we can construct the cipher using the rail matrix  let result = '';  for (let i = 0; i < key; i++)  for (let j = 0; j < text.length; j++)  if (rail[i][j] != 'n') result += rail[i][j];  return result; } // function to decrypt a message function decryptRailFence(cipher key) {  // create the matrix to cipher plain text  // key = rows  text.length = columns  let rail = new Array(key).fill().map(() => new Array(cipher.length).fill('n'));  // filling the rail matrix to mark the places with '*'  let dir_down = false;  let row = 0 col = 0;  for (let i = 0; i < cipher.length; i++) {  // check the direction of flow  if (row == 0) dir_down = true;  if (row == key - 1) dir_down = false;  // place the marker  rail[row][col++] = '*';  // find the next row using direction flag  dir_down ? row++ : row--;  }  // now we can construct the rail matrix by filling the marked places with cipher text  let index = 0;  for (let i = 0; i < key; i++)  for (let j = 0; j < cipher.length; j++)  if (rail[i][j] == '*' && index < cipher.length) rail[i][j] = cipher[index++];  // now read the matrix in zig-zag manner to construct the resultant text  let result = '';  row = 0 col = 0;  for (let i = 0; i < cipher.length; i++) {  // check the direction of flow  if (row == 0) dir_down = true;  if (row == key - 1) dir_down = false;  // place the marker  if (rail[row][col] != '*') result += rail[row][col++];  // find the next row using direction flag  dir_down ? row++ : row--;  }  return result; } // driver program to check the above functions  // Encryption console.log(encryptRailFence('attack at once' 2));  console.log(encryptRailFence('GeeksforGeeks' 3));  console.log(encryptRailFence('defend the east wall' 3)); // Now decryption of the same cipher-text console.log(decryptRailFence('GsGsekfrek eoe' 3)); console.log(decryptRailFence('atc toctaka ne' 2)); console.log(decryptRailFence('dnhaweedtees alf tl' 3)); 

산출
atc toctaka ne GsGsekfrek eoe dnhaweedtees alf tl GeeksforGeeks attack at once defend the east wall 

시간 복잡도: O(행*열)
보조 공간: O(행*열) 
참고자료: 
https://en.wikipedia.org/wiki/Rail_fence_cipher
이 기사는 기고자: 아슈토시 쿠마르

 

퀴즈 만들기