Advertisement
Guest User

TI3 17.11 13:50

a guest
Nov 17th, 2019
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 14.74 KB | None | 0 0
  1. unit Unit2;
  2.  
  3. interface
  4.  
  5. uses
  6.    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  7.    System.Classes, Vcl.Graphics,
  8.    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Math, Vcl.Grids;
  9.  
  10. type
  11.    TIntArray = array of Int64;
  12.    TBoolArray = array of Boolean;
  13.    TBytesToPrint = array of Byte;
  14.    TIntToPrint = array of Integer;
  15.  
  16.    TForm2 = class(TForm)
  17.       mmPlainText: TMemo;
  18.       Файл: TButton;
  19.       OpenDialog: TOpenDialog;
  20.       edtP: TEdit;
  21.       Button2: TButton;
  22.       Label2: TLabel;
  23.       ListBox: TListBox;
  24.       edtG: TEdit;
  25.       Label3: TLabel;
  26.       edtX: TEdit;
  27.       Label4: TLabel;
  28.       Label5: TLabel;
  29.       edtOpenKey: TEdit;
  30.       Label6: TLabel;
  31.       Label7: TLabel;
  32.       edtPrivateKey: TEdit;
  33.       Label8: TLabel;
  34.       edtK: TEdit;
  35.       Button6: TButton;
  36.       sgOutput: TStringGrid;
  37.       Label1: TLabel;
  38.       Label9: TLabel;
  39.       procedure ProcessCode(FileName: string);
  40.       procedure ФайлClick(Sender: TObject);
  41.       procedure Button2Click(Sender: TObject);
  42.       procedure edtPKeyPress(Sender: TObject; var Key: Char);
  43.       procedure CheckEnteredNumber(Sender: TObject; Ident: Char;
  44.         var Number: string; BottomLine: Integer; TopLine: Int64);
  45.       procedure FormCreate(Sender: TObject);
  46.       procedure ListBoxClick(Sender: TObject);
  47.       procedure edtXKeyPress(Sender: TObject; var Key: Char);
  48.       procedure CheckEnteredNumberExt(Sender: TObject; Ident: Char;
  49.         var Number: string; BottomLine: Integer; TopLine: Int64);
  50.       procedure edtKKeyPress(Sender: TObject; var Key: Char);
  51.       procedure Button6Click(Sender: TObject);
  52.    private
  53.       { Private declarations }
  54.    public
  55.       { Public declarations }
  56.    end;
  57.  
  58. var
  59.    Form2: TForm2;
  60.    NumberP, NumberX, NumberG, NumberK: string;
  61.    fNameCipher, fNameDecipher: string;
  62.  
  63. const
  64.    AMOUNT_ROOTS = 10000;
  65.    cBytesMax = 128;
  66.  
  67. implementation
  68.  
  69. {$R *.dfm}
  70.  
  71. function IsPrimeNumber(Number: Int64): Boolean;
  72. var
  73.    i: Integer;
  74. begin
  75.    result := false;
  76.    if not Odd(Number) and (Number <> 2) then
  77.       Exit;
  78.    i := 3;
  79.    while i <= Sqrt(Number) do
  80.    begin
  81.       if Number mod i = 0 then
  82.          Exit;
  83.       inc(i, 2);
  84.    end;
  85.    result := true;
  86. end;
  87.  
  88. function FastExp(Number, Degree, Module: Int64): Int64;
  89. var
  90.    Num, Deg, Res, TempNum: Int64;
  91. begin
  92.    Num := Number;
  93.    Deg := Degree;
  94.    Res := 1;
  95.    while Deg <> 0 do
  96.    begin
  97.       while (Deg mod 2) = 0 do
  98.       begin
  99.          Deg := Deg div 2;
  100.          TempNum := Num mod Module;
  101.          Num := (TempNum * TempNum) mod Module;
  102.       end;
  103.       Deg := Deg - 1;
  104.       Res := (Res * Num) mod Module;
  105.    end;
  106.    FastExp := Res;
  107. end;
  108.  
  109. function FastExpMul(Number, Degree, Module: Int64;
  110.   var Multiplier: Integer): Int64;
  111. var
  112.    TempRes, TempInt: Int64;
  113. begin
  114.    TempRes := FastExp(Number, Degree, Module);
  115.    TempInt := Multiplier mod Module;
  116.    FastExpMul := (TempRes * TempInt) mod Module;
  117. end;
  118.  
  119. function FastExpMulByte(Number, Degree, Module: Int64;
  120.   var Multiplier: Byte): Int64;
  121. var
  122.    TempRes, TempInt: Int64;
  123. begin
  124.    TempRes := FastExp(Number, Degree, Module);
  125.    TempInt := Multiplier mod Module;
  126.    FastExpMulByte := (TempRes * TempInt) mod Module;
  127. end;
  128.  
  129. function ExtendedGCD(a, b: Integer; var x, y, gcd: Integer): Integer;
  130. var
  131.    x1, y1: Integer;
  132. begin
  133.    If b = 0 Then
  134.    begin
  135.       gcd := a;
  136.       x := 1;
  137.       y := 0;
  138.       Exit
  139.    end;
  140.    ExtendedGCD(b, a mod b, x1, y1, gcd);
  141.    x := y1;
  142.    y := x1 - (a div b) * y1;
  143.    result := gcd;
  144. end;
  145.  
  146. function FindPrimeDividers(Number: Int64; var Amount: Int64): TIntArray;
  147. var
  148.    i, j, k: Int64;
  149.    PrimeArray, ResArray: TIntArray;
  150. begin
  151.    SetLength(PrimeArray, Number);
  152.    for i := 2 to Number do
  153.       if Number mod i = 0 then
  154.       begin
  155.          k := 0;
  156.          for j := 2 to i div 2 do
  157.             if i mod j = 0 then
  158.                k := k + 1;
  159.          if k = 0 then
  160.          begin
  161.             PrimeArray[Amount] := i;
  162.             inc(Amount);
  163.          end;
  164.       end;
  165.    SetLength(ResArray, Amount);
  166.    for i := 0 to Amount - 1 do
  167.       ResArray[i] := PrimeArray[i];
  168.    FindPrimeDividers := ResArray;
  169. end;
  170.  
  171. function FindPrimRoots(p: Int64): TIntArray;
  172. var
  173.    PrimDeviders, PrimRoots, ResArray: TIntArray;
  174.    BoolArray: TBoolArray;
  175.    i, j, PrimDivNum, PrimRootNum: Int64;
  176. begin
  177.    SetLength(PrimDeviders, p);
  178.    SetLength(PrimRoots, p);
  179.    SetLength(BoolArray, p);
  180.    for i := 0 to p - 1 do
  181.       BoolArray[i] := true;
  182.    PrimDivNum := 0;
  183.    PrimRootNum := 0;
  184.    PrimDeviders := FindPrimeDividers(p - 1, PrimDivNum);
  185.    for i := 2 to p - 1 do
  186.    begin
  187.       for j := 1 to PrimDivNum do
  188.       begin
  189.          if (FastExp(i, round((p - 1) / PrimDeviders[j - 1]), p) = 1) then
  190.          begin
  191.             BoolArray[i] := false;
  192.             break;
  193.          end;
  194.       end;
  195.       if BoolArray[i] = true then
  196.       begin
  197.          PrimRoots[PrimRootNum] := i;
  198.          inc(PrimRootNum);
  199.       end;
  200.    end;
  201.    SetLength(ResArray, PrimRootNum);
  202.    for i := 0 to PrimRootNum - 1 do
  203.       ResArray[i] := PrimRoots[i];
  204.    FindPrimRoots := ResArray;
  205. end;
  206.  
  207. procedure TForm2.Button2Click(Sender: TObject);
  208. var
  209.    i: Integer;
  210.    OutputArray: TIntArray;
  211.    k: Int64;
  212. begin
  213.    CheckEnteredNumber(edtP, 'p', NumberP, 257, 9223372036854775807);
  214.    CheckEnteredNumber(edtX, 'x', NumberX, 2, StrToInt64(NumberP) - 1);
  215.    CheckEnteredNumberExt(edtK, 'k', NumberK, 2, StrToInt64(NumberP) - 1);
  216.    if (NumberP <> ' ') and (NumberX <> ' ') and (NumberK <> ' ') then
  217.    begin
  218.       SetLength(OutputArray, StrToInt64(NumberP));
  219.       OutputArray := FindPrimRoots(StrToInt64(NumberP));
  220.       i := 0;
  221.       if high(OutputArray) > AMOUNT_ROOTS then
  222.          k := AMOUNT_ROOTS
  223.       else
  224.          k := high(OutputArray);
  225.       while (i <= k) do
  226.       begin
  227.          ListBox.Items.Insert(i, inttostr(OutputArray[i]));
  228.          inc(i);
  229.       end;
  230.    end;
  231. end;
  232.  
  233. function IsPrimeButton(Number: Int64): Boolean;
  234. begin
  235.    if IsPrimeNumber(Number) then
  236.       result := true
  237.    else
  238.       result := false;
  239. end;
  240.  
  241. procedure EncryptLFSR(InputFileName, OutputFileName: string;
  242.   var Output: TIntToPrint);
  243. var
  244.    InputBuffer: array [1 .. cBytesMax div 2] of Byte;
  245.    OutputBuffer: array [1 .. cBytesMax] of Integer;
  246.    InputStream, OutputStream: TFileStream;
  247.    cBytes, i, j: Integer;
  248.    IsOutputFilled: Boolean;
  249.    y, a, k, p: Int64;
  250. begin
  251.    NumberG := Form2.edtG.text;
  252.    y := FastExp(StrToInt64(Form2.edtG.text), StrToInt64(NumberX),
  253.      StrToInt64(NumberP));
  254.    Form2.edtOpenKey.text := NumberP + ', ' + NumberG + ', ' + inttostr(y);
  255.    Form2.edtPrivateKey.text := NumberX;
  256.    a := FastExp(StrToInt64(Form2.edtG.text), StrToInt64(NumberK),
  257.      StrToInt64(NumberP));
  258.    k := StrToInt64(NumberK);
  259.    p := StrToInt64(NumberP);
  260.    InputStream := TFileStream.Create(InputFileName, fmOpenRead);
  261.    OutputStream := TFileStream.Create(OutputFileName, fmCreate);
  262.    IsOutputFilled := false;
  263.    SetLength(Output, cBytesMax);
  264.    repeat
  265.       cBytes := InputStream.ReadData(InputBuffer);
  266.       i := 1;
  267.       j := 1;
  268.       while i <= cBytes * 2 do
  269.       begin
  270.          OutputBuffer[i] := a;
  271.          OutputBuffer[i + 1] := FastExpMulByte(y, k, p, InputBuffer[j]);
  272.          if not IsOutputFilled then
  273.          begin
  274.             Output[i - 1] := OutputBuffer[i];
  275.             Output[i] := OutputBuffer[i + 1];
  276.          end;
  277.          inc(i, 2);
  278.          inc(j, 1);
  279.       end;
  280.       if not IsOutputFilled then
  281.       begin
  282.          SetLength(Output, cBytes * 2);
  283.          IsOutputFilled := true;
  284.       end;
  285.       OutputStream.WriteData(OutputBuffer, cBytes * 2 * SizeOf(Integer));
  286.    until (InputStream.Position = InputStream.Size);
  287.    InputStream.Free;
  288.    OutputStream.Free;
  289. end;
  290.  
  291. procedure DecryptLFSR(InputFileName, OutputFileName: string;
  292.   var Output: TBytesToPrint);
  293. var
  294.    InputBuffer: array [1 .. cBytesMax] of Integer;
  295.    OutputBuffer: array [1 .. cBytesMax div 2] of Byte;
  296.    InputStream, OutputStream: TFileStream;
  297.    cBytes, i, j: Integer;
  298.    IsOutputFilled: Boolean;
  299.    Degr: Int64;
  300. begin
  301.    Degr := (StrToInt64(NumberP) - 1 - StrToInt64(NumberX));
  302.    InputStream := TFileStream.Create(InputFileName, fmOpenRead);
  303.    OutputStream := TFileStream.Create(OutputFileName, fmCreate);
  304.    IsOutputFilled := false;
  305.    SetLength(Output, cBytesMax div 2);
  306.    repeat
  307.       cBytes := InputStream.ReadData(InputBuffer);
  308.       i := 1;
  309.       j := 1;
  310.       while i <= cBytes div 4 do
  311.       begin
  312.          OutputBuffer[j] := FastExpMul(InputBuffer[i], Degr,
  313.            StrToInt64(NumberP), InputBuffer[i + 1]);
  314.          if not IsOutputFilled then
  315.          begin
  316.             Output[j - 1] := OutputBuffer[j];
  317.          end;
  318.          inc(i, 2);
  319.          inc(j, 1);
  320.       end;
  321.       if not IsOutputFilled then
  322.       begin
  323.          SetLength(Output, cBytes div 2  div SizeOf(Integer));
  324.          IsOutputFilled := true;
  325.       end;
  326.       OutputStream.WriteData(OutputBuffer, cBytes div 2 div SizeOf(Integer));
  327.    until (InputStream.Position = InputStream.Size);
  328.    InputStream.Free;
  329.    OutputStream.Free;
  330. end;
  331.  
  332.  
  333.  
  334. procedure TForm2.Button6Click(Sender: TObject);
  335. var
  336.    Output: TBytesToPrint;
  337.    i, j: Integer;
  338. begin
  339.    if OpenDialog.Execute then
  340.    begin
  341.       DecryptLFSR(OpenDialog.FileName, fNameDecipher, Output);
  342.       if Length(Output) > 0 then
  343.       begin
  344.          sgOutput.RowCount := Length(Output) + 1;
  345.          i := Low(Output);
  346.          j := Low(Output);
  347.          while i <= High(Output) do
  348.          begin
  349.             {sgOutput.Cells[2, j + 1] := inttostr(Output[i]) + ', ' +
  350.               inttostr(Output[i + 1]);
  351.             inc(i, 2);
  352.             inc(j);}
  353.             sgOutput.Cells[2, i + 1] := inttostr(Output[i]);
  354.             inc(i);
  355.          end;
  356.       end;
  357.    end;
  358. end;
  359.  
  360. procedure TForm2.CheckEnteredNumber(Sender: TObject; Ident: Char;
  361.   var Number: string; BottomLine: Integer; TopLine: Int64);
  362. begin
  363.    with Sender as TEdit do
  364.       if Number <> ' ' then
  365.       begin
  366.          if (StrToInt64(Number) >= BottomLine) and (StrToInt64(Number) < TopLine)
  367.          then
  368.          begin
  369.             if not IsPrimeButton(StrToInt64(Number)) then
  370.             begin
  371.                ShowMessage('Число ' + Ident + ' должно быть простым');
  372.                Number := ' ';
  373.                Clear;
  374.             end;
  375.          end
  376.          else
  377.          begin
  378.             ShowMessage('Введите число ' + Ident + ' больше ' +
  379.               inttostr(BottomLine - 1) + ' меньше ' + inttostr(TopLine));
  380.             Number := ' ';
  381.             Clear;
  382.          end;
  383.       end
  384.       else
  385.       begin
  386.          ShowMessage('Введите простое число ' + Ident);
  387.          Number := ' ';
  388.          Clear;
  389.       end;
  390. end;
  391.  
  392. procedure TForm2.CheckEnteredNumberExt(Sender: TObject; Ident: Char;
  393.   var Number: string; BottomLine: Integer; TopLine: Int64);
  394. var
  395.    x, y, gcd: Integer;
  396. begin
  397.    with Sender as TEdit do
  398.    begin
  399.       if Number <> ' ' then
  400.       begin
  401.          if (StrToInt64(Number) >= BottomLine) and (StrToInt64(Number) < TopLine)
  402.          then
  403.          begin
  404.             if not IsPrimeButton(StrToInt64(Number)) then
  405.             begin
  406.                ShowMessage('Число ' + Ident + ' должно быть простым');
  407.                Number := ' ';
  408.                Clear;
  409.             end;
  410.          end
  411.          else
  412.          begin
  413.             ShowMessage('Введите число ' + Ident + ' больше ' +
  414.               inttostr(BottomLine - 1) + ' меньше ' + inttostr(TopLine));
  415.             Number := ' ';
  416.             Clear;
  417.          end;
  418.       end
  419.       else
  420.       begin
  421.          ShowMessage('Введите простое число ' + Ident);
  422.          Number := ' ';
  423.          Clear;
  424.       end;
  425.       if NumberK <> ' ' then
  426.          if ExtendedGCD(StrToInt64(NumberK), StrToInt64(NumberP) - 1, x, y,
  427.            gcd) <> 1 then
  428.          begin
  429.             ShowMessage('Введите число k взаимно простое с p - 1');
  430.             Number := ' ';
  431.             Clear;
  432.          end;
  433.    end;
  434. end;
  435.  
  436. procedure TForm2.edtKKeyPress(Sender: TObject; var Key: Char);
  437. const
  438.    Digit: set of Char = ['0' .. '9'];
  439. begin
  440.    if Key in Digit then
  441.       NumberK := NumberK + Key;
  442.    if Key = #8 then
  443.       NumberK := ' ';
  444. end;
  445.  
  446. procedure TForm2.edtPKeyPress(Sender: TObject; var Key: Char);
  447. const
  448.    Digit: set of Char = ['0' .. '9'];
  449. begin
  450.    if Key in Digit then
  451.       NumberP := NumberP + Key;
  452.    if Key = #8 then
  453.       NumberP := ' ';
  454. end;
  455.  
  456. procedure TForm2.edtXKeyPress(Sender: TObject; var Key: Char);
  457. const
  458.    Digit: set of Char = ['0' .. '9'];
  459. begin
  460.    if Key in Digit then
  461.       NumberX := NumberX + Key;
  462.    if Key = #8 then
  463.       NumberX := ' ';
  464. end;
  465.  
  466. procedure OutputSource(InputFileName: string; var Output: TBytesToPrint);
  467. var
  468.    InputBuffer: array [1 .. cBytesMax div 2] of Byte;
  469.    InputStream: TFileStream;
  470.    cBytes, i: Integer;
  471. begin
  472.    InputStream := TFileStream.Create(InputFileName, fmOpenRead);
  473.    SetLength(Output, cBytesMax div 2);
  474.    cBytes := InputStream.ReadData(InputBuffer);
  475.    if Length(Output) > 0 then
  476.    begin
  477.       Form2.sgOutput.RowCount := cBytes + 1;
  478.       i := Low(InputBuffer);
  479.       while i <= cBytes do
  480.       begin
  481.          Output[i - 1] := InputBuffer[i];
  482.          Form2.sgOutput.Cells[0, i] := inttostr(Output[i - 1]);
  483.          inc(i);
  484.       end;
  485.    end;
  486.    InputStream.Free;
  487. end;
  488.  
  489. procedure TForm2.ProcessCode(FileName: string);
  490. var
  491.    i: Integer;
  492. begin
  493.    fNameCipher := FileName;
  494.    i := Length(fNameCipher);
  495.    while fNameCipher[i] <> '.' do
  496.       Dec(i);
  497.    Insert('  CIPHER', fNameCipher, i);
  498.    fNameDecipher := fNameCipher;
  499.    Insert(' DE', fNameDecipher, pos('CIPHER', fNameDecipher));
  500. end;
  501.  
  502. procedure TForm2.ФайлClick(Sender: TObject);
  503. var
  504.    Output: TIntToPrint;
  505.    Source: TBytesToPrint;
  506.    i, j: Integer;
  507. begin
  508.    if OpenDialog.Execute then
  509.    begin
  510.       mmPlainText.Clear;
  511.       ProcessCode(OpenDialog.FileName);
  512.       OutputSource(OpenDialog.FileName, Source);
  513.       EncryptLFSR(OpenDialog.FileName, fNameCipher, Output);
  514.       if Length(Output) > 0 then
  515.       begin
  516.          sgOutput.RowCount := Length(Output) div 2 + 1;
  517.          i := Low(Output);
  518.          j := Low(Output);
  519.          while i <= High(Output) do
  520.          begin
  521.             sgOutput.Cells[1, j + 1] := inttostr(Output[i]) + ', ' +
  522.               inttostr(Output[i + 1]);
  523.             inc(i, 2);
  524.             inc(j);
  525.          end;
  526.       end;
  527.    end;
  528. end;
  529.  
  530. procedure TForm2.FormCreate(Sender: TObject);
  531. begin
  532.    NumberP := ' ';
  533.    NumberX := ' ';
  534. end;
  535.  
  536. procedure TForm2.ListBoxClick(Sender: TObject);
  537. var
  538.    i: Integer;
  539. begin
  540.    for i := 0 to ListBox.Items.Count - 1 do
  541.       if ListBox.Selected[i] then
  542.          edtG.text := ListBox.Items[i];
  543. end;
  544.  
  545. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement