Data update

This commit is contained in:
Ingy döt Net 2026-04-30 12:34:36 -04:00
parent 4bb20c9b71
commit cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions

View file

@ -0,0 +1,30 @@
-- Bifid cipher
-- J. Carter 2023 May
-- The Bifid cipher is included as part of the PragmAda Reusable Components (https://github.com/jrcarter/PragmARC)
with Ada.Text_IO;
with PragmARC.Encryption.Bifid;
procedure Bifid_Test is
package Bifid renames PragmARC.Encryption.Bifid;
Key_1 : constant Bifid.Square_Layout := ("ABCDE", "FGHIK", "LMNOP", "QRSTU", "VWXYZ");
Key_2 : constant Bifid.Square_Layout := ("BGWKZ", "QPNDS", "IOAXE", "FCLUM", "THYVR");
Msg_1 : constant String := "ATTACKATDAWN";
Msg_2 : constant String := "FLEEATONCE";
Msg_3 : constant String := "THEINVASIONWILLSTARTONTHEFIRSTOFJANUARY";
Crypt_1 : String (Msg_1'Range);
Crypt_2 : String (Msg_2'Range);
Crypt_3 : String (Msg_3'Range);
begin -- Bifid_Test
Crypt_1 := Bifid.Encrypt (Msg_1, Key_1);
Ada.Text_IO.Put_Line (Item => Msg_1 & " => " & Crypt_1 & " => " & Bifid.Decrypt (Crypt_1, Key_1) );
Crypt_2 := Bifid.Encrypt (Msg_2, Key_2);
Ada.Text_IO.Put_Line (Item => Msg_2 & " => " & Crypt_2 & " => " & Bifid.Decrypt (Crypt_2, Key_2) );
Crypt_1 := Bifid.Encrypt (Msg_1, Key_2);
Ada.Text_IO.Put_Line (Item => Msg_1 & " => " & Crypt_1 & " => " & Bifid.Decrypt (Crypt_1, Key_2) );
Crypt_3 := Bifid.Encrypt (Msg_3, Key_2);
Ada.Text_IO.Put_Line (Item => Msg_3 & " => " & Crypt_3 & " => " & Bifid.Decrypt (Crypt_3, Key_2) );
end Bifid_Test;

View file

@ -9,104 +9,104 @@ typedef std::pair<int32_t, int32_t> point;
class Bifid {
public:
Bifid(const int32_t n, std::string_view text) {
if ( text.length() != n * n ) {
throw std::invalid_argument("Incorrect length of text");
}
Bifid(const int32_t n, std::string_view text) {
if ( text.length() != n * n ) {
throw std::invalid_argument("Incorrect length of text");
}
grid.resize(n);
for ( uint64_t i = 0; i < grid.size(); i++ ) {
grid[i].resize(n);
}
grid.resize(n);
for ( uint64_t i = 0; i < grid.size(); i++ ) {
grid[i].resize(n);
}
int32_t row = 0;
int32_t col = 0;
for ( const char& ch : text ) {
grid[row][col] = ch;
coordinates[ch] = point(row, col);
col += 1;
if ( col == n ) {
col = 0;
row += 1;
}
}
int32_t row = 0;
int32_t col = 0;
for ( const char& ch : text ) {
grid[row][col] = ch;
coordinates[ch] = point(row, col);
col += 1;
if ( col == n ) {
col = 0;
row += 1;
}
}
if ( n == 5 ) {
coordinates['J'] = coordinates['I'];
}
}
if ( n == 5 ) {
coordinates['J'] = coordinates['I'];
}
}
std::string encrypt(std::string_view text) {
std::vector<int32_t> row_one, row_two;
for ( const char& ch : text ) {
point coordinate = coordinates[ch];
row_one.push_back(coordinate.first);
row_two.push_back(coordinate.second);
}
std::string encrypt(std::string_view text) {
std::vector<int32_t> row_one, row_two;
for ( const char& ch : text ) {
point coordinate = coordinates[ch];
row_one.push_back(coordinate.first);
row_two.push_back(coordinate.second);
}
row_one.insert(row_one.end(), row_two.begin(), row_two.end());
std::string result;
for ( uint64_t i = 0; i < row_one.size() - 1; i += 2 ) {
result += grid[row_one[i]][row_one[i + 1]];
}
return result;
}
row_one.insert(row_one.end(), row_two.begin(), row_two.end());
std::string result;
for ( uint64_t i = 0; i < row_one.size() - 1; i += 2 ) {
result += grid[row_one[i]][row_one[i + 1]];
}
return result;
}
std::string decrypt(std::string_view text) {
std::vector<int32_t> row;
for ( const char& ch : text ) {
point coordinate = coordinates[ch];
row.push_back(coordinate.first);
row.push_back(coordinate.second);
}
std::string decrypt(std::string_view text) {
std::vector<int32_t> row;
for ( const char& ch : text ) {
point coordinate = coordinates[ch];
row.push_back(coordinate.first);
row.push_back(coordinate.second);
}
const int middle = row.size() / 2;
std::vector<int32_t> row_one = { row.begin(), row.begin() + middle };
std::vector<int32_t> row_two = { row.begin() + middle, row.end() };
std::string result;
for ( int32_t i = 0; i < middle; i++ ) {
result += grid[row_one[i]][row_two[i]];
}
return result;
}
const int middle = row.size() / 2;
std::vector<int32_t> row_one = { row.begin(), row.begin() + middle };
std::vector<int32_t> row_two = { row.begin() + middle, row.end() };
std::string result;
for ( int32_t i = 0; i < middle; i++ ) {
result += grid[row_one[i]][row_two[i]];
}
return result;
}
void display() const {
for ( const std::vector<char>& row : grid ) {
for ( const char& ch : row ) {
std::cout << ch << " ";
}
std::cout << std::endl;
}
}
void display() const {
for ( const std::vector<char>& row : grid ) {
for ( const char& ch : row ) {
std::cout << ch << " ";
}
std::cout << std::endl;
}
}
private:
std::vector<std::vector<char>> grid;
std::unordered_map<char, point> coordinates;
std::vector<std::vector<char>> grid;
std::unordered_map<char, point> coordinates;
};
void runTest(Bifid& bifid, std::string_view message) {
std::cout << "Using Polybius square:" << std::endl;
bifid.display();
std::cout << "Message: " << message << std::endl;
std::string encrypted = bifid.encrypt(message);
std::cout << "Encrypted: " << encrypted << std::endl;
std::string decrypted = bifid.decrypt(encrypted);
std::cout << "Decrypted: " << decrypted << std::endl;
std::cout << std::endl;
std::cout << "Using Polybius square:" << std::endl;
bifid.display();
std::cout << "Message: " << message << std::endl;
std::string encrypted = bifid.encrypt(message);
std::cout << "Encrypted: " << encrypted << std::endl;
std::string decrypted = bifid.decrypt(encrypted);
std::cout << "Decrypted: " << decrypted << std::endl;
std::cout << std::endl;
}
int main() {
const std::string_view message1 = "ATTACKATDAWN";
const std::string_view message2 = "FLEEATONCE";
const std::string_view message3 = "THEINVASIONWILLSTARTONTHEFIRSTOFJANUARY";
const std::string_view message1 = "ATTACKATDAWN";
const std::string_view message2 = "FLEEATONCE";
const std::string_view message3 = "THEINVASIONWILLSTARTONTHEFIRSTOFJANUARY";
Bifid bifid1(5, "ABCDEFGHIKLMNOPQRSTUVWXYZ");
Bifid bifid2(5, "BGWKZQPNDSIOAXEFCLUMTHYVR");
Bifid bifid1(5, "ABCDEFGHIKLMNOPQRSTUVWXYZ");
Bifid bifid2(5, "BGWKZQPNDSIOAXEFCLUMTHYVR");
runTest(bifid1, message1);
runTest(bifid2, message2);
runTest(bifid2, message1);
runTest(bifid1, message2);
runTest(bifid1, message1);
runTest(bifid2, message2);
runTest(bifid2, message1);
runTest(bifid1, message2);
Bifid bifid3(6, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
runTest(bifid3, message3);
Bifid bifid3(6, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
runTest(bifid3, message3);
}

View file

@ -0,0 +1,46 @@
enum BifidOp
Encode
Decode
end
def bifid_encode (message, alphabet, op : BifidOp = :encode)
square = alphabet.chars
side = Math.isqrt(square.size)
raise "alphabet not a square" unless side*side == square.size
chars = message.chars
raise "incomplete alphabet" unless chars.all?(&.in? square)
coords = chars.flat_map {|ch| [*square.index!(ch).divmod(side)] }
coords = if op.encode?
(0...coords.size).step(2).map {|i| coords[i] }.to_a +
(1...coords.size).step(2).map {|i| coords[i] }.to_a
else
half = coords.size//2
coords[...half].zip(coords[half..]).map {|c1, c2|
[c1, c2]
}.flatten
end
coords.each_slice(2).map {|(row, col)|
square[row * side + col]
}.join
end
poly1 = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
poly2 = "BGWKZQPNDSIOAXEFCLUMTHYVR"
superpoly = (' '..'~').join + "¡éßñø"
attack = "ATTACKATDAWN"
flee = "FLEEATONCE"
invasion = "The invasion will start on the first of January".upcase.tr("J", "I").delete("^A-Z")
ataque = "¡Attack on 1/1 at 23:59, señor!"
[{attack, poly1}, {flee, poly2}, {attack, poly2},
{invasion, poly1}, {ataque, superpoly}].each do |message, alphabet|
encoded = bifid_encode(message, alphabet)
decoded = bifid_encode(encoded, alphabet, :decode)
puts "Message: #{message} #{alphabet.size > 80 ? "\n" : " "}- Alphabet: #{alphabet}"
puts "Encoded: #{encoded}"
puts "Decoded: #{decoded}"
puts
end

View file

@ -18,13 +18,13 @@ model
end
fun asText ← text by block
text result
for int y ← 0; y < me.grid.length; y++
for int x ← 0; x < me.grid[y].length; x++
result.append(" " + me.grid[y][x])
end
result.appendLine()
end
return result
for int y ← 0; y < me.grid.length; y++
for int x ← 0; x < me.grid[y].length; x++
result.append(" " + me.grid[y][x])
end
result.appendLine()
end
return result
end
end
type BifidCipher

View file

@ -0,0 +1,219 @@
!
! Bifid cipher
! tested with Intel ifx (IFX) 2025.2.1 20250806 on Kubuntu 25.10
! GNU Fortran (Ubuntu 15.2.0-4ubuntu4) 15.2.0 on Kubuntu 25.10
! VSI Fortran x86-64 V8.6-001 on OpenVMS x86_64 V9.2-3
! No Non-standard features used, should compile on any fairly recent Fortran.
!
! U.B., October 2025
!==============================================================================
program BifidCipher
implicit none
! Constants:
integer, parameter :: nTests = 6 ! NUmber of different test messages
integer, parameter :: maxLen=100 ! Maximum length of any test message
! Instead of drawing the Polybius squares, we only define the alphabet to applied and calculate
! row and column number on the fly when needed.
! If necessary, the Encrypt and Decrypt subroutines extend the alphabets using "SpareAlpha"
! until the total length of the extended alphabet is a square number. This is important because
! otherwise the enccrypt or decrypt algorithm may calculate a row/column combination that is
! not used by the actual alphabet.
! The alphabet as shown in the task description has no J.
character (len=*), parameter :: Alphabet_no_J ='ABCDEFGHIKLMNOPQRSTUVWXYZ'
! The alphabet of capital letters as used in most western languages
character (len=*), parameter :: Alphabet_With_J ='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
! The square in the wikipedia article in 1 long string:
character (len=*), parameter :: AlternateAlphabet = 'BGWKZQPNDSIOAXEFCLUMTHYVR'
! Standard Alphabet with CAPITAL and small letters
character (len=*), parameter :: Alphabet_withSmallLetters = &
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
! Printable spare characters to extend alphabets so the total length becomes the
! next larger square number > the alphabet's length
character (len=*), parameter :: SpareAlpha = '1234567890!"§$%&/()=' ! omitted ! and "
! Variables:
character (len=maxLen) :: MsgToEncrypt (nTests), EncryptedMsg (nTests), DecryptedMsg (nTests)
integer :: ColWidth ! Is variable and depends on length of the used alphabet
integer :: i, lx
! The test strings: (1) is from the task description, (2) is from the Wikipedia Article, (3) is
! the additional message as presented in the task description
MsgToEncrypt(1) = 'ATTACKATDAWN'
MsgToEncrypt(2) = 'FLEEATONCE'
MsgToEncrypt(3) = 'THEINVASIONWILLSTARTONTHEFIRSTOFJANUARY'
! Same text, with both small and capital letters, to be used with an extended Polybius square
MsgToEncrypt(4) = 'AttackAtDawn'
MsgToEncrypt(5) = 'FleeAtOnce'
MsgToEncrypt(6) = 'TheInvasionWillStartOnTheFirstOfJanuary'
print '(A/)', 'Using the alphabet and Polybius square without "J"'
call PrintSquare (Alphabet_no_J)
do i=1, nTests/2
lx = len_trim (MsgToEncrypt(i))
call encrypt (MsgToEncrypt(i)(:lx) , EncryptedMsg (i) , Alphabet_no_J)
call decrypt (EncryptedMsg(i) (:lx), DecryptedMsg (i) , Alphabet_no_J)
print '(A, " => ", A, " => ", A)', MsgToEncrypt(i)(:lx), EncryptedMsg (i)(:lx), DecryptedMsg (i)(:lx)
enddo
print '(/A/)', 'Using the extended alphabet and Polybius square that includes "J"'
call PrintSquare (Alphabet_with_J)
do i=1, nTests/2
lx = len_trim (MsgToEncrypt(i))
call encrypt (MsgToEncrypt(i)(:lx) , EncryptedMsg (i) , Alphabet_with_J)
call decrypt (EncryptedMsg(i) (:lx), DecryptedMsg (i) , Alphabet_with_J)
print '(A, " => ", A, " => ", A)', MsgToEncrypt(i)(:lx), EncryptedMsg (i)(:lx), DecryptedMsg (i)(:lx)
end do
print '(/A/)', 'Using the alphabet and Polybius square as shown in the Wikipedia article (no J!)'
call PrintSquare (AlternateAlphabet)
do i=1, nTests/2
lx = len_trim (MsgToEncrypt(i))
call encrypt (MsgToEncrypt(i)(:lx) , EncryptedMsg (i) , AlternateAlphabet)
call decrypt (EncryptedMsg(i) (:lx), DecryptedMsg (i) , AlternateAlphabet)
print '(A, " => ", A, " => ", A)', MsgToEncrypt(i)(:lx), EncryptedMsg (i)(:lx), DecryptedMsg (i)(:lx)
end do
print '(/A/)', 'Using the extended alphabet with both upper case and lower case letters, including J and j'
call PrintSquare (Alphabet_withSmallLetters)
do i=nTests/2+1, nTests
lx = len_trim (MsgToEncrypt(i))
call encrypt (MsgToEncrypt(i)(:lx) , EncryptedMsg (i) , Alphabet_withSmallLetters)
call decrypt (EncryptedMsg(i) (:lx), DecryptedMsg (i) , Alphabet_withSmallLetters)
print '(A, " => ", A, " => ", A)', MsgToEncrypt(i)(:lx), EncryptedMsg (i)(:lx), DecryptedMsg (i)(:lx)
end do
contains
!======================
! Encode a given string
! ======================
subroutine encrypt (inString,outString, argAlphabet)
character (len=*), intent(in) :: argAlphabet
character (len=*), intent(in) :: inString
character (len=*), intent(out) :: outString
character (len=100) :: Alphabet
integer :: idxLine(2*maxLen)
integer :: l, ii, idx, row, col
! Calculate required column width: so that ColWidth^2 >= (length of Alphabet)
Alphabet = argAlphabet
l = len_trim(alphabet)
ColWidth = 1
do while (ColWidth*ColWidth .lt. l)
ColWidth = ColWidth + 1
end do
if (ColWidth .gt.8) stop 'ERROR: Cannot handle Alphabets with more than 64 characters.'
! Provide some printable chars until the length is a square number
Alphabet (l+1:) = SpareAlpha
l = len_trim (inString)
if (l .gt. len(outString)) stop 'ERROR: not enough storage space for encrypt result string.'
do ii=1, l
! print *, ' ii = ', ii, ' instring(ii) = ', inString(ii:ii)
idx = index (Alphabet, inString(ii:ii))
if (idx .eq. 0) idx = index (Alphabet, char(ichar(instring(ii:ii))-1)) ! J=I, j=i, just in case
row = (idx+ColWidth-1) / ColWidth ! e.g. 'A' ...'E', idx=1...5, row=(5...9)/5 = 1, col = 1...5
col = 1+mod (idx+ColWidth-1, ColWidth) ! e.g. 'F' ...'K', idx=6...10, row=(10...14)/5 = 2, col = 1...5
idxLine (ii) = row
idxLine (ii+l) = col
end do
do ii=1, l
idx = 10*idxLine(1+2*(ii-1)) + idxLine (2+2*(ii-1))
row = idxLine(1+2*(ii-1))
col = idxLine (2+2*(ii-1))
idx = ColWidth*(row-1) + col
outString (ii:ii) = alphabet (idx:idx)
enddo
end subroutine encrypt
!======================
! Decode a given string
!======================
subroutine decrypt (inString,outString, argAlphabet)
character (len=*), intent(in) :: inString
character (len=*), intent(out) :: outString
character (len=*), intent(in) :: argAlphabet
character (len=100) :: Alphabet
integer :: idxLine(2*maxLen)
integer :: l, ii, idx, row, col
! Calculate required column width: so that ColWidth^2 >= (length of Alphabet)
Alphabet = argAlphabet
l = len_trim(alphabet)
ColWidth = 1
do while (ColWidth*ColWidth .lt. l)
ColWidth = ColWidth + 1
end do
! Append some spare characters so that the square is completely filled without undefined fields
Alphabet (l+1:) = SpareAlpha
l = len_trim (inString)
if (l .gt. len(outString)) stop 'ERROR: not enough storage space for decrypt result string.'
do ii=1, l
idx = index (Alphabet, inString(ii:ii))
row = (idx+ColWidth-1) / ColWidth ! idx 1...5 is row 1, 6...10 is row 2 etc
col = 1+mod (idx+ColWidth-1, ColWidth) ! so that 21...29 -> 1...9 etc.
idxLine (1+2*(ii-1)) = row
idxLine (2+2*(ii-1)) = col
end do
do ii=1, l
row = idxLine (ii)
col = idxLine (ii+l)
idx = ColWidth*(row-1) + col
outString (ii:ii) = alphabet (idx:idx)
end do
end subroutine decrypt
! ================================================================================
! Print the resulting Polybius square based on the alphabet used for encode/decode
! ================================================================================
subroutine PrintSquare (Alphabet)
character (len=*), intent(in) :: Alphabet
integer:: ii, l
l = len_trim(alphabet)
ColWidth = 1
do while (ColWidth*ColWidth .lt. l)
ColWidth = ColWidth + 1
end do
print '("The alphabet has a length of ", I0, " so it requires the square size of ", I0, "x", I0 /)' , l, ColWidth, ColWidth
do ii=1, ColWidth*ColWidth
if (ii .le. l) then
write (*, '(A2)', advance='no') Alphabet(ii:ii)
else
write (*, '(A2)', advance='no') SpareAlpha (ii-l:ii-l) ! Use spares to complete the square
endif
if (mod (ii, ColWidth) .eq. 0) print * ! End of line
end do
print * ! one extra blank line
end subroutine PrintSquare
end program BifidCipher

View file

@ -5,176 +5,176 @@
package main
import (
"fmt"
"strings"
"fmt"
"strings"
)
var (
squareRosetta [][]byte = [][]byte{ //rosettacode
{'A', 'B', 'C', 'D', 'E'},
{'F', 'G', 'H', 'I', 'K'},
{'L', 'M', 'N', 'O', 'P'},
{'Q', 'R', 'S', 'T', 'U'},
{'V', 'W', 'X', 'Y', 'Z'},
{'J', '1', '2', '3', '4'},
}
squareRosetta [][]byte = [][]byte{ //rosettacode
{'A', 'B', 'C', 'D', 'E'},
{'F', 'G', 'H', 'I', 'K'},
{'L', 'M', 'N', 'O', 'P'},
{'Q', 'R', 'S', 'T', 'U'},
{'V', 'W', 'X', 'Y', 'Z'},
{'J', '1', '2', '3', '4'},
}
squareWikipedia [][]byte = [][]byte{ // wikipedia
squareWikipedia [][]byte = [][]byte{ // wikipedia
{'B', 'G', 'W', 'K', 'Z'},
{'Q', 'P', 'N', 'D', 'S'},
{'I', 'O', 'A', 'X', 'E'},
{'F', 'C', 'L', 'U', 'M'},
{'T', 'H', 'Y', 'V', 'R'},
{'J', '1', '2', '3', '4'},
}
{'B', 'G', 'W', 'K', 'Z'},
{'Q', 'P', 'N', 'D', 'S'},
{'I', 'O', 'A', 'X', 'E'},
{'F', 'C', 'L', 'U', 'M'},
{'T', 'H', 'Y', 'V', 'R'},
{'J', '1', '2', '3', '4'},
}
textRosetta string = "0ATTACKATDAWN"
textRosettaEncoded string = "DQBDAXDQPDQH" // only for test
textWikipedia string = "FLEEATONCE"
textWikipediaEncoded string = "UAEOLWRINS" // only for test
textTest string = "The invasion will start on the first of January"
textTextEncoded string = "RASOAQXFIOORXESXADETSWLTNIAZQOISBRGBALY" // only for test
textRosetta string = "0ATTACKATDAWN"
textRosettaEncoded string = "DQBDAXDQPDQH" // only for test
textWikipedia string = "FLEEATONCE"
textWikipediaEncoded string = "UAEOLWRINS" // only for test
textTest string = "The invasion will start on the first of January"
textTextEncoded string = "RASOAQXFIOORXESXADETSWLTNIAZQOISBRGBALY" // only for test
)
type koord struct {
X byte
Y byte
X byte
Y byte
}
func (k *koord) LessThen(other *koord) bool {
if k.Y > other.Y {
return false
}
if k.Y < other.Y {
return true
}
if k.X < other.X {
return true
}
return false
if k.Y > other.Y {
return false
}
if k.Y < other.Y {
return true
}
if k.X < other.X {
return true
}
return false
}
func (k *koord) EqualTo(other koord) bool {
if k.X == other.X && k.Y == other.Y {
return true
}
return false
if k.X == other.X && k.Y == other.Y {
return true
}
return false
}
var encryptMap map[byte]koord
var decryptMap map[koord]byte
func squareToMaps(square [][]byte) (map[byte]koord, map[koord]byte) {
eMap := make(map[byte]koord)
dMap := make(map[koord]byte)
for x, col := range square {
for y, v := range col {
eMap[v] = koord{byte(x), byte(y)}
dMap[koord{byte(x), byte(y)}] = v
eMap := make(map[byte]koord)
dMap := make(map[koord]byte)
for x, col := range square {
for y, v := range col {
eMap[v] = koord{byte(x), byte(y)}
dMap[koord{byte(x), byte(y)}] = v
}
}
return eMap, dMap
}
}
return eMap, dMap
}
func removeSpaceI(text string) string {
var n string
s := strings.ToUpper(text)
for _, b := range []byte(s) {
//use only ASCII Characters from A to Z
if b < 'A' || b > 'Z' {
continue
}
if b == 'J' {
b = 'I'
}
n = n + string(b)
}
return n
var n string
s := strings.ToUpper(text)
for _, b := range []byte(s) {
//use only ASCII Characters from A to Z
if b < 'A' || b > 'Z' {
continue
}
if b == 'J' {
b = 'I'
}
n = n + string(b)
}
return n
}
func removeSpace(text string, square map[byte]koord) string {
var n string
//to UpperCase and then remove all Spaces an Characters witch are not in square
s := strings.ReplaceAll(strings.ToUpper(text), " ", "")
for _, b := range []byte(s) {
_, ok := square[b]
if ok {
n = n + string(b)
}
}
return n
var n string
//to UpperCase and then remove all Spaces an Characters witch are not in square
s := strings.ReplaceAll(strings.ToUpper(text), " ", "")
for _, b := range []byte(s) {
_, ok := square[b]
if ok {
n = n + string(b)
}
}
return n
}
func encrypt(text string, emap map[byte]koord, dmap map[koord]byte) string {
text = removeSpace(text, emap)
var row0, row1 []byte
for _, b := range []byte(text) {
xy := emap[b]
row0 = append(row0, xy.X)
row1 = append(row1, xy.Y)
}
row0 = append(row0, row1...)
text = removeSpace(text, emap)
var row0, row1 []byte
for _, b := range []byte(text) {
xy := emap[b]
row0 = append(row0, xy.X)
row1 = append(row1, xy.Y)
}
row0 = append(row0, row1...)
var s string
for i := 0; i < len(row0); i += 2 {
s = s + string(dmap[koord{row0[i], row0[i+1]}])
}
return s
var s string
for i := 0; i < len(row0); i += 2 {
s = s + string(dmap[koord{row0[i], row0[i+1]}])
}
return s
}
func decrypt(text string, emap map[byte]koord, dmap map[koord]byte) string {
text = removeSpace(text, emap)
k := make([]koord, len(text))
text = removeSpace(text, emap)
k := make([]koord, len(text))
for i, b := range []byte(text) {
k[i] = emap[b]
}
for i, b := range []byte(text) {
k[i] = emap[b]
}
kl := make([]byte, len(k)*2)
i := int(0)
for _, ki := range k {
kl[i] = ki.X
kl[i+1] = ki.Y
i += 2
}
l := len(kl) / 2
k1 := kl[:l]
k2 := kl[l:]
var s string
kl := make([]byte, len(k)*2)
i := int(0)
for _, ki := range k {
kl[i] = ki.X
kl[i+1] = ki.Y
i += 2
}
l := len(kl) / 2
k1 := kl[:l]
k2 := kl[l:]
var s string
for i := 0; i < l; i++ {
s = s + string(dmap[koord{k1[i], k2[i]}])
}
return s
for i := 0; i < l; i++ {
s = s + string(dmap[koord{k1[i], k2[i]}])
}
return s
}
func main() {
encryptMap, decryptMap = squareToMaps(squareRosetta)
fmt.Println("from Rosettacode")
fmt.Println("original:\t", textRosetta)
s := encrypt(textRosetta, encryptMap, decryptMap)
fmt.Println("codiert:\t", s)
s = decrypt(s, encryptMap, decryptMap)
fmt.Println("and back:\t", s)
encryptMap, decryptMap = squareToMaps(squareRosetta)
fmt.Println("from Rosettacode")
fmt.Println("original:\t", textRosetta)
s := encrypt(textRosetta, encryptMap, decryptMap)
fmt.Println("codiert:\t", s)
s = decrypt(s, encryptMap, decryptMap)
fmt.Println("and back:\t", s)
fmt.Println("from Wikipedia")
encryptMap, decryptMap = squareToMaps(squareWikipedia)
fmt.Println("original:\t", textWikipedia)
s = encrypt(textWikipedia, encryptMap, decryptMap)
fmt.Println("codiert:\t", s)
s = decrypt(s, encryptMap, decryptMap)
fmt.Println("and back:\t", s)
fmt.Println("from Wikipedia")
encryptMap, decryptMap = squareToMaps(squareWikipedia)
fmt.Println("original:\t", textWikipedia)
s = encrypt(textWikipedia, encryptMap, decryptMap)
fmt.Println("codiert:\t", s)
s = decrypt(s, encryptMap, decryptMap)
fmt.Println("and back:\t", s)
encryptMap, decryptMap = squareToMaps(squareWikipedia)
fmt.Println("from Rosettacode long part")
fmt.Println("original:\t", textTest)
s = encrypt(textTest, encryptMap, decryptMap)
fmt.Println("codiert:\t", s)
// Wenn der Text eine ungerade Anzahl Buchstaben hat, funktioniert der Algorithmus nicht!!!
s = decrypt(s, encryptMap, decryptMap)
fmt.Println("and back:\t", s)
encryptMap, decryptMap = squareToMaps(squareWikipedia)
fmt.Println("from Rosettacode long part")
fmt.Println("original:\t", textTest)
s = encrypt(textTest, encryptMap, decryptMap)
fmt.Println("codiert:\t", s)
// Wenn der Text eine ungerade Anzahl Buchstaben hat, funktioniert der Algorithmus nicht!!!
s = decrypt(s, encryptMap, decryptMap)
fmt.Println("and back:\t", s)
}

View file

@ -7,101 +7,101 @@ import java.util.Map;
public final class BifidCipher {
public static void main(String[] aArgs) {
final String message1 = "ATTACKATDAWN";
final String message2 = "FLEEATONCE";
final String message3 = "The invasion will start on the first of January".toUpperCase().replace(" ", "");
Bifid bifid1 = new Bifid(5, "ABCDEFGHIKLMNOPQRSTUVWXYZ");
Bifid bifid2 = new Bifid(5, "BGWKZQPNDSIOAXEFCLUMTHYVR");
runTest(bifid1, message1);
runTest(bifid2, message2);
runTest(bifid2, message1);
runTest(bifid1, message2);
Bifid bifid3 = new Bifid(6, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
runTest(bifid3, message3);
}
private static void runTest(Bifid aBifid, String aMessage) {
System.out.println("Using Polybius square:");
aBifid.display();
System.out.println("Message: " + aMessage);
String encrypted = aBifid.encrypt(aMessage);
System.out.println("Encrypted: " + encrypted);
String decrypted = aBifid.decrypt(encrypted);
System.out.println("Decrypted: " + decrypted);
System.out.println();
}
public static void main(String[] aArgs) {
final String message1 = "ATTACKATDAWN";
final String message2 = "FLEEATONCE";
final String message3 = "The invasion will start on the first of January".toUpperCase().replace(" ", "");
Bifid bifid1 = new Bifid(5, "ABCDEFGHIKLMNOPQRSTUVWXYZ");
Bifid bifid2 = new Bifid(5, "BGWKZQPNDSIOAXEFCLUMTHYVR");
runTest(bifid1, message1);
runTest(bifid2, message2);
runTest(bifid2, message1);
runTest(bifid1, message2);
Bifid bifid3 = new Bifid(6, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
runTest(bifid3, message3);
}
private static void runTest(Bifid aBifid, String aMessage) {
System.out.println("Using Polybius square:");
aBifid.display();
System.out.println("Message: " + aMessage);
String encrypted = aBifid.encrypt(aMessage);
System.out.println("Encrypted: " + encrypted);
String decrypted = aBifid.decrypt(encrypted);
System.out.println("Decrypted: " + decrypted);
System.out.println();
}
}
final class Bifid {
public Bifid(int aN, String aText) {
if ( aText.length() != aN * aN ) {
throw new IllegalArgumentException("Incorrect length of text");
}
grid = new char[aN][aN];
int row = 0;
int col = 0;
for ( char ch : aText.toCharArray() ) {
grid[row][col] = ch;
coordinates.put(ch, new Point(row, col) );
col += 1;
if ( col == aN ) {
col = 0;
row += 1;
}
}
if ( aN == 5 ) {
coordinates.put('J', coordinates.get('I'));
}
}
public String encrypt(String aText) {
List<Integer> rowOne = new ArrayList<Integer>();
List<Integer> rowTwo = new ArrayList<Integer>();
for ( char ch : aText.toCharArray() ) {
Point coordinate = coordinates.get(ch);
rowOne.add(coordinate.x);
rowTwo.add(coordinate.y);
}
rowOne.addAll(rowTwo);
StringBuilder result = new StringBuilder();
for ( int i = 0; i < rowOne.size() - 1; i += 2 ) {
result.append(grid[rowOne.get(i)][rowOne.get(i + 1)]);
}
return result.toString();
}
public String decrypt(String aText) {
List<Integer> row = new ArrayList<Integer>();
for ( char ch : aText.toCharArray() ) {
Point coordinate = coordinates.get(ch);
row.add(coordinate.x);
row.add(coordinate.y);
}
final int middle = row.size() / 2;
List<Integer> rowOne = row.subList(0, middle);
List<Integer> rowTwo = row.subList(middle, row.size());
StringBuilder result = new StringBuilder();
for ( int i = 0; i < middle; i++ ) {
result.append(grid[rowOne.get(i)][rowTwo.get(i)]);
}
return result.toString();
}
public Bifid(int aN, String aText) {
if ( aText.length() != aN * aN ) {
throw new IllegalArgumentException("Incorrect length of text");
}
grid = new char[aN][aN];
int row = 0;
int col = 0;
for ( char ch : aText.toCharArray() ) {
grid[row][col] = ch;
coordinates.put(ch, new Point(row, col) );
col += 1;
if ( col == aN ) {
col = 0;
row += 1;
}
}
if ( aN == 5 ) {
coordinates.put('J', coordinates.get('I'));
}
}
public String encrypt(String aText) {
List<Integer> rowOne = new ArrayList<Integer>();
List<Integer> rowTwo = new ArrayList<Integer>();
for ( char ch : aText.toCharArray() ) {
Point coordinate = coordinates.get(ch);
rowOne.add(coordinate.x);
rowTwo.add(coordinate.y);
}
rowOne.addAll(rowTwo);
StringBuilder result = new StringBuilder();
for ( int i = 0; i < rowOne.size() - 1; i += 2 ) {
result.append(grid[rowOne.get(i)][rowOne.get(i + 1)]);
}
return result.toString();
}
public String decrypt(String aText) {
List<Integer> row = new ArrayList<Integer>();
for ( char ch : aText.toCharArray() ) {
Point coordinate = coordinates.get(ch);
row.add(coordinate.x);
row.add(coordinate.y);
}
final int middle = row.size() / 2;
List<Integer> rowOne = row.subList(0, middle);
List<Integer> rowTwo = row.subList(middle, row.size());
StringBuilder result = new StringBuilder();
for ( int i = 0; i < middle; i++ ) {
result.append(grid[rowOne.get(i)][rowTwo.get(i)]);
}
return result.toString();
}
public void display() {
Arrays.stream(grid).forEach( row -> System.out.println(Arrays.toString(row)) );
}
private char[][] grid;
private Map<Character, Point> coordinates = new HashMap<Character, Point>();
Arrays.stream(grid).forEach( row -> System.out.println(Arrays.toString(row)) );
}
private char[][] grid;
private Map<Character, Point> coordinates = new HashMap<Character, Point>();
}

View file

@ -1,64 +1,64 @@
module Bifid_cipher (f, code$) {
n=sqrt(len(code$))
print #f," ";
for i=1 to n
print #f, i+" ";
next
print #f
for i=0 to n-1
Print #f, (i+1)+" "+STR$(mid$(code$,1+i*n, n),STRING$("@ ", 5))
next
tables=lambda (a$)->{
n=sqrt(len(a$))
a=list
for i=1 to len(a$)
append a, mid$(a$,i, 1):=((i-1) mod n+1, (i-1) div n+1 )
next
b=list
m=each(a)
while m
z=eval(m)
append b, z#val$(1)+z#val$(0):=eval$(m!)
end while
=a, b
}(code$)
encode= lambda (a, b)->{
=lambda a,b (mess as string) -> {
document code$
for n=1 to 0
for i=1 to len(mess)
q=mid$(mess, i,1)
if not exist(a, q) then
if q="J" then q="I" else q="A"
end if
code$=a(q)#val$(n)
next
next
document final$
for i=1 to len(code$) step 2
final$=b$(mid$(code$, i, 2))
next
= final$
}
}(!tables)
decode= lambda (a, b)->{
=lambda a,b (final as string) -> {
document code$, mess$
for i=1 to len(final)
q=a(mid$(final, i, 1))
code$=q#val$(1)+q#val$(0)
next
offset=len(code$) div 2
for i=1 to offset
mess$=b$(mid$(code$,i,1)+mid$(code$,i+offset,1))
next
= mess$
}
}(!tables)
Print #f, encode("ATTACKATDAWN")
Print #f, decode(encode("ATTACKATDAWN"))="ATTACKATDAWN"
Print #f, encode(ucase$(filter$("The invasion will start on the first of January", " ")))
Print #f, decode(encode(ucase$(filter$("The invasion will start on the first of January", " "))))
n=sqrt(len(code$))
print #f," ";
for i=1 to n
print #f, i+" ";
next
print #f
for i=0 to n-1
Print #f, (i+1)+" "+STR$(mid$(code$,1+i*n, n),STRING$("@ ", 5))
next
tables=lambda (a$)->{
n=sqrt(len(a$))
a=list
for i=1 to len(a$)
append a, mid$(a$,i, 1):=((i-1) mod n+1, (i-1) div n+1 )
next
b=list
m=each(a)
while m
z=eval(m)
append b, z#val$(1)+z#val$(0):=eval$(m!)
end while
=a, b
}(code$)
encode= lambda (a, b)->{
=lambda a,b (mess as string) -> {
document code$
for n=1 to 0
for i=1 to len(mess)
q=mid$(mess, i,1)
if not exist(a, q) then
if q="J" then q="I" else q="A"
end if
code$=a(q)#val$(n)
next
next
document final$
for i=1 to len(code$) step 2
final$=b$(mid$(code$, i, 2))
next
= final$
}
}(!tables)
decode= lambda (a, b)->{
=lambda a,b (final as string) -> {
document code$, mess$
for i=1 to len(final)
q=a(mid$(final, i, 1))
code$=q#val$(1)+q#val$(0)
next
offset=len(code$) div 2
for i=1 to offset
mess$=b$(mid$(code$,i,1)+mid$(code$,i+offset,1))
next
= mess$
}
}(!tables)
Print #f, encode("ATTACKATDAWN")
Print #f, decode(encode("ATTACKATDAWN"))="ATTACKATDAWN"
Print #f, encode(ucase$(filter$("The invasion will start on the first of January", " ")))
Print #f, decode(encode(ucase$(filter$("The invasion will start on the first of January", " "))))
}
open "out.txt" for output as #a
Bifid_cipher a, "ABCDEFGHIKLMNOPQRSTUVWXYZ"

View file

@ -0,0 +1,60 @@
require "table2"
class bifid
static function encrypt(polybius, message)
message = message:upper():replace("J", "I")
local rows = {}
local cols = {}
for i = 1, #message do
local c = message[i]
local ix = polybius:find(c, 1, true)
if !ix then continue end
rows:insert((ix - 1) // 5 + 1)
cols:insert((ix - 1) % 5 + 1)
end
local s = ""
for table.joined(rows, cols):chunk(2) as pair do
local ix = (pair[1] - 1) * 5 + pair[2]
s ..= polybius[ix]
end
return s
end
static function decrypt(polybius, message)
local rows = {}
local cols = {}
for i = 1, #message do
local c = message[i]
local ix = polybius:find(c, 1, true)
rows:insert((ix - 1) // 5 + 1)
cols:insert((ix - 1) % 5 + 1)
end
local lines = table.zip(rows, cols):flatten()
local count = #lines // 2
rows = lines:slice(1, count)
cols = lines:slice(count + 1)
local s = ""
for i = 1, count do
local ix = (rows[i] - 1) * 5 + cols[i]
s ..= polybius[ix]
end
return s
end
end
local poly1 = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
local poly2 = "BGWKZQPNDSIOAXEFCLUMTHYVR"
local poly3 = "PLAYFIREXMBCDGHKNOQSTUVWZ"
local polys = {poly1, poly2, poly2, poly3}
local msg1 = "ATTACKATDAWN"
local msg2 = "FLEEATONCE"
local msg3 = "The invasion will start on the first of January"
local msgs = {msg1, msg2, msg1, msg3}
for i = 1, #msgs do
local encrypted = bifid.encrypt(polys[i], msgs[i])
local decrypted = bifid.decrypt(polys[i], encrypted)
print($"Message : {msgs[i]}")
print($"Encrypted : {encrypted}")
print($"Decrypted : {decrypted}")
if i < #msgs then print() end
end

View file

@ -0,0 +1,137 @@
Rebol [
title: "Rosetta code: Bifid cipher"
file: %Bifid_cipher.r3
url: https://rosettacode.org/wiki/Bifid_cipher
]
make-square: function [
{Build a Polybius square from an alphabet string.
Returns a block of rows, each row a block of single-character strings.
The square is sized ceil(sqrt(len)) x ceil(sqrt(len)), with none padding
if the alphabet does not fill the last row exactly.}
alphabet [string!]
][
size: to-integer round/ceiling square-root length? alphabet
rows: copy []
row: copy []
i: 0
foreach ch alphabet [
append row ch
++ i
if i = size [
append/only rows row
row: copy []
i: 0
]
]
unless empty? row [ ;; pad final row with none
append/dup row none (size - length? row)
append/only rows row
]
new-line/all rows true
]
square-map: function [
{Return a map of character -> [row col] (1-based) for the given square.}
square [block!]
][
m: make map! 64
r: 1
foreach row square [
c: 1
foreach ch row [
if ch [ m/:ch: reduce [r c] ] ; skip none padding
++ c
]
++ r
]
m
]
encrypt: function [
{Encrypt plaintext using the bifid cipher with the given Polybius square.
Collects all row coordinates then all column coordinates, pairs them up,
and maps each pair back through the square.}
message [string!]
square [block!]
][
m: square-map square
rows: copy []
cols: copy []
foreach ch message [
if coord: m/:ch [
append rows coord/1
append cols coord/2
]
]
combined: append copy rows cols ;; [r1 r2 .. rN c1 c2 .. cN]
result: copy ""
i: 1
while [i < length? combined] [
r: pick combined i
c: pick combined i + 1
append result pick (pick square r) c
i: i + 2
]
result
]
decrypt: function [
{Decrypt ciphertext using the bifid cipher with the given Polybius square.
Splits the coordinate stream into the first half (rows) and second half
(cols), zips them, and maps each pair back through the square.}
message [string!]
square [block!]
][
m: square-map square
coords: copy []
foreach ch message [
if coord: m/:ch [ repend coords coord ]
]
half: (length? coords) / 2 ;; split interleaved coords at midpoint
rows: copy/part coords half
cols: copy/part (skip coords half) half
result: copy ""
i: 1
while [i <= half] [
r: rows/:i
c: cols/:i
append result square/:r/:c
++ i
]
result
]
normalize: func [
{Replace J with I for a standard 25-letter Polybius square.}
message [string!]
][
replace/all copy message "J" "I"
]
; --- Polybius squares used in test cases ---
typical-square: make-square "ABCDEFGHIKLMNOPQRSTUVWXYZ" ;; 25 letters, no J
example-square: make-square "BGWKZQPNDSIOAXEFCLUMTHYVR"
playfair-square: make-square "PLAYFIREXMBCDGHKNOQSTUVWZ"
digits-square: make-square "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
; --- Test cases ---
test-cases: reduce [
"ATTACKATDAWN" typical-square
"FLEEATONCE" example-square
"FLEEATONCE" typical-square
normalize "The invasion will start on the first of January" playfair-square
"The invasion will start on the first of January" digits-square
]
foreach [msg square] test-cases [
probe square
enc: encrypt msg square
dec: decrypt enc square
print ["Message :" msg]
print ["Encrypted:" enc]
print ["Decrypted:" dec]
print ""
]