1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | -- PragmAda Reusable Component (PragmARC)
-- Copyright (C) 2023 by PragmAda Software Engineering. All rights reserved.
-- Released under the terms of the BSD 3-Clause license; see https://opensource.org/licenses
-- **************************************************************************
--
-- Implementation of the Bifid cipher
--
-- 2023 May 15 J. Carter V1.0--Initial version
--
with Ada.Characters.Handling;
package body PragmARC.Encryption.Bifid is
type Coord_List is array (Positive range <>) of Index;
type Coordinate is record
Row : Index;
Col : Index;
end record;
function Find (Letter : in Upper; Key : in Square_Layout) return Coordinate with Pre => Letter /= 'J';
function Find (Letter : in Upper; Key : in Square_Layout) return Coordinate is
begin -- Find
All_Rows : for R in Key'Range loop
All_Cols : for C in Key (R)'Range loop
if Key (R) (C) = Letter then
return (Row => R, Col => C);
end if;
end loop All_Cols;
end loop All_Rows;
raise Program_Error with Letter & " not found in Key";
end Find;
function Encrypt (Plaintext : in String; Key : in Square_Layout) return String is
function Cleaned (Source : in String) return String with
Post => Valid_Ciphertext (Cleaned'Result) and Cleaned'Result'First = 1;
-- Converts Source to upper case, removes non-letters, and changes 'J' to 'I'
function Cleaned (Source : in String) return String is
Capped : constant String := Ada.Characters.Handling.To_Upper (Source);
Result : String (1 .. Source'Length);
Last : Natural := 0;
begin -- Cleaned
All_Source : for C of Capped loop
case C is
when Upper =>
Last := Last + 1;
Result (Last) := (if C = 'J' then 'I' else C);
when others =>
null;
end case;
end loop All_Source;
return Result (1 .. Last);
end Cleaned;
Input : constant String := Cleaned (Plaintext);
Loc : Coordinate;
Row : Coord_List (Input'Range); -- Row in Key containing corresponding letter from Input
Col : Coord_List (Input'Range); -- Col in Key containing corresponding letter from Input
Coord : Coord_List (1 .. 2 * Input'Length); -- Row & Col
Result : String (Input'Range);
begin -- Encrypt
Get_Coords : for I in Input'Range loop
Loc := Find (Input (I), Key);
Row (I) := Loc.Row;
Col (I) := Loc.Col;
end loop Get_Coords;
Coord := Row & Col;
Convert : for I in Result'Range loop
Result (I) := Key (Coord (2 * I - 1) ) (Coord (2 * I) );
end loop Convert;
return Result;
end Encrypt;
function Decrypt (Ciphertext : in String; Key : in Square_Layout) return String is
Loc : Coordinate;
Coord : Coord_List (1 .. 2 * Ciphertext'Length);
Row : Coord_List (Ciphertext'Range); -- Coord (1 .. Ciphertext'Length)
Col : Coord_List (Ciphertext'Range); -- Coord (Ciphertext'Length + 1 .. Coord'Last)
Result : String (Ciphertext'Range);
begin -- Decrypt
Get_Coords : for I in Ciphertext'Range loop
Loc := Find (Ciphertext (I), Key);
Coord (2 * I - 1) := Loc.Row;
Coord (2 * I) := Loc.Col;
end loop Get_Coords;
Row := Coord (1 .. Ciphertext'Length);
Col := Coord (Ciphertext'Length + 1 .. Coord'Last);
Convert : for I in Result'Range loop
Result (I) := Key (Row (I) ) (Col (I) );
end loop Convert;
return Result;
end Decrypt;
end PragmARC.Encryption.Bifid;
|