ADFGVX cipher: Difference between revisions

m
(add task to arm assembly raspberry pi)
m (→‎{{header|Wren}}: Minor tidy)
 
(8 intermediate revisions by 3 users not shown)
Line 116:
 
Decrypted : ATTACKAT1200AM
</pre>
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> }}
<syntaxhighlight lang AArch64 Assembly>
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program adfgvx64.s */
/* remark 1 : At each launch, the random values are identical.
To change them, modify the value of the seed (graine) */
/* remark 2 : this program not run in android with termux
because the call system stats is not find */
 
/************************************/
/* Constantes */
/************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
 
.equ SIZE, 6
.equ SIZEC, SIZE * SIZE
.equ KEYSIZE, 9
.equ FSTAT, 80
.equ O_RDWR, 0x0002 // open for reading and writing
 
/*******************************************/
/* Structures **/
/*******************************************/
/* structure de type stat 64 bits : infos fichier */
.struct 0
Stat_dev_t: // ID of device containing file
.struct Stat_dev_t + 8
Stat_ino_t: // inode
.struct Stat_ino_t + 4
Stat_mode_t: // File type and mode
.struct Stat_mode_t + 4
Stat_nlink_t: // Number of hard links
.struct Stat_nlink_t + 4
Stat_uid_t: // User ID of owner
.struct Stat_uid_t + 8
Stat_gid_t: // Group ID of owner
.struct Stat_gid_t + 8
Stat_rdev_t: // Device ID (if special file)
.struct Stat_rdev_t + 8
Stat_size_deb: // la taille est sur 8 octets si gros fichiers
.struct Stat_size_deb + 4
Stat_size_t: // Total size, in bytes
.struct Stat_size_t + 4
Stat_blksize_t: // Block size for filesystem I/O
.struct Stat_blksize_t + 4
Stat_blkcnt_t: // Number of 512B blocks allocated
.struct Stat_blkcnt_t + 4
Stat_atime: // date et heure fichier
.struct Stat_atime + 8
Stat_mtime: // date et heure modif fichier
.struct Stat_atime + 8
Stat_ctime: // date et heure creation fichier
.struct Stat_atime + 8
Stat_Fin:
 
 
/*********************************/
/* Initialized data */
/*********************************/
.data
szText: .asciz "ATTACKAT1200AM"
//szText: .asciz "ABCDEFGHIJ"
szMessOpen: .asciz "File open error.\n"
szMessStat: .asciz "File information error.\n"
szMessRead: .asciz "File read error.\n"
szMessClose: .asciz "File close error.\n"
szMessDecryptText: .asciz "Decrypted text :\n"
szMessCryptText: .asciz "Encrypted text :\n"
szMessErrorChar: .asciz "Character text not Ok!\n"
szFileName: .asciz "unixdict.txt"
szMessPolybius: .asciz "6 x 6 Polybius square:\n"
szTitle: .asciz " | A D F G V X\n---------------\n"
szLine1: .asciz "A | \n"
szLine2: .asciz "D | \n"
szLine3: .asciz "F | \n"
szLine4: .asciz "G | \n"
szLine5: .asciz "V | \n"
szLine6: .asciz "X | \n"
szListCharCode: .asciz "ADFGVX"
szListChar: .asciz "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
.equ LGLISTCHAR, . - szListChar - 1
szMessStart: .asciz "Program 64 bits start.\n"
szCarriageReturn: .asciz "\n"
.align 4
 
qGraine: .quad 1234567 // random init
 
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
sKeyWord: .skip 16
sKeyWordSorted: .skip 16
tabPolybius: .skip SIZE * SIZE + 4
sBuffer: .skip 1000
sBuffex1: .skip 1000
sBuffex2: .skip 1000
tabPosit: .skip 16
tabPositInv: .skip 16
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: // entry of program
ldr x0,qAdrszMessStart
bl affichageMess
bl createPolybius // create 6*6 polybius
 
