Given the matrix , use a Hill cipher to encipher the message using modulo 26, where , , , , and enter the result as a string of integers.
Write a general program(in any language) to encipher and decipher a Hill cipher. Check your program by deciphering the enciphered message obtained using the given matrix and plain text message above.
Also, the program should not contain any predefined functions or procedures. That is you must create all functions and procedures and they should appear in the program, and not called from a library you created.
Note: For the program
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
I used Free Pascal to write the program:
program HillCipher; {self contained for brillant}
const maxnum = 30;
type matrix = array[1 .. maxnum,1 .. maxnum + 1] of longint;
var a,b,p,holdp,holdb,y,holda,newa:matrix;
PROCEDURE CONVERT_NUMTOTEXT(NUM:LONGINT; VAR LETTER:CHAR);
BEGIN
CASE NUM OF
0:LETTER:= 'A';
1:LETTER:= 'B';
2:LETTER:= 'C';
3:LETTER:= 'D';
4:LETTER:= 'E';
5:LETTER:= 'F';
6:LETTER:= 'G';
7:LETTER:= 'H';
8:LETTER:= 'I';
9:LETTER:= 'J';
10:LETTER:= 'K';
11:LETTER:= 'L';
12:LETTER:= 'M';
13:LETTER:= 'N';
14:LETTER:= 'O';
15:LETTER:= 'P';
16:LETTER:= 'Q';
17:LETTER:= 'R';
18:LETTER:= 'S';
19:LETTER:= 'T';
20:LETTER:= 'U';
21:LETTER:= 'V';
22:LETTER:= 'W';
23:LETTER:= 'X';
24:LETTER:= 'Y';
25:LETTER:= 'Z';
END;
END;
PROCEDURE CONVERT_TEXTTONUM(LETTER:CHAR; VAR NUM:LONGINT);
BEGIN
CASE UPCASE(LETTER) OF
'A':NUM:= 0;
'B':NUM:= 1;
'C':NUM:= 2;
'D':NUM:= 3;
'E':NUM:= 4;
'F':NUM:= 5;
'G':NUM:= 6;
'H':NUM:= 7;
'I':NUM:= 8;
'J':NUM:= 9;
'K':NUM:= 10;
'L':NUM:= 11;
'M':NUM:= 12;
'N':NUM:= 13;
'O':NUM:= 14;
'P':NUM:= 15;
'Q':NUM:= 16;
'R':NUM:= 17;
'S':NUM:= 18;
'T':NUM:= 19;
'U':NUM:= 20;
'V':NUM:= 21;
'W':NUM:= 22;
'X':NUM:= 23;
'Y':NUM:= 24;
'Z':NUM:= 25;
END;
END;
function prime(p:integer):boolean;
var n:integer;
PROCEDURE GET NUMEQS NUMBLOCKS(VAR NUMEQS,NUMBLOCKS:INTEGER);
VAR K:INTEGER;
BEGIN
IF PRIME(NUMCHARS) THEN
BEGIN
NUMEQS:= NUMCHARS;
NUMBLOCKS:= 1;
END
ELSE
BEGIN
FOR K:= 2 TO (NUMCHARS - 1) DO
BEGIN
IF NUMCHARS MOD K = 0 THEN
NUMEQS:= NUMCHARS DIV K;
END;
BOOL:= TRUE;
K:= 1;
WHILE BOOL DO
BEGIN
K:= K + 1;
IF NUMCHARS MOD K = 0 THEN
BEGIN
NUMBLOCKS:= NUMCHARS DIV K; {FOR SMALLEST FACTOR}
BOOL:= FALSE;
END;
END;
END;
END;
PROCEDURE INITDATA;
VAR HOLDSTR:STRING;
BEGIN
writeln('Enter Plainrext Message, leave no blanks');
readln(holdstr);
writeln;
NUMCHARS:= LENGTH(HOLDSTR);
GET NUMEQS NUMBLOCKS(NUMLINES,NUMBLOCKS);
FOR J:= 1 TO NUMBLOCKS DO
BEGIN
FOR K:= 1 TO NUMLINES DO
BEGIN
CONVERT_TEXTTONUM(HOLDSTR[(J - 1) * NUMLINES + K],HOLDP[K,J]);
END;
END;
writeln('Enter moduli');
readln(m);
END;
function gcf(m,k:LONGINT):LONGINT;
var n,factor,min:longint;
begin{gcf}
if m <= k then
min:= m
else min:= k;
for n:= 1 to min do
begin{loop}
if (k mod n = 0) and (m mod n = 0)
end;{loop}
gcf:= factor;
end;{gcf}
PROCEDURE INITDATA1A;
VAR J,K:INTEGER;
BEGIN
FOR J:= 1 TO NUMLINES DO
begin
writeln('Enter row', j,' of Matrix');
FOR K:= 1 TO NUMLINES DO
begin
read(a[j,k]);
end;
writeln;
end;
for k:= 1 to numlines do
begin
for j:= 1 to numlines do
begin
holda[k,j]:= a[k,j];
end;
end;
end;
procedure matrixmult(a,b:matrix; var summat:matrix);
var j,k,s:integer;
begin{matrixmult}
for j:= 1 to NUMLINES do
begin{j}
for k:= 1 to 1 do
begin{k}
for s:= 1 to NUMLINES do
begin{s}
end;{s}
end;{k}
end;{j}
end;{matrixmult}
PROCEDURE ENCIPHER;
VAR J,K:INTEGER;
BEGIN
WRITELN(' PLAIN TEXT BLOCKS:');
WRITELN(' ------------------');
FOR J:= 1 TO NUMBLOCKS DO
BEGIN
STRSUM2:= '';
FOR K:= 1 TO NUMLINES DO
BEGIN
STR(HOLDP[K,J],STRP);
STRSUM2:= STRSUM2 + STRP + ' ';
END;
WRITELN(' BLOCK',J,':',STRSUM2);
END;
WRITELN;
STRTXT:= '';
WRITELN(' ENCIPHERED BLOCKS:');
WRITELN(' ------------------');
FOR J:= 1 TO NUMBLOCKS DO
BEGIN
STRSUM:= '';
FOR K:= 1 TO NUMLINES DO
BEGIN
P[K,1]:= HOLDP[K,J];
END;
MATRIXMULT(A,P,B);
FOR K:= 1 TO NUMLINES DO
BEGIN
B[K,1]:= B[K,1] MOD M;
STR(B[K,1],STRB);
HOLDB[K,J]:= B[K,1];
STRSUM:= STRSUM + STRB + ' ';
CONVERT_NUMTOTEXT(B[K,1],LETTER);
STRTXT:= STRTXT + LETTER;
END;
WRITELN(' BLOCK',J,':',STRSUM);
END;
WRITELN;
WRITELN(' ENCIPHERED TEXT IS:');
WRITELN(' -------------------');
WRITELN(' ',STRTXT);
writeln;
writeln;
END;
procedure hold(VAR C:REALMATRIX; A:MATRIX);
var k,j:integer;
begin
for k:= 1 to numlines do
begin
for j:= 1 to numlines do
begin
c[k,j]:= a[k,j];
end;
end;
end;
procedure switch2(var c:realmatrix; l,p,n:integer);
var m:integer;
begin{switch}
for m:= 1 to n do
begin{m}
end;{m}
end;{switch}
procedure safeguard2(var c:realmatrix; l:integer; var p:integer; n:integer; var v:integer; var product:real);
var m:integer;
begin{safeguard}
v:=0;
if (c[l,l] = 0) then
begin{then}
v:= 1;
m:= l;
while ((m + 1) <= n) and (v = 1) do
begin{loop}
if c[m + 1,l] <> 0 then
begin{then}
end;{then}
m:= m + 1;
end;{loop}
end;{then}
end;{safeguard}
procedure operation1(var a:realmatrix; l,n:integer; VAR PRODUCT:REAL);
var k,m:integer;
procedure operation2(var a:realmatrix; l,n:integer);
var k,m,q:integer;
FUNCTION DETERMINANT(a:realmatrix; n:integer; PRODUCT:REAL):integer;
var j,m:integer;
begin{DETERMINANT}
DIAGONAL:= 1;
FOR j:= 1 TO N DO
BEGIN{LOOP}
DIAGONAL:= DIAGONAL * (a[j,j]);
END;{LOOP}
IF DIAGONAL = 1 THEN
DET:= 1/PRODUCT
ELSE
DET:= 0;
DETERMINANT:= ROUND(DET);
END;{DETERMINANT}
procedure switch(var c:matrix; l,p,n:integer);
var m:integer;
begin{switch}
for m:= 1 to n + 1 do
begin{m}
end;{m}
end;{switch}
procedure safeguard(var c:matrix; l:integer; var p:integer; n:integer; var v:integer);
var j:integer;
begin{safeguard}
v:= 0;
if (c[l,l] mod m = 0) or (gcf(c[l,l],m) <> 1) then
begin{then}
v:= 1;
j:= l;
while ((j + 1) <= n) and (v = 1) do
begin{loop}
if (c[j + 1,l] mod m <> 0) and (gcf(c[j + 1,l],m) = 1) then
begin{then}
end;{then}
j:= j + 1;
end;{loop}
end;{then}
end;{safeguard}
procedure operation11(var a:matrix; l,n:integer);
var j,k,i,inverse:longint;
begin{op1}
for i:= 0 to m - 1 do
begin
if (a[l,l] * i) mod m = 1 then
begin
inverse:= i;
end;
end;
for j:= 1 to n + 1 do
begin
s[l,j]:= (a[l,j] * inverse) mod m;
if s[l,j] < 0 then
s[l,j]:= m + s[l,j];
end;
for j:= 1 to n + 1 do
begin{j}
a[l,j]:= s[l,j];
end;{j}
for k:= 1 to n do
begin
for j:= 1 to n + 1 do
begin
a[k,j]:= a[k,j] mod m;
if a[k,j] < 0 then
a[k,j]:= m + a[k,j];
end;
end;
end;{op1}
procedure operation21(var a:matrix; l,n:integer);
var q,j,k,x:longint;
begin{op2}
for q:= 1 to n do
begin{q}
if q <> l then
begin{then}
x:= m - a[q,l];
for j:= 1 to n + 1 do
begin{j}
s[q,j]:= (x * a[l,j] + a[q,j]);
end;{j}
for j:= 1 to n + 1 do
begin{j}
a[q,j]:= s[q,j];
end;{j}
end;{then}
end;{q}
for k:= 1 to n do
begin
for j:= 1 to n + 1 do
begin
a[k,j]:= a[k,j] mod m;
if a[k,j] < 0 then
a[k,j]:= m + a[k,j];
end;
end;
end;{op2}
procedure onesol(var a:matrix; n,r:integer);
var j,K:integer;
begin
strsum:= '';
for j:= 1 to n do
begin
X[J,J]:= A[J,N + 1] MOD M;
Y[J,R]:= X[J,J];
IF X[J,J] < 0 THEN
BEGIN
X[J,J]:= M + X[J,J];
Y[J,R]:= X[J,J];
END;
end;
FOR K:= 1 TO N DO
BEGIN
STR(X[K,K],STRBkk);
STRSUM:= STRSUM + STRBkk + ' ';
END;
end;
PROCEDURE DECIPHER;
VAR J,K,T,N:INTEGER;
BEGIN
WRITELN(' DECIPHERED BLOCKS');
WRITELN(' -----------------');
FOR J:= 1 TO NUMBLOCKS DO
BEGIN
FOR K:= 1 TO NUMLINES DO
BEGIN
A[K,NUMLINES + 1]:= HOLDB[K,J];
END;
for l:= 1 to numlines do
begin{l}
safeguard(a,l,r,numlines,v);
if v = 0 then
begin{then}
operation11(a,l,numlines);
operation21(a,l,numlines);
end;{then}
end;{l}
ONESOL(A,NUMLINES,J);
WRITELN(' ',STRSUM);
FOR T:= 1 TO NUMLINES DO
BEGIN
FOR N:= 1 TO NUMLINES DO
BEGIN
A[T,N]:= HOLDA[T,N];
END;
END;
END;
STRTEXT:= '';
FOR J:= 1 TO NUMBLOCKS DO
BEGIN
FOR K:= 1 TO NUMLINES DO
BEGIN
CONVERT_NUMTOTEXT(Y[K,J],LETTER);
STRTEXT:= STRTEXT + LETTER;
END;
END;
WRITELN(' DECIPHERED TEXT IS:');
WRITELN(' ',STRTEXT);
END;
begin
INITDATA;
INITDATA1A;
hold(C,A); {testing to see if (m,det(a)) = 1}
PRODUCT:= 1;
for l:= 1 to numlines do
begin{l}
safeguard2(c,l,r,numlines,v,PRODUCT);
if v = 0 then
begin{then}
operation1(c,l,numlines,PRODUCT);
operation2(c,l,numlines);
end;{then}
end;{l}
DET:= DETERMINANT(c,numlines,PRODUCT);
WHILE (gcf(m,abs(det)) <> 1) or (det mod m = 0) DO
BEGIN
writeln(' GCF(M,DET(A)) <> 1.REENTER MATRIX ');
INITDATA1A;
hold(C,A); {testing to see if (m,det(a)) = 1}
PRODUCT:= 1;
for l:= 1 to numlines do
begin{l}
safeguard2(c,l,r,numlines,v,PRODUCT);
if v = 0 then
begin{then}
operation1(c,l,numlines,PRODUCT);
operation2(c,l,numlines);
end;{then}
end;{l}
DET:= DETERMINANT(c,numlines,PRODUCT);
END;
ENCIPHER;
DECIPHER;
readln;
end.
Running the program with the given data we obtain:
Enciphered Blocks:
8 2 3 1 5
7 1 8 1
4 0 1 2
1 7 3 7
6 1 1 5
2 2 5 1 8
1 8 7 2 5
Enciphered Message:
I X P H S B E A M R D H G L F C Z S S H Z
Deciphered Blocks:
1 9 1 4 1 2
1 4 1 7 1 7
1 4 2 2 8
1 8 1 3 1 4
1 9 0 6
1 4 1 4 3
3 0 2 4
Deciphered Message:
T O M O R R O W I S N O T A G O O D D A Y
As a string of integers the enciphered Blocks are: 8 2 3 1 5 7 1 8 1 4 0 1 2 1 7 3 7 6 1 1 5 2 2 5 1 8 1 8 7 2 5