SkazOff Blog

ЭЦП RSA

Перебирая архивы за прошлые годы нашел задание с 4ого кажется курса — реализация ЭЦП (RSA), выложу исходники, возможно кому-нибудь пригодится. Делал на дельфях.

Изначально судя по документам задание звучало так: «Разработать алгоритм электронной цифровой подписи на основе алгоритма. RSA. Создать подделку цифровой подписи. Проверить подлинность исходной цифровой подписи и подделки. Сделать выводы о безопасности цифровой подписи открытого текста и его целостности.»

Ну для начала что такое RSA можно почитать в википедии. Про ЭЦП на основе RSA есть тут и тут, по последней ссылке есть даже реализация, точнее фрагменты кода. Форма выглядит вот так. Последовательность действий думаю ясна:

Окно программы

1.Генерируем ключи (+делаем вывод различных переменных типа p и q, для наглядности»)

2.Вводим текст и подписываем его

3.Передаем текст

4.Проверяем текст.

 
Функция вычисления s=x^e mod n:

function PowerInMod(base, ex, modul: uint64): uint64;     
  begin
    if ex = 0 then result := 1
    else
    begin
      if ex = 1 then result := base
      else
      begin
        result := PowerInMod(base, ex div 2, modul);
        result := result * result mod modul;
        if (ex mod 2) <> 0 then result := result * base mod modul;
      end;
    end;
  end;

Получаем случайное простое число:

  function GetSimpleNumber: uint64;    
  var ok: boolean;
    i: uint64;
  begin
    ok := false;
    while not ok do
    begin
      result := random(Max) + 3;
      i := 2;
      while i <= result do
      begin
        if (result mod i) = 0 then break;
        inc(i);
      end;
      if i = result then ok := true;
    end;
  end;

Расширенный алгоритм Евклида:

function gcd_ext(a, b: int64): int64;      
  var a0, x_, v_, y_, u_, q_, r_, newu_, newv_: int64;
  begin
    a0 := a;
    x_ := 1;
    v_ := 1;
    y_ := 0;
    u_ := 0;
    while b <> 0 do
    begin
      q_ := a div b;
      r_ := a mod b;
      a := b;
      b := r_;
      newu_ := x_ - q_ * u_;
      newv_ := y_ - q_ * v_;
      x_ := u_;
      y_ := v_;
      u_ := newu_;
      v_ := newv_;
    end;
    if y_ > 0 then result := y_
    else result := y_ + a0;
  end;

NOD:

function gcd(a, b: uint64): uint64;      
  begin
    repeat
      if a > b then a := a mod b
      else b := b mod a;
    until (a = 0) or (b = 0);
    result := a + b;
  end;

Два числа взаимно простые — когда их НОД=1:

  function SimpleBetween(ValueN: uint): uint;
  var ok: boolean;
    i: int64;
  begin
    ok := false;
    i := 3;
    while not ok do
    begin
      result := i;
      inc(i);
      if gcd(result, ValueN) = 1 then ok := true;
    end;
  end;

Все расчеты:

var x, gcdval: uint64;
begin
  Memo1.Clear;
  randomize;
  //p
  p := GetSimpleNumber;
  //q
  repeat
    q := GetSimpleNumber;
  until p <> q;
  Memo1.Lines.Add('p=' + IntToStr(p));
  Memo1.Lines.Add('q=' + IntToStr(q));
  //n
  n := p * q;
  Memo1.Lines.Add('n=' + IntToStr(n));
  //fi
  fi := (p - 1) * (q - 1);
  Memo1.Lines.Add('(p-1)(q-1)=' + IntToStr(fi));
  //e
  e := SimpleBetween(fi);
  Memo1.Lines.Add('e=' + IntToStr(e));
  //расширенный алгоритм евклида
  d := gcd_ext(fi, e);
  Memo1.Lines.Add('d=' + IntToStr(d));
  if gcd(d, n) <> 1 then
  begin
    ShowMessage('d и n получились не взаимно простыми - повторите генерацию');
   { x := PowerInMod(666, e, n);
    if PowerInMod(x, d, n) = 666 then
    begin
      ShowMessage('прокатило')
    end;
    }
  end
end;

Подписываем:

var t,source:string;
    i:integer;
    res:uint64;
begin
  source := Edit1.Text;
  t:='';
  for i:=1 to length(source) do
  begin
    res := PowerInMod( Ord(source[i]) ,d,n);
    t:=t+','+IntToStr(res);
  end;
  delete(t,1,1);
  Edit3.Text := t;
end;

Проверяем подпись:

var t,source:string;
    i:integer;
    res:uint64;
    sl:TStringList;
begin
  sl := TStringList.Create;
  sl.CommaText := Edit3.Text;
  t:='';
  for i:=0 to sl.Count-1 do
  begin
    t := t + Chr(  PowerInMod( StrToInt(sl[i]) ,e,n )  );
  end;
  if t = Edit2.Text then ShowMessage('Подпись верна!')
  else ShowMessage('Подпись НЕверна!')
end;

Вот собственно и все:)

Проверка

2 комментариев

  1. Здравствуйте! а можете проект скинуть?

    1. Маловероятно, что они у меня сохранились( Если найду — вышлю

Оставить комментарий