ldr x0,qAdrsKeyWord
bl generateKey // generate key
cmp x0,#-1 // file error ?
beq 100f
bl affichageMess // display key
ldr x0,qAdrszCarriageReturn
bl affichageMess
ldr x0,qAdrszMessCryptText
bl affichageMess
ldr x0,qAdrszText // text encrypt
ldr x1,qAdrtabPolybius
ldr x2,qAdrsKeyWord
ldr x3,qAdrsBuffer // result buffer
bl encryption
cmp x0,#-1 // error if unknow character in text
beq 100f
bl affichageMess // display text encrypted
ldr x0,qAdrszCarriageReturn
bl affichageMess
ldr x0,qAdrszCarriageReturn
bl affichageMess
ldr x0,qAdrszMessDecryptText
bl affichageMess
ldr x0,qAdrsBuffer // text decrypt
ldr x1,qAdrtabPolybius
ldr x2,qAdrsKeyWord
ldr x3,qAdrsBuffex1 // result buffer
bl decryption
bl affichageMess
ldr x0,qAdrszCarriageReturn
bl affichageMess
100: // standard end of the program
mov x0, #0 // return code
mov x8, #EXIT // request to exit program
svc #0 // perform the system call
qAdrszCarriageReturn: .quad szCarriageReturn
qAdrszMessDecryptText: .quad szMessDecryptText
qAdrszMessCryptText: .quad szMessCryptText
qAdrszMessStart: .quad szMessStart
qAdrsKeyWord: .quad sKeyWord
qAdrszText: .quad szText
/***************************************************/
/* create 6 * 6 polybius */
/***************************************************/
createPolybius:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
ldr x0,qAdrszListChar // character list address
mov x1,#LGLISTCHAR // character list size
ldr x2,qAdrtabPolybius
bl shufflestrings // shuffle list
ldr x0,qAdrszMessPolybius
bl affichageMess
ldr x0,qAdrszTitle // display polybius lines
bl affichageMess
ldr x0,qAdrszLine1
mov x3,#0
mov x4,#4
1:
ldrb w1,[x2,x3]
strb w1,[x0,x4]
add x4,x4,#2
add x3,x3,#1
cmp x3,#SIZE
blt 1b
bl affichageMess
ldr x0,qAdrszLine2
mov x3,#SIZE
mov x4,#4
2:
ldrb w1,[x2,x3]
strb w1,[x0,x4]
add x4,x4,#2
add x3,x3,#1
cmp x3,#SIZE * 2
blt 2b
bl affichageMess
ldr x0,qAdrszLine3
mov x3,#SIZE * 2
mov x4,#4
3:
ldrb w1,[x2,x3]
strb w1,[x0,x4]
add x4,x4,#2
add x3,x3,#1
cmp x3,#SIZE * 3
blt 3b
bl affichageMess
ldr x0,qAdrszLine4
mov x3,#SIZE * 3
mov x4,#4
4:
ldrb w1,[x2,x3]
strb w1,[x0,x4]
add x4,x4,#2
add x3,x3,#1
cmp x3,#SIZE * 4
blt 4b
bl affichageMess
ldr x0,qAdrszLine5
mov x3,#SIZE * 4
mov x4,#4
5:
ldrb w1,[x2,x3]
strb w1,[x0,x4]
add x4,x4,#2
add x3,x3,#1
cmp x3,#SIZE * 5
blt 5b
bl affichageMess
ldr x0,qAdrszLine6
mov x3,#SIZE * 5
mov x4,#4
6:
ldrb w1,[x2,x3]
strb w1,[x0,x4]
add x4,x4,#2
add x3,x3,#1
cmp x3,#SIZE * 6
blt 6b
bl affichageMess
100:
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16
ret
qAdrszListChar: .quad szListChar
qAdrtabPolybius: .quad tabPolybius
qAdrszMessPolybius: .quad szMessPolybius
qAdrszTitle: .quad szTitle
qAdrszLine1: .quad szLine1
qAdrszLine2: .quad szLine2
qAdrszLine3: .quad szLine3
qAdrszLine4: .quad szLine4
qAdrszLine5: .quad szLine5
qAdrszLine6: .quad szLine6
/***************************************************/
/* generate key word */
/***************************************************/
/* x0 key word address */
generateKey:
stp x1,lr,[sp,-16]!
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
stp x6,x7,[sp,-16]!
stp x8,x9,[sp,-16]!
stp x10,x11,[sp,-16]!
stp x12,x13,[sp,-16]!
mov x9,x0
mov x0,AT_FDCWD
ldr x1,qAdrszFileName // file name
mov x2,#O_RDWR // flags
mov x3,#0 // mode
mov x8,#OPEN // file open
svc 0
cmp x0,#0 // error ?
ble 99f
mov x11,x0 // FD save
ldr x1,qAdrsBuffer // buffer address
mov x8, #FSTAT // call systeme NEWFSTAT
svc 0
cmp x0,#0
blt 98f
// load file size
ldr x1,qAdrsBuffer // buffer address
ldr w6,[x1,#Stat_size_t] // file size
//ldr w6,[x1,mbox_data_size]
lsr x12,x6,#5 // align size to multiple 16 for stack alignement
lsl x12,x12,#5
add x12,x12,#32 // add for great buffer
sub sp,sp,x12 // reserve buffer on stack
mov fp,sp // address save
mov x0,x11
mov x1,fp
mov x2,x12
mov x8,#READ // call system read file
svc 0
cmp x0,#0 // error read ?
blt 97f
mov x0,x11
mov x8,#CLOSE // call system close file
svc 0
cmp x0,#0 // error close ?
blt 96f
sub sp,sp,#0x1000 // create array word address on stack
mov x10,sp // save address array
mov x1,#0
mov x2,fp
mov x5,#0 // index word ok
mov x3,#0 // word length
1:
ldrb w4,[fp,x1] // load character
cmp w4,#0x0D // end word ?
beq 2f // yes
add x1,x1,#1
add x3,x3,#1
b 1b
2:
cmp x3,#KEYSIZE // word length = key length ?
bne 3f // no ?
mov x0,x2
bl wordControl // contril if all letters are différent ?
cmp x0,#1
bne 3f
str x2,[x10,x5,lsl #3] // if ok store word address in array on stack
add x5,x5,#1 // increment word counter
3:
add x1,x1,#2
cmp x1,x6 // end ?
beq 4f
add x2,fp,x1 // new word begin
mov x3,#0 // init word length
b 1b // and loop
4:
mov x0,x5 // number random to total words
bl genereraleas
ldr x2,[x10,x0,lsl #3] // load address word
mov x1,#0
5: // copy random word in word result
ldrb w3,[x2,x1]
strb w3,[x9,x1]
add x1,x1,#1
cmp x1,#KEYSIZE
blt 5b
strb wzr,[x9,x1] // zero final
mov x0,x9
b 100f
// display errors
96:
ldr x0,qAdrszMessClose
bl affichageMess
mov x0,#-1 // error
b 100f
97:
ldr x0,qAdrszMessRead
bl affichageMess
mov x0,#-1 // error
b 100f
98:
ldr x0,qAdrszMessStat
bl affichageMess
mov x0,#-1 // error
b 101f
99:
ldr x0,qAdrszMessOpen
bl affichageMess
mov x0,#-1 // error
b 101f
100:
add sp,sp,x12
add sp,sp,#0x1000
101:
ldp x12,x13,[sp],16
ldp x10,x11,[sp],16
ldp x8,x9,[sp],16
ldp x6,x7,[sp],16
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16
ret
qAdrszFileName: .quad szFileName
qAdrszMessOpen: .quad szMessOpen
qAdrszMessRead: .quad szMessRead
qAdrszMessStat: .quad szMessStat
qAdrszMessClose: .quad szMessClose
qAdrsBuffer: .quad sBuffer
/******************************************************************/
/* control if letters are diferents */
/******************************************************************/
/* x0 contains the address of the string */
/* x0 return 1 if Ok else return 0 */
wordControl:
stp x1,lr,[sp,-16]!
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
mov x1,#0 // init index 1
1:
ldrb w3,[x0,x1] // load one character
cmp x3,#0x0D // end word ?
mov x5,#1
csel x0,x5,x0,eq // yes is ok
//moveq x0,#1 // yes is ok
beq 100f // -> end
add x2,x1,#1 // init index two
2:
ldrb w4,[x0,x2] // load one character
cmp w4,#0x0D // end word ?
add x5,x1,1
csel x1,x5,x1,eq // yes increment index 1
beq 1b // and loop1
cmp x3,x4 // caracters equals ?
csel x0,xzr,x0,eq // yes is not good
beq 100f // and end
add x2,x2,#1 // else increment index 2
b 2b // and loop 2
100:
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16
ret
/******************************************************************/
/* key sort by insertion sort */
/******************************************************************/
/* x0 contains the address of String */
/* x1 contains the first element */
/* x2 contains the number of element */
/* x3 contains result address */
keySort:
stp x1,lr,[sp,-16]!
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
stp x6,x7,[sp,-16]!
stp x8,x9,[sp,-16]!
stp x10,x11,[sp,-16]!
ldr x7,qAdrtabPosit
mov x10,x3
mov x3,#0
0: // init position array and copy key
strb w3,[x7,x3] // in result array
ldrb w4,[x0,x3]
strb w4,[x10,x3]
add x3,x3,#1
cmp x3,#KEYSIZE
blt 0b
add x3,x1,#1 // start index i
1: // start loop
ldrb w4,[x10,x3] // load value A[i]
ldrb w8,[x7,x3] // load position
sub x5,x3,#1 // index j
2:
ldrb w6,[x10,x5] // load value A[j]
ldrb w9,[x7,x5] // load position
cmp x6,x4 // compare value
ble 3f
add x5,x5,#1 // increment index j
strb w6,[x10,x5] // store value A[j+1]
strb w9,[x7,x5] // store position
subs x5,x5,#2 // j = j - 1
bge 2b // loop if j >= 0
3:
add x5,x5,#1 // increment index j
strb w4,[x10,x5] // store value A[i] in A[j+1]
strb w8,[x7,x5]
add x3,x3,#1 // increment index i
cmp x3,x2 // end ?
blt 1b // no -> loop
ldr x1,qAdrtabPositInv // inverse position
mov x2,#0 // index
4:
ldrb w3,[x7,x2] // load position index
strb w2,[x1,x3] // store index in position
add x2,x2,#1 // increment index
cmp x2,#KEYSIZE // end ?
blt 4b
mov x0,x10
100:
ldp x10,x11,[sp],16
ldp x8,x9,[sp],16
ldp x6,x7,[sp],16
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16 // TODO: retaur à completer
ret
qAdrtabPosit: .quad tabPosit
qAdrtabPositInv: .quad tabPositInv
/******************************************************************/
/* text encryption */
/******************************************************************/
/* x0 contains the address of text */
/* x1 contains polybius address
/* x2 contains the key address */
/* x3 contains result buffer address */
encryption:
stp x1,lr,[sp,-16]!
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
stp x6,x7,[sp,-16]!
stp x8,x9,[sp,-16]!
stp x10,x11,[sp,-16]!
mov x9,x0 // save text address
mov x8,x3
mov x10,x1 // save address polybius
mov x0,x2 // key address
mov x1,#0 // first character
mov x2,#KEYSIZE // key length
ldr x3,qAdrsKeyWordSorted // result address
bl keySort // sort leters of key
// bl affichageMess // if you want display sorted key
// ldr x0,qAdrszCarriageReturn
// bl affichageMess
ldr x3,qAdrsBuffex1
mov x5,#0 // init text index
mov x4,#0 // init result index
1:
ldrb w0,[x9,x5] // load a byte to text
cmp x0,#0 // end ?
beq 4f
mov x6,#0 // init index polybius
2:
ldrb w7,[x10,x6] // load character polybius
cmp x7,x0 // equal ?
beq 3f
add x6,x6,#1 // increment index
cmp x6,#SIZEC // not find -> error
bge 99f
b 2b // and loop
3:
mov x0,x6
bl convPosCode // convert position in code character
strb w0,[x3,x4] // line code character
add x4,x4,#1
strb w1,[x3,x4] // column code character
add x4,x4,#1
add x5,x5,#1 // increment text index
b 1b
4:
mov x0,#0 // zero final -> text result
strb w0,[x3,x4]
mov x5,x3
mov x1,#0 // index position column
mov x7,#0 // index text
ldr x2,qAdrtabPositInv
5:
ldrb w0,[x2,x1] // load position text
7: // loop to characters transposition
ldrb w6,[x5,x0] // load character
strb w6,[x8,x7] // store position final
add x7,x7,#1 // increment final index
add x0,x0,#KEYSIZE // add size key
cmp x0,x4 // end ?
blt 7b
add x1,x1,#1 // add index column
cmp x1,#KEYSIZE // < key size
blt 5b // yes -> loop
 
mov x6,#0 // zero final
strb w6,[x8,x7]
mov x0,x8 // return address encrypted text
 
b 100f
99: // display error
ldr x0,qAdrszMessErrorChar
bl affichageMess
mov x0,#-1
100:
ldp x10,x11,[sp],16
ldp x8,x9,[sp],16
ldp x6,x7,[sp],16
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16
ret
qAdrsBuffex1: .quad sBuffex1
qAdrsKeyWordSorted: .quad sKeyWordSorted
qAdrszMessErrorChar: .quad szMessErrorChar
/******************************************************************/
/* text decryption */
/******************************************************************/
/* x0 contains the address of text */
/* x1 contains polybius address
/* x2 contains the key */
/* x3 contains result buffer */
/* x0 return decoded text */
decryption:
stp x1,lr,[sp,-16]!
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
stp x6,x7,[sp,-16]!
stp x8,x9,[sp,-16]!
stp x10,x11,[sp,-16]!
stp x12,x13,[sp,-16]!
mov x4,#0
1: // compute text length
ldrb w5,[x0,x4]
cmp x5,#0
add x11,x4,1
csel x4,x11,x4,ne
bne 1b
mov x12,x0
mov x11,x1
mov x10,x2
mov x13,x3
// compute line number and remainder
mov x1,#KEYSIZE // compute line number and remainder
udiv x8,x4,x1 // line number
msub x7,x8,x1,x4 // remainder characters last line
mov x0,x10 // key address
mov x1,#0 // first character
mov x2,#KEYSIZE // size
ldr x3,qAdrsKeyWordSorted // result address
bl keySort // sort key
ldr x10,qAdrtabPositInv // inverse position
mov x2,#0 // index colonne tabposit
mov x5,#0 // text index
mov x0,#0 // index line store text
mov x1,#0 // counter line
ldr x9,qAdrsBuffex2
1:
ldrb w3,[x10,x2] // load position
ldrb w6,[x12,x5] // load text character
add x3,x3,x0 // compute position with index line
strb w6,[x9,x3] // store character in good position
add x5,x5,#1 // increment index text
cmp x5,x4 // end ?
bge 4f
add x1,x1,#1 // increment line
cmp x1,x8 // line < line size
blt 2f
bgt 11f // line = line size
sub x3,x3,x0 // restaure position column
cmp x3,x7 // position < remainder so add character other line
blt 2f
11:
mov x1,#0 // init ligne
mov x0,#0 // init line shift
add x2,x2,#1 // increment index array position inverse
cmp x2,#KEYSIZE // end ?
csel x2,xzr,x2,ge // init index
b 3f
2:
add x0,x0,#KEYSIZE
3:
b 1b
4: // convertir characters with polybius
mov x3,#0
mov x5,#0
 
5:
mov x0,x11
ldrb w1,[x9,x3] // load a first character
add x3,x3,#1
ldrb w2,[x9,x3] // load a 2ieme character
bl decodPosCode // decode
strb w0,[x13,x5] // store result in final result
add x5,x5,#1 // increment final result index
add x3,x3,#1 // increment index text
cmp x3,x4 // end ?
blt 5b
mov x0,#0 // final zero
strb w0,[x13,x5]
mov x0,x13 // return final result address
100:
ldp x12,x13,[sp],16
ldp x10,x11,[sp],16
ldp x8,x9,[sp],16
ldp x6,x7,[sp],16
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16 // TODO: retaur à completer
ret
qAdrsBuffex2: .quad sBuffex2
/******************************************************************/
/* convertir position en code */
/******************************************************************/
/* x0 contains the position in polybius */
/* x0 return code1 */
/* x1 return code2 */
convPosCode:
stp x2,lr,[sp,-16]!
stp x3,x4,[sp,-16]!
ldr x4,qAdrszListCharCode
mov x1,#SIZE
udiv x2,x0,x1
msub x3,x2,x1,x0
//bl division
ldrb w0,[x4,x2]
ldrb w1,[x4,x3]
100:
ldp x3,x4,[sp],16
ldp x2,lr,[sp],16
ret
qAdrszListCharCode: .quad szListCharCode
/******************************************************************/
/* convertir code en character */
/******************************************************************/
/* x0 polybius address */
/* x1 code 1 */
/* x2 code 2 */
/* x0 return character */
decodPosCode:
stp x1,lr,[sp,-16]!
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
ldr x4,qAdrszListCharCode
mov x3,#0
1:
ldrb w5,[x4,x3]
cmp x5,#0
beq 2f
cmp x5,x1
csel x1,x3,x1,eq
cmp x5,x2
csel x2,x3,x2,eq
add x3,x3,#1
b 1b
2:
mov x5,#SIZE
mul x1,x5,x1
add x1,x1,x2
ldrb w0,[x0,x1]
100:
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16
ret
 
/******************************************************************/
/* shuffle strings algorithme Fisher-Yates */
/******************************************************************/
/* x0 contains the address of the string */
/* x1 contains string length */
/* x2 contains address result string */
shufflestrings:
stp x1,lr,[sp,-16]! // TODO: save à completer
stp x2,x3,[sp,-16]!
stp x4,x5,[sp,-16]!
mov x3,#0
1: // loop copy string in result
ldrb w4,[x0,x3]
strb w4,[x2,x3]
add x3,x3,#1
cmp x3,x1
ble 1b
sub x1,x1,#1 // last element
2:
mov x0,x1
bl genereraleas // call random
ldrb w4,[x2,x1] // load byte string index loop
ldrb w3,[x2,x0] // load byte string random index
strb w3,[x2,x1] // and exchange
strb w4,[x2,x0]
subs x1,x1,#1
cmp x1,#1
bge 2b
 
100:
ldp x4,x5,[sp],16
ldp x2,x3,[sp],16
ldp x1,lr,[sp],16
ret
/***************************************************/
/* Generation random number */
/***************************************************/
/* x0 contains limit */
genereraleas:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
ldr x1,qAdrqGraine
ldr x2,[x1]
ldr x3,qNbDep1
mul x2,x3,x2
ldr x3,qNbDep2
add x2,x2,x3
str x2,[x1] // maj de la graine pour l appel suivant
cmp x0,#0
beq 100f
udiv x3,x2,x0
msub x0,x3,x0,x2 // résult = remainder
100: // end function
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
qAdrqGraine: .quad qGraine
qNbDep1: .quad 0x0019660d
qNbDep2: .quad 0x3c6ef35f
 
/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../includeARM64.inc"
 
</syntaxhighlight>
{{Out}}
<pre>
Program 64 bits start.
6 x 6 Polybius square:
| A D F G V X
---------------
A | Q A M C 0 X
D | 1 S O Y R E
F | H 7 J T U W
G | V F 3 Z 4 I
V | 8 B 9 K 6 2
X | P D L G 5 N
hailstorm
Encrypted text :
DVXAGVFFGAGAVDDDAAAGFVAGAFDA
 
Decrypted text :
ATTACKAT1200AM
</pre>
=={{header|ARM Assembly}}==
Line 856 ⟶ 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,129 ⟶ 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 1,625 ⟶ 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 1,794 ⟶ 3,072:
{{libheader|Wren-seq}}
{{libheader|Wren-str}}
<syntaxhighlight lang="ecmascriptwren">import "random" for Random
import "./ioutil" for FileUtil
import "./seq" for Lst
import "./str" for Char, Str
 
var rand = Random.new()
Line 1,920 ⟶ 3,198:
 
Decrypted : ATTACKAT1200AM
</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>
9,482

edits