Advertisement
Guest User

TI 3 best

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