Блочное симметричное шифрование. Шифр DES (Отчет по практической работе № 4), страница 2

  private static int[] Shift  =

        {  1,  1,  2,  2,  2,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  1};

  private static int[] H  =

        { 14, 17, 11, 24, 01, 05, 03, 28, 15, 06, 21, 10, 23, 19, 12, 04,

          26, 08, 16, 07, 27, 20, 13, 02, 41, 52, 31, 37, 47, 55, 30, 40,

          51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32};

  private UInt64 key;

  public DES(String key)

  {

    this.key = 0;

    for (int j = 0; j < key.Length; j++)

    {

    this.key |= (UInt64)(key[j] & 0xFF) << (j * 8);

    }

  }

  private UInt64 Relocate(UInt64 val, int[] moves)

  {

    UInt64 result = 0;

    for (int i = 0; i < moves.Length; i++ )

    {

    result |= ((val >> (moves[i] - 1)) & 1ul) << i;

    }

    return result;

  }

  private UInt64 Key(UInt64 Key, int index)

  {

    UInt64 tmp = Relocate(Key, G);

    UInt64 C = tmp & 0xFFFFFFF;

    UInt64 D = (tmp >> 28) & 0xFFFFFFF;

    for (int i = 0; i < index; i++ )

    {

    for (int j = 0; j < Shift[i]; j++)

    {

      C = (C >> 27) | (C << 1);

      D = (D >> 27) | (D << 1);

    }

    }

    return Relocate((C << 28) | D, H);

  }

  private UInt32 f(UInt32 value, UInt64 key)

  {

    UInt64 tmp = Relocate(value, E) ^ key;

    UInt32 result = 0;

    int[] h = {1,6};

    int[] w = {2,3,4,5};

    for (int i = 0; i < 8; i++ )

    {

     UInt64 oct = (tmp >> (i * 6)) & 0x3F;

     result |= S[i, (int)Relocate(oct, h), (int)Relocate(oct, w)] << (i * 4);

    }

    return (UInt32)Relocate(result, P);

  }

  private UInt64 codeBlock(UInt64 value)

  {

    value = Relocate(value, IP);

    UInt32 R = (UInt32)(value & 0xFFFFFFFF);

    UInt32 L = (UInt32)((value >> 32) & 0xFFFFFFFF);

    for (int i = 1; i <= 16; i++)

    {

    UInt32 oldL = L;

    L = R;

    R = oldL ^ f(R, Key(key, i));

    }

    return Relocate(((UInt64)L << 32) | R , IPrev);

  }

  private UInt64 decodeBlock(UInt64 value)

  {

    value = Relocate(value, IP);

    UInt32 R = (UInt32)(value & 0xFFFFFFFF);

    UInt32 L = (UInt32)((value >> 32) & 0xFFFFFFFF);

    for (int i = 16; i > 0; i--)

    {

    UInt32 oldR = R;

    R = L;

    L = oldR ^ f(L, Key(key, i));

    }

    return Relocate(((UInt64)L << 32) | R, IPrev);

  }

  private UInt64[] messageSpliter(String message)

  {

    List<UInt64> result = new List<UInt64>();

    for (int i = 0; i < message.Length; i += 8)

    {

    UInt64 block = 0;

    for (int j = 0; j < 8 && (i + j) < message.Length; j++)

    {

      block |= (UInt64)(message[i + j] & 0xFF) << (j * 8);

    }

    result.Add(block);

    }

    return result.ToArray();

  }

  private String messageCollector(UInt64[] message)

  {

    StringBuilder result = new StringBuilder();

    for (int i = 0; i < message.Length; i++)

    {

    for (int j = 0; j < 8; j++)

    {

      result.Append((char)((message[i] >> j * 8) & 0xFF));

    }

    }

    return result.ToString();

  }

  public String Code(String message)

  {

    List<UInt64> codes = new List<UInt64>();

    foreach (UInt64 block in messageSpliter(message))

    {

    codes.Add(codeBlock(block));

    }

    return messageCollector(codes.ToArray());

  }

  public String Decode(String message)

  {

    List<UInt64> codes = new List<UInt64>();

    foreach (UInt64 block in messageSpliter(message))

    {

    codes.Add(decodeBlock(block));

    }

    return messageCollector(codes.ToArray());

  }

  }

}

3. Протестировать работу программы.

using System;

using System.Collections.Generic;

using System.Text;

using System.IO;

using Cripto.CodeAlgorithm;

using Cripto.CriptoAnalyze;

namespace Cripto

{

  class Program

  {

  static void Main(string[] args)

  {

    String c = null;

    do

    {

    String key = null;

    do

    {

      Console.Write("Введите ключ: ");

      key = Console.ReadLine();

      for (int i = key.Length; i % 8 != 0; i++) key += " ";

      if (key.Length > 8) Console.WriteLine("Ключ должен быть меньше 8 символов.");

    } while (key.Length > 8);

    DES des = new DES(key);

    CodeTest(des);

    Console.WriteLine("Повторить? (Y/N)");

    c = Console.ReadLine().ToUpper();

    }

    while (c.Equals("Y"));

  }

  static void CodeTest(Code code)

  {

    Console.WriteLine("Введите сообщение: ");

    String message = Console.ReadLine();

    Console.WriteLine("Зашифрование : ");

    String coded = code.Code(message);

    Console.WriteLine(coded);

    Console.WriteLine("Расшифрование: ");

    String decoded = code.Decode(coded);

    Console.WriteLine(decoded);

  }

  }

}

Результат работы программы:

Вывод: в ходе выполнения этой практической работы, я научился шифровать информацию с помощью блочного симметричного шифра DES.