If the plain text message was first enciphered using the affine transformation , then was enciphered again using the hill cipher , where matrix , find the enciphered text.
Encipher the message above and express the result as a string of integers.
Write a general program(in any language) to encipher and decipher a cipher of the above type. Check your program by deciphering the enciphered message obtained using the given affine transformation, the given matrix, and the plain text message above.
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.
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 doubleCipher;
const maxnum = 30;
var NUM,C1,Y:NUMARRAY;
PROCEDURE CONVERT_NUMTOTEXT(NUM:INTEGER; 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:INTEGER);
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 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}
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 plaintext message, no blanks.');
readln(holdstr);
NUMCHARS:= LENGTH(HOLDSTR);
FOR K:= 1 TO NUMCHARS DO
BEGIN
CONVERT_TEXTTONUM(HOLDSTR[K],NUM[K]);
END;
writeln;
writeln('Enter moduli');
readln(m);
writeln('Enter A');
readln(a1);
a1:= abs(a1); {safeguard}
writeln('Enter shift B');
readln(b1);
b1:= abs(b1); {safeguard}
while (GCF(A1,M) > 1) do
BEGIN
writeln('Renter A');
readln(a1);
a1:= abs(a1);
END;
GET NUMEQS NUMBLOCKS(NUMLINES,NUMBLOCKS);
END;
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 ENCIPHER;
VAR K:INTEGER;
BEGIN
WRITELN(' ENCIPHERED BLOCK(AFFINE TRANSFORMATION:');
WRITELN(' -----------------------------------------------------------------------');
FOR K:= 1 TO NUMCHARS DO
BEGIN
C1[K]:= (A1 * NUM[K] + B1) MOD M;
WRITE(C1[K],' ');
END;
WRITELN;
writeln;
WRITELN(' ENCIPHERED TEXT(AFFINE TRANSFORMATION:');
WRITELN(' --------------------------------------------------------------------');
WRITELN;
FOR K:= 1 TO NUMCHARS DO
BEGIN
CONVERT_NUMTOTEXT(C1[K],LETTER[K]);
WRITE(LETTER[K]);
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 ENCIPHER2;
VAR J,K:INTEGER;
BEGIN
FOR J:= 1 TO NUMBLOCKS DO
BEGIN
FOR K:= 1 TO NUMLINES DO
BEGIN
HOLDP[K,J]:= C1[(J - 1) * NUMLINES + K];
END;
END;
writeln; writeln;
STRTXT:= '';
WRITELN(' ENCIPHERED BLOCKS(HILL CIPHER):');
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(HILL CIPHER):');
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:integer);
var j,K:integer;
begin
for j:= 1 to n do
begin
X[J,J]:= A[J,N + 1] MOD M;
IF X[J,J] < 0 THEN
BEGIN
X[J,J]:= M + X[J,J];
END;
end;
end;
PROCEDURE DECIPHER;
VAR J,K,T,N,q:INTEGER;
BEGIN
writeln(' Deciphered Blocks using Hill cipher');
writeln(' ----------------------------------------------');
writeln;
writeln;
assign(myfile,'doublecipher.txt');
rewrite(myfile);
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);
for q:= 1 to numlines do
begin
writeln(myfile,x[q,q]); {write to file for affine transformation}
write(x[q,q],' ');
end;
FOR T:= 1 TO NUMLINES DO
BEGIN
FOR N:= 1 TO NUMLINES DO
BEGIN
A[T,N]:= HOLDA[T,N];
END;
END;
writeln;
END;
END;
procedure DECIPHER2;
VAR K,J,INVERSE_A1:INTEGER;
begin
reset(myfile);
for k:= 1 to numchars do
begin
readln(myfile,c1[k]);
end;
FOR K:= 1 TO NUMCHARS DO
BEGIN
FOR J:= -(M - 1) TO M - 1 DO
BEGIN
IF A1 * J MOD M = 1 THEN
BEGIN
INVERSE_A1:= J;
Y[K]:= ((C1[K] - B1) * INVERSE_A1) MOD M;
IF Y[K] < 0 THEN
Y[K]:= M + Y[K];
END;
END;
END;
WRITELN(' LIST OF INTEGERS TO DECIPHER USING AFFINE TRANSFORMATION');
WRITELN(' --------------------------------------------------------');
WRITELN;
FOR K:= 1 TO NUMCHARS DO
BEGIN
WRITE(Y[K],' ');
END;
WRITELN;
WRITELN(' DECIPHERED TEXT USING AFFINE TRANSFORM:');
WRITELN(' -----------------------------------------------------------------------');
WRITELN;
FOR K:= 1 TO NUMCHARS DO
BEGIN
CONVERT_NUMTOTEXT(Y[K],LETTER[K]);
WRITE(LETTER[K]);
END;
close(myfile);
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;
ENCIPHER2;
DECIPHER;
DECIPHER2;
readln;
end.
Running the program we obtain:
Enciphered Blocks:
1 6 2 1 1 7
1 2 7 2 4
5 2 3 1 5
5 2 0 6
1 3 5 2 3
Enciphered Text:
Q V R M H Y F X P F U G N F X
As a string of integers we have:
1 6 2 1 1 7 1 2 7 2 4 5 2 3 1 5 5 2 0 6 1 3 5 2 3
Deciphering we obtain:
T O D A Y I T W I L L S N O W