Encrypting string in ADA
I have to do a task where I write 3 type of encrypting methods. I've done it but somewhy it only works for upper letters.
crypto.ads
package crypto is
--private
type keys_arr is array( Natural range <> ) of Natural;
function Generate_key return Natural;
function Generate_keys(len: Positive) return keys_arr;
type keys(len:Positive) is record
single_key : Natural :=Generate_key;
multi_keys : keys_arr(1..len) := Generate_keys(len);
end record;
procedure print_key(k:keys);
function shift_char(c: Character; n:Integer) return Character;
function encrypt_caesar(x:String; k:keys ) return String;
function encrypt_vigenere_with_numbers(x:String; k:keys ) return String;
function encrypt_with_pos(x:String) return String;
function decrypt_caesar(x:String; k:keys ) return String;
function decrypt_vigenere_with_numbers(x:String; k:keys ) return String;
end crypto;
crypto.adb
with ada.numerics.discrete_random, Ada.Text_IO, Ada.Characters.Handling;
use Ada.Characters.Handling; --Ada.Characters;
package body crypto is
subtype Lower is Character range 'a' .. 'z';
subtype Upper is Character range 'A' .. 'Z';
-- type R is range 1..26;
-- upper letters from 65-90, lower letters from 97-122
--source: https://www.adaic.org/resources/add_content/standards/05rm/html/RM-A-5-2.html
function Generate_key return Natural is
package Random_Key is new Ada.Numerics.Discrete_Random (Natural);
use Random_Key;
Generator : Random_Key.Generator;
begin
-- english alphabet consisting 26 letters;
Random_key.Reset(Generator);
return Random_key.Random(Generator) mod 26;
end;
function Generate_keys(len: Positive) return keys_arr is
keys : keys_arr(1..len);
begin
for i in keys'range loop
keys(i) := Generate_key;
end loop;
return keys;
end;
procedure print_key(k:keys) is
begin
Ada.Text_IO.Put_Line("generated single_key is :" & integer'image(k.single_key));
Ada.Text_IO.Put_Line("generated multi_keys list is : ");
for i in k.multi_keys'range loop
Ada.Text_IO.Put(Integer'image(k.multi_keys(i)));
end loop;
end;
--my math is not working here somewhy
-- Its working for upper leters but not for lower letters
function shift_char(c: Character; n:Integer) return Character is
I : Integer;
begin
-- mod 26 to get the position of the letter in the range
-- +n , than second mod 26 if the sum is more than 26
--than add 97 or 65 because thats the beginning of the interval
-- if Character'Pos(c)>96 AND Character'Pos(c)<123 then
if Is_Lower(c) then
I:= ((((Character'Pos(c) rem 26) + n) mod 26) + 97);
-- elsif Character'Pos(c)<91 AND Character'Pos(c)>64 then
elsif Is_Upper(c) then
I:= ((((Character'Pos(c) rem 26) + n) mod 26) + 65);
end if;
return Character'val(I);
end;
function encrypt_caesar(x:String; k:keys ) return String is
stringrange: string(x'first..x'last);
begin
for i in x'range loop
if Is_Letter (x(i)) then
stringrange(i):= shift_char(x(i),k.single_key);
else
stringrange(i):= x(i);
end if;
end loop;
return stringrange;
end;
function encrypt_vigenere_with_numbers(x:String; k:keys ) return String is
stringrange: string(x'first..x'last);
ind : Natural := k.multi_keys'first;
begin
--ind:= k.multi_keys'first;
for i in x'range loop
if Is_Letter (x(i)) then
stringrange(i):= shift_char(x(i), k.multi_keys(ind));
-- if ind=k.multi_keys'last then
-- ind:=k.multi_keys'first;
--else ind := ind + 1;
--end if;
ind := (ind + 1) rem (k.multi_keys'length +1);
if ind = 0 then ind := 1;
end if;
else
stringrange(i):= x(i);
end if;
end loop;
return stringrange;
end;
function encrypt_with_pos(x:String) return String is
stringrange: string(x'first..x'last);
begin
--similar to shift char +encrypt caesar
for i in x'range loop
if Is_Letter(x(i)) then
if Character'Pos(x(i))<123 AND Character'Pos(x(i))>96 then
stringrange(i):= shift_char(x(i), Character'pos(x(i)) mod 97);
elsif Character'Pos(x(i))<91 then
stringrange(i):= shift_char (x(i), Character'pos(x(i)) mod 65);
end if;
else
stringrange(i):=x(i);
end if;
end loop;
return stringrange;
end;
-- opposite of encrypt caesar
function decrypt_caesar(x:String; k:keys ) return String is
stringrange: string(x'first..x'last);
begin
for i in x'range loop
stringrange(i):= shift_char(x(i), -k.single_key);
end loop;
return stringrange;
end;
-- opposite of encrypt vigenere
function decrypt_vigenere_with_numbers(x:String; k:keys ) return String is
stringrange: string(x'first..x'last);
ind : Natural:= k.multi_keys'first;
begin
-- ind:= k.multi_keys'first;
for i in x'range loop
if Is_Letter(x(i)) then
stringrange(i):= shift_char(x(i), -k.multi_keys(ind));
--if ind=k.multi_keys'last then
-- ind:=k.multi_keys'first;
--else ind := ind + 1;
--end if;
ind := (ind + 1) rem (k.multi_keys'length +1);
if ind = 0 then ind:= 1; end if;
else
stringrange(i) := x(i);
end if;
end loop;
return stringrange;
end;
crypto demo:
with crypto, Ada.Text_IO, Ada.Integer_Text_IO;
use crypto,Ada.Text_IO, Ada.Integer_Text_IO;
procedure crypto_demo is
k: Integer := 4;
st : String := ("Ada Is Cool");
st2 : String := ("Ada Is Cool");
st3 : String := ("Ada Is Cool");
begin
declare
V: Keys(k);
begin
Print_key(V);
new_Line(1);
Put("before encryption with caesar: ");
Put(st);
new_Line(1);
Put("encrypted:");
st:=encrypt_caesar(st,V);
Put(st);
new_Line(1);
Put("decrypted: ");
st:=decrypt_caesar(st,V);
Put(st);
new_Line(1);
Put("before encryption with vigenere: ");
Put(st2);
new_Line(1);
Put("encrypted: ");
st2:=encrypt_vigenere_with_numbers(st2,V);
Put(st2);
new_Line(1);
Put("deecrypted: ");
st2:=decrypt_vigenere_with_numbers(st2,V);
Put(st2);
new_Line(1);
Put("before encryption with position: ");
Put(st3);
new_Line(1);
Put("encrypted: ");
st3:=encrypt_with_pos(st3);
Put(st3);
new_Line(1);
end;
end crypto_demo;
So this is working for Upper letters but not for lower letters but im using the same method. The problem must be in my shift char function. Anyone have any idea?
Thank you PL
from Recent Questions - Stack Overflow https://ift.tt/3xzkPYa
https://ift.tt/eA8V8J
Comments
Post a Comment