2021-04-30

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

No comments:

Post a Comment