Rail Fence Cipher - Criptografia e Descriptografia
Dada uma mensagem de texto simples e uma chave numérica, cifra/decifra o texto fornecido usando o algoritmo Rail Fence.
A cifra da cerca ferroviária (também chamada de cifra em zigue-zague) é uma forma de cifra de transposição. Seu nome deriva da maneira como é codificado.
Exemplos:
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
Criptografia
Em uma cifra de transposição, a ordem dos alfabetos é reorganizada para obter o texto cifrado.
- Na cifra da cerca ferroviária, o texto simples é escrito para baixo e diagonalmente nos trilhos sucessivos de uma cerca imaginária.
- Quando alcançamos o trilho inferior, percorremos para cima movendo-nos diagonalmente. Depois de chegar ao trilho superior, a direção muda novamente. Assim, os alfabetos da mensagem são escritos em zigue-zague.
- Após cada alfabeto ter sido escrito, as linhas individuais são combinadas para obter o texto cifrado.
Por exemplo, se a mensagem for 'GeeksforGeeks' e o número de trilhos = 3, a cifra será preparada como:
.'.Sua criptografia será feita em linha, ou seja, GSGSEKFREKEOE
Descriptografia
Como vimos anteriormente, o número de colunas na cifra da barreira ferroviária permanece igual ao comprimento da mensagem de texto simples. E a chave corresponde ao número de trilhos.
- Portanto, a matriz ferroviária pode ser construída de acordo. Uma vez obtida a matriz, podemos descobrir os locais onde os textos devem ser colocados (usando a mesma forma de mover-se diagonalmente para cima e para baixo alternativamente).
- Em seguida, preenchemos a linha do texto cifrado. Após preenchê-lo percorremos a matriz em zigue-zague para obter o texto original.
Implementação:
Seja cipher-text = 'GsGsekfrek eoe' e Key = 3
- Número de colunas na matriz = len(texto cifrado) = 13
- Número de linhas = chave = 3
Portanto, a matriz original será 3*13, agora marcando lugares com texto como '*' obtemos
* _ _ _ * _ _ _ * _ _ _ *
_ * _ * _ * _ * _ * _ *
_ _ * _ _ _ * _ _ _ * _
C++
Abaixo está um programa para criptografar/descriptografar a mensagem usando o algoritmo acima.
Java// C++ program to illustrate Rail Fence Cipher // Encryption and Decryption #includeusing 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 ; } Python3// 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 JayC## 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 SomwanshiJavaScriptusing 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 )); } }// 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 ));
Saídaatc toctaka ne GsGsekfrek eoe dnhaweedtees alf tl GeeksforGeeks attack at once defend the east wallComplexidade de tempo: O(linha * coluna)
Criar questionário
Espaço Auxiliar: O(linha * coluna)
Referências:
https://en.wikipedia.org/wiki/Rail_fence_cipher
Este artigo é uma contribuição de Ashutosh Kumar