ADFGVX cipher: Difference between revisions
Content deleted Content added
VincentARM (talk | contribs) mNo edit summary |
→{{header|Uiua}}: Changed the algorithm |
||
(8 intermediate revisions by 3 users not shown) | |||
Line 1,672:
ATTACKAT1200AM
</pre>
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_set>
#include <vector>
const std::string ADFGVX = "ADFGVX";
const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::random_device random;
std::mt19937 mersenne_twister(random());
std::vector<std::vector<char>> initialise_polybius_square() {
std::vector<char> letters(ALPHABET.begin(), ALPHABET.end());
std::shuffle(letters.begin(), letters.end(), mersenne_twister);
std::vector<std::vector<char>> result = { 6, std::vector<char>(6, 0) };
for ( int32_t row = 0; row < 6; ++row ) {
for ( int32_t column = 0; column < 6; ++column ) {
result[row][column] = letters[6 * row + column];
}
}
return result;
}
// Create a key using a word from the dictionary 'unixdict.txt'
std::string create_key(const uint64_t& size) {
if ( size < 7 || size > 12 ) {
throw std::invalid_argument("Key should contain between 7 and 12 letters, both inclusive.");
}
std::vector<std::string> candidates;
std::fstream file_stream;
file_stream.open("../unixdict.txt");
std::string word;
while ( file_stream >> word ) {
if ( word.length() == size &&
word.length() == std::unordered_set<char>{ word.begin(), word.end() }.size() ) {
std::transform(word.begin(), word.end(), word.begin(), [](const char& ch){ return std::toupper(ch); });
if ( word.find_first_not_of(ALPHABET) == std::string::npos ) {
candidates.emplace_back(word);
}
}
}
std::shuffle(candidates.begin(), candidates.end(), mersenne_twister);
std::string key = candidates[0];
return key;
}
std::string encrypt(const std::string& plain_text,
const std::vector<std::vector<char>>& polybius,
const std::string& key) {
std::string code = "";
for ( const char& ch : plain_text ) {
for ( int32_t row = 0; row < 6; ++row ) {
for ( int32_t column = 0; column < 6; ++column ) {
if ( polybius[row][column] == ch ) {
code += ADFGVX[row];
code += ADFGVX[column];
}
}
}
}
std::string encrypted = "";
for ( const char& ch : key ) {
for ( uint64_t i = key.find(ch); i < code.length(); i += key.length() ) {
encrypted += code[i];
}
encrypted += " ";
}
return encrypted;
}
std::string decrypt(const std::string& encrypted_text,
const std::vector<std::vector<char>>& polybius,
const std::string& key) {
const uint64_t space_count = std::count(encrypted_text.begin(), encrypted_text.end(), ' ');
const uint64_t code_size = encrypted_text.length() - space_count;
std::vector<std::string> blocks;
std::stringstream stream(encrypted_text);
std:: string word;
while ( stream >> word ) {
blocks.emplace_back(word);
}
std::string code = "";
for ( int32_t i = 0; code.length() < code_size; ++i ) {
for ( const std::string& block : blocks ) {
if ( code.length() < code_size ) {
code += block[i];
}
}
}
std::string plain_text = "";
for ( uint64_t i = 0; i < code_size - 1; i += 2 ) {
int32_t row = ADFGVX.find(code[i]);
int32_t column = ADFGVX.find(code[i + 1]);
plain_text += polybius[row][column];
}
return plain_text;
}
int main() {
const std::vector<std::vector<char>> polybius = initialise_polybius_square();
std::cout << "The 6 x 6 Polybius square:" << std::endl;
std::cout << " | A D F G V X" << std::endl;
std::cout << "--------------" << std::endl;
for ( int32_t row = 0; row < 6; ++row ) {
std::cout << ADFGVX[row] << "|";
for ( int32_t column = 0; column < 6; ++column ) {
std::cout << " " << polybius[row][column];
}
std::cout << std::endl;
}
std::cout << std::endl;
const std::string key = create_key(9);
std::cout << "The key is " << key << std::endl << std::endl;
const std::string plain_text = "ATTACKAT1200AM";
std::cout << "Plain text: " << plain_text <<std::endl << std::endl;
const std::string encrypted_text = encrypt(plain_text, polybius, key);
std::cout << "Encrypted: " << encrypted_text << std::endl << std::endl;
const std::string decrypted_text = decrypt(encrypted_text, polybius, key);
std::cout << "Decrypted: " << decrypted_text << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
The 6 x 6 Polybius square:
| A D F G V X
--------------
A| X Q I Z 1 K
D| A O Y 2 S 5
F| G 7 J R 9 T
G| 0 3 E P C V
V| N 6 D L H B
X| U 4 F W M 8
The key is HORSETAIL
Plain text: ATTACKAT1200AM
Encrypted: DVDV AAG FXG XDA FAG XFA DXD AAA GVX
Decrypted: ATTACKAT1200AM
</pre>
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
Line 1,945 ⟶ 2,103:
(Technically, we do not need the Polybius square to recover the spaces, but it's passed as an argument here for symmetry.)
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public final class ADFGVXCipher {
public static void main(String[] args) throws IOException {
final char[][] polybius = initialisePolybiusSquare();
System.out.println("The 6 x 6 Polybius square:");
System.out.println(" | A D F G V X");
System.out.println("--------------");
for ( int row = 0; row < 6; row++ ) {
System.out.print(ADFGVX.charAt(row) + "|");
for ( int column = 0; column < 6; column++ ) {
System.out.print(" " + polybius[row][column]);
}
System.out.println();
}
System.out.println();
final String key = createKey(9);
System.out.println("The key is " + key);
System.out.println();
final String plainText = "ATTACKAT1200AM";
System.out.println("Plain text: " + plainText);
System.out.println();
final String encryptedText = encrypt(plainText, polybius, key);
System.out.println("Encrypted: " + encryptedText);
System.out.println();
final String decryptedText = decrypt(encryptedText, polybius, key);
System.out.println("Decrypted: " + decryptedText);
}
private static String encrypt(String plainText, char[][] polybius, String key) {
String code = "";
for ( char ch : plainText.toCharArray() ) {
for ( int row = 0; row < 6; row++ ) {
for ( int column = 0; column < 6; column++ ) {
if ( polybius[row][column] == ch ) {
code += ADFGVX.charAt(row) + "" + ADFGVX.charAt(column);
}
}
}
}
String encrypted = "";
for ( char ch : key.toCharArray() ) {
for ( int i = key.indexOf(ch); i < code.length(); i += key.length() ) {
encrypted += code.charAt(i);
}
encrypted += " ";
}
return encrypted;
}
private static String decrypt(String encryptedText, char[][] polybius, String key) {
final int codeSize = encryptedText.replace(" ", "").length();
String code = "";
for ( int i = 0; code.length() < codeSize; i++ ) {
for ( String block : encryptedText.split(" ") ) {
if ( code.length() < codeSize ) {
code += block.charAt(i);
}
}
}
String plainText = "";
for ( int i = 0; i < codeSize - 1; i += 2 ) {
int row = ADFGVX.indexOf(code.substring(i, i + 1));
int column = ADFGVX.indexOf(code.substring(i + 1, i + 2));
plainText += polybius[row][column];
}
return plainText;
}
// Create a key using a word from the dictionary 'unixdict.txt'
private static String createKey(int size) throws IOException {
if ( size < 7 || size > 12 ) {
throw new AssertionError("Key should contain between 7 and 12 letters, both inclusive.");
}
List<String> candidates = Files.lines(Path.of("unixdict.txt"))
.filter( word -> word.length() == size )
.filter( word -> word.chars().distinct().count() == word.length() )
.filter( word -> word.chars().allMatch(Character::isLetterOrDigit) )
.collect(Collectors.toList());
Collections.shuffle(candidates);
return candidates.get(0).toUpperCase();
}
private static char[][] initialisePolybiusSquare() {
List<String> letters = Arrays.asList("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split(""));
Collections.shuffle(letters);
char[][] result = new char[6][6];
for ( int row = 0; row < 6; row++ ) {
for ( int column = 0; column < 6; column++ ) {
result[row][column] = letters.get(6 * row + column).charAt(0);
}
}
return result;
}
private static final String ADFGVX = "ADFGVX";
}
</syntaxhighlight>
{{ out }}
<pre>
The 6 x 6 Polybius square:
| A D F G V X
--------------
A| 2 K 4 Q 9 8
D| W C I M V A
F| 5 S 0 Y B D
G| F T O U J E
V| 6 1 R X 3 G
X| H L Z P 7 N
The key is DISHWATER
Plaintext: ATTACKAT1200AM
Encrypted: DDAG XAA GDF DDF GXF DGF DDD XVX DDD
Decrypted: ATTACKAT1200AM
</pre>
=={{header|Julia}}==
Line 2,441 ⟶ 2,733:
Encoded: DVVA FVX XXA FGF XVX GXA XXD GFA XXD
</pre>
=={{header|REXX}}==
<syntaxhighlight lang="rexx">
/* REXX */
cls
eol=x2c(0D0A) ; msg="ATTACKAT1200AM"
keyword= upper('lifeguard') ; cyph= 'ADFGVX'
s_sort= keyword ; new_key= ''
do while length(s_sort) > 0
nmax= 0
do i=1 to length(s_sort)
ch= substr(s_sort,i,1)
num= c2d(ch)
if num > nmax then do
nmax= num
max_i = i
end
end
s_sort= delstr(s_sort,max_i,1)
new_key= d2c(nmax)||new_key
end /* Alphabetical sorting */
j=0 ; num_str= '' ; rnd_s= ''
do while j < 36
num= random(0,35)
if wordpos(num,num_str) = 0 then do
j= j + 1
num_str= num_str||num||' '
if num >= 10 then do
num= num - 10 + x2d(41)
num= d2c(num)
end
rnd_s= rnd_s||num
end
end /* say 'Generated string: '||rnd_s||eol */
say 'Polybius square:'||eol
call tab cyph, rnd_s ,1
say "Only characters from the '"|| msg||"'"||eol
t= translate(rnd_s,' ',msg)
_t= translate(rnd_s,' ',t)
call tab cyph, _t ,1
len_c= length(cyph) ; cyph_T=''
do i=1 to len_c
ch_i= substr(cyph,i,1)
do j=1 to len_c
ch_j= substr(cyph,j,1)
cyph_T= cyph_T||ch_i||ch_j||' '
end
end
enc_msg= ''
do i=1 to length(msg)
ch= substr(msg,i,1)
j= pos(ch,rnd_s,1)
enc_msg= enc_msg||word(cyph_T,j)
end
say "Conversion by table: "||eol||eol||msg||" ==> "||enc_msg||eol
call tab keyword, enc_msg
len= length(keyword)
n_row= 0 ; column.= ''
do while enc_msg <> ''
parse var enc_msg 1 s1 +(len) enc_msg
n_row= n_row+1
do m= 1 to len
ch_m= substr(s1,m,1)
column.m= column.m||ch_m
end
end
s_lst= ''
do m= 1 to len
ch= substr(new_key,m,1)
i= pos(ch,keyword,1)
w_i= column.i
s_lst= s_lst||w_i||' '
end
row.= '' ; t_row= ''
do i=1 to len
w_i= word(s_lst,i)
do j=1 to n_row
row.j= row.j||substr(w_i,j,1)
end
end
do j=1 to n_row; t_row= t_row||row.j; end
say "Sorted by columns:"||eol
call tab new_key, t_row
say '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
say 'Encrypted message: '||s_lst
say '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
exit
tab:
parse arg h, s, p /* header, string, param */
lh= length(h) ;
s= h||copies('-',lh)||s ; ls= length(s)
h=' -'||h
t= '' ; j= 1
do i= 1 to ls by lh
row= substr(s,i,lh)
r_ch= ''
do l=1 to lh
ch= substr(row,l,1)
r_ch= r_ch||ch||' '
end
row= r_ch
if p <> '' then row= row||'|'||substr(h,j,1)
t= t||row||eol
j= j + 1
end
say t
return
</syntaxhighlight>
{{out}}
<pre>
Polybius square:
A D F G V X |
- - - - - - |-
D H 8 P U 4 |A
E T S C 5 9 |D
A 3 Z F R I |F
Y O 1 Q 7 W |G
J 2 G V N X |V
L 6 0 K M B |X
Only characters from the 'ATTACKAT1200AM'
A D F G V X |
- - - - - - |-
|A
T C |D
A |F
1 |G
2 |V
0 K M |X
Conversion by table:
ATTACKAT1200AM ==> FADDDDFADGXGFADDGFVDXFXFFAXV
L I F E G U A R D
- - - - - - - - -
F A D D D D F A D
G X G F A D D G F
V D X F X F F A X
V
Sorted by columns:
A D E F G I L R U
- - - - - - - - -
F D D D D A F A D
D F F G A X G G D
F X F X X D V A F
V
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Encrypted message: FDF DFX DFF DGX DAX AXD FGVV AGA DDF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</pre>
Line 2,605 ⟶ 3,067:
Decoded: ATTACKAT1200AM</pre>
=={{header|Uiua}}==
Quick and simple solution for demonstration purposes.
<syntaxhighlight lang="uiua">
A ← ↯∞_2⊞⊟."ADFGVX"
P ← ⊏⍏[⍥⚂]⧻."ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
K ← "PACKHORSE"
Sw ← ⊜□≠" ".
Polybius ← setinv(/⊂⊡≡(⊚⌕):⊙:¤P A|⊏:P≡(⊢⊚⌕)⊙¤∩≡□↯∞_2:A)
SortByK ← setinv(⊏⍏⟜(⍉⬚" "↯⊟∞⧻)K|▽≠" "./⊂⍉⊏⍏⍏K)
Str ← setinv(/$"_ _"Sw/⊂≡(⊂:" ")|≡(⊢°□◇⬚" "↯⊟∞)/↥≡◇⧻.Sw)
Pt ← "ATTACKAT1200AM"
&p $"Key = _\nPolybius:\n_\nPlaintext = _"K↯⊟.√⧻.P Pt
&p$"Crypttext = _". Str SortByK Polybius Pt
&p$"Plaintext = _" °Polybius °SortByK °Str
</syntaxhighlight>
{{out}}
<pre>
Key = PACKHORSE
Polybius:
╭─
╷ "7ENLUB"
"WOJ69G"
"8ZFAKP"
"I4R3C1"
"V5TMHD"
"SY0XQ2"
╯
Plaintext = ATTACKAT1200AM
Crypttext = GFX VVX GXV VGX FFF FVF FVXG FFF GGG
Plaintext = ATTACKAT1200AM
</pre>
=={{header|Wren}}==
Line 2,610 ⟶ 3,105:
{{libheader|Wren-seq}}
{{libheader|Wren-str}}
<syntaxhighlight lang="
import "./ioutil" for FileUtil
import "./seq" for Lst
import "./str" for Char, Str
var rand = Random.new()
Line 2,736 ⟶ 3,231:
Decrypted : ATTACKAT1200AM
</pre>
